|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | +.macro save_registers |
| 3 | + add sp, sp, #-16 * 17 |
| 4 | + |
| 5 | + stp x0, x1, [sp, #16 * 0] |
| 6 | + stp x2, x3, [sp, #16 * 1] |
| 7 | + stp x4, x5, [sp, #16 * 2] |
| 8 | + stp x6, x7, [sp, #16 * 3] |
| 9 | + stp x8, x9, [sp, #16 * 4] |
| 10 | + stp x10, x11, [sp, #16 * 5] |
| 11 | + stp x12, x13, [sp, #16 * 6] |
| 12 | + stp x14, x15, [sp, #16 * 7] |
| 13 | + stp x16, x17, [sp, #16 * 8] |
| 14 | + stp x18, x19, [sp, #16 * 9] |
| 15 | + stp x20, x21, [sp, #16 * 10] |
| 16 | + stp x22, x23, [sp, #16 * 11] |
| 17 | + stp x24, x25, [sp, #16 * 12] |
| 18 | + stp x26, x27, [sp, #16 * 13] |
| 19 | + stp x28, x29, [sp, #16 * 14] |
| 20 | + |
| 21 | + /* |
| 22 | + * This stores sp_el1 into ex_regs.sp so exception handlers can "look" |
| 23 | + * at it. It will _not_ be used to restore the sp on return from the |
| 24 | + * exception so handlers can not update it. |
| 25 | + */ |
| 26 | + add x1, sp, #16 * 17 |
| 27 | + stp x30, x1, [sp, #16 * 15] /* x30, SP */ |
| 28 | + |
| 29 | + mrs x1, elr_el1 |
| 30 | + mrs x2, spsr_el1 |
| 31 | + stp x1, x2, [sp, #16 * 16] /* PC, PSTATE */ |
| 32 | +.endm |
| 33 | + |
| 34 | +.macro restore_registers |
| 35 | + ldp x1, x2, [sp, #16 * 16] /* PC, PSTATE */ |
| 36 | + msr elr_el1, x1 |
| 37 | + msr spsr_el1, x2 |
| 38 | + |
| 39 | + /* sp is not restored */ |
| 40 | + ldp x30, xzr, [sp, #16 * 15] /* x30, SP */ |
| 41 | + |
| 42 | + ldp x28, x29, [sp, #16 * 14] |
| 43 | + ldp x26, x27, [sp, #16 * 13] |
| 44 | + ldp x24, x25, [sp, #16 * 12] |
| 45 | + ldp x22, x23, [sp, #16 * 11] |
| 46 | + ldp x20, x21, [sp, #16 * 10] |
| 47 | + ldp x18, x19, [sp, #16 * 9] |
| 48 | + ldp x16, x17, [sp, #16 * 8] |
| 49 | + ldp x14, x15, [sp, #16 * 7] |
| 50 | + ldp x12, x13, [sp, #16 * 6] |
| 51 | + ldp x10, x11, [sp, #16 * 5] |
| 52 | + ldp x8, x9, [sp, #16 * 4] |
| 53 | + ldp x6, x7, [sp, #16 * 3] |
| 54 | + ldp x4, x5, [sp, #16 * 2] |
| 55 | + ldp x2, x3, [sp, #16 * 1] |
| 56 | + ldp x0, x1, [sp, #16 * 0] |
| 57 | + |
| 58 | + add sp, sp, #16 * 17 |
| 59 | + |
| 60 | + eret |
| 61 | +.endm |
| 62 | + |
| 63 | +.pushsection ".entry.text", "ax" |
| 64 | +.balign 0x800 |
| 65 | +.global vectors |
| 66 | +vectors: |
| 67 | +.popsection |
| 68 | + |
| 69 | +.set vector, 0 |
| 70 | + |
| 71 | +/* |
| 72 | + * Build an exception handler for vector and append a jump to it into |
| 73 | + * vectors (while making sure that it's 0x80 aligned). |
| 74 | + */ |
| 75 | +.macro HANDLER, label |
| 76 | +handler_\label: |
| 77 | + save_registers |
| 78 | + mov x0, sp |
| 79 | + mov x1, #vector |
| 80 | + bl route_exception |
| 81 | + restore_registers |
| 82 | + |
| 83 | +.pushsection ".entry.text", "ax" |
| 84 | +.balign 0x80 |
| 85 | + b handler_\label |
| 86 | +.popsection |
| 87 | + |
| 88 | +.set vector, vector + 1 |
| 89 | +.endm |
| 90 | + |
| 91 | +.macro HANDLER_INVALID |
| 92 | +.pushsection ".entry.text", "ax" |
| 93 | +.balign 0x80 |
| 94 | +/* This will abort so no need to save and restore registers. */ |
| 95 | + mov x0, #vector |
| 96 | + mov x1, #0 /* ec */ |
| 97 | + mov x2, #0 /* valid_ec */ |
| 98 | + b kvm_exit_unexpected_exception |
| 99 | +.popsection |
| 100 | + |
| 101 | +.set vector, vector + 1 |
| 102 | +.endm |
| 103 | + |
| 104 | +/* |
| 105 | + * Caution: be sure to not add anything between the declaration of vectors |
| 106 | + * above and these macro calls that will build the vectors table below it. |
| 107 | + */ |
| 108 | + HANDLER_INVALID // Synchronous EL1t |
| 109 | + HANDLER_INVALID // IRQ EL1t |
| 110 | + HANDLER_INVALID // FIQ EL1t |
| 111 | + HANDLER_INVALID // Error EL1t |
| 112 | + |
| 113 | + HANDLER el1h_sync // Synchronous EL1h |
| 114 | + HANDLER el1h_irq // IRQ EL1h |
| 115 | + HANDLER el1h_fiq // FIQ EL1h |
| 116 | + HANDLER el1h_error // Error EL1h |
| 117 | + |
| 118 | + HANDLER el0_sync_64 // Synchronous 64-bit EL0 |
| 119 | + HANDLER el0_irq_64 // IRQ 64-bit EL0 |
| 120 | + HANDLER el0_fiq_64 // FIQ 64-bit EL0 |
| 121 | + HANDLER el0_error_64 // Error 64-bit EL0 |
| 122 | + |
| 123 | + HANDLER el0_sync_32 // Synchronous 32-bit EL0 |
| 124 | + HANDLER el0_irq_32 // IRQ 32-bit EL0 |
| 125 | + HANDLER el0_fiq_32 // FIQ 32-bit EL0 |
| 126 | + HANDLER el0_error_32 // Error 32-bit EL0 |
0 commit comments