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 | |