| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | /* |
| 3 | * Copyright (C) 2020 Google LLC |
| 4 | */ |
| 5 | |
| 6 | #include <linux/linkage.h> |
| 7 | #include <asm/assembler.h> |
| 8 | |
| 9 | /* |
| 10 | * Report a tag mismatch detected by tag-based KASAN. |
| 11 | * |
| 12 | * A compiler-generated thunk calls this with a non-AAPCS calling |
| 13 | * convention. Upon entry to this function, registers are as follows: |
| 14 | * |
| 15 | * x0: fault address (see below for restore) |
| 16 | * x1: fault description (see below for restore) |
| 17 | * x2 to x15: callee-saved |
| 18 | * x16 to x17: safe to clobber |
| 19 | * x18 to x30: callee-saved |
| 20 | * sp: pre-decremented by 256 bytes (see below for restore) |
| 21 | * |
| 22 | * The caller has decremented the SP by 256 bytes, and created a |
| 23 | * structure on the stack as follows: |
| 24 | * |
| 25 | * sp + 0..15: x0 and x1 to be restored |
| 26 | * sp + 16..231: free for use |
| 27 | * sp + 232..247: x29 and x30 (same as in GPRs) |
| 28 | * sp + 248..255: free for use |
| 29 | * |
| 30 | * Note that this is not a struct pt_regs. |
| 31 | * |
| 32 | * To call a regular AAPCS function we must save x2 to x15 (which we can |
| 33 | * store in the gaps), and create a frame record (for which we can use |
| 34 | * x29 and x30 spilled by the caller as those match the GPRs). |
| 35 | * |
| 36 | * The caller expects x0 and x1 to be restored from the structure, and |
| 37 | * for the structure to be removed from the stack (i.e. the SP must be |
| 38 | * incremented by 256 prior to return). |
| 39 | */ |
| 40 | SYM_CODE_START(__hwasan_tag_mismatch) |
| 41 | bti c |
| 42 | add x29, sp, #232 |
| 43 | stp x2, x3, [sp, #8 * 2] |
| 44 | stp x4, x5, [sp, #8 * 4] |
| 45 | stp x6, x7, [sp, #8 * 6] |
| 46 | stp x8, x9, [sp, #8 * 8] |
| 47 | stp x10, x11, [sp, #8 * 10] |
| 48 | stp x12, x13, [sp, #8 * 12] |
| 49 | stp x14, x15, [sp, #8 * 14] |
| 50 | #ifndef CONFIG_SHADOW_CALL_STACK |
| 51 | str x18, [sp, #8 * 18] |
| 52 | #endif |
| 53 | |
| 54 | mov x2, x30 |
| 55 | bl kasan_tag_mismatch |
| 56 | |
| 57 | ldp x0, x1, [sp] |
| 58 | ldp x2, x3, [sp, #8 * 2] |
| 59 | ldp x4, x5, [sp, #8 * 4] |
| 60 | ldp x6, x7, [sp, #8 * 6] |
| 61 | ldp x8, x9, [sp, #8 * 8] |
| 62 | ldp x10, x11, [sp, #8 * 10] |
| 63 | ldp x12, x13, [sp, #8 * 12] |
| 64 | ldp x14, x15, [sp, #8 * 14] |
| 65 | #ifndef CONFIG_SHADOW_CALL_STACK |
| 66 | ldr x18, [sp, #8 * 18] |
| 67 | #endif |
| 68 | ldp x29, x30, [sp, #8 * 29] |
| 69 | |
| 70 | /* remove the structure from the stack */ |
| 71 | add sp, sp, #256 |
| 72 | ret |
| 73 | SYM_CODE_END(__hwasan_tag_mismatch) |
| 74 | EXPORT_SYMBOL(__hwasan_tag_mismatch) |
| 75 | |