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 66vectors: 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 76handler_\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 127