/* SPDX-License-Identifier: GPL-2.0 */ .macro save_registers add sp, sp, #-16 * 17 stp x0, x1, [sp, #16 * 0] stp x2, x3, [sp, #16 * 1] stp x4, x5, [sp, #16 * 2] stp x6, x7, [sp, #16 * 3] stp x8, x9, [sp, #16 * 4] stp x10, x11, [sp, #16 * 5] stp x12, x13, [sp, #16 * 6] stp x14, x15, [sp, #16 * 7] stp x16, x17, [sp, #16 * 8] stp x18, x19, [sp, #16 * 9] stp x20, x21, [sp, #16 * 10] stp x22, x23, [sp, #16 * 11] stp x24, x25, [sp, #16 * 12] stp x26, x27, [sp, #16 * 13] stp x28, x29, [sp, #16 * 14] /* * This stores sp_el1 into ex_regs.sp so exception handlers can "look" * at it. It will _not_ be used to restore the sp on return from the * exception so handlers can not update it. */ add x1, sp, #16 * 17 stp x30, x1, [sp, #16 * 15] /* x30, SP */ mrs x1, elr_el1 mrs x2, spsr_el1 stp x1, x2, [sp, #16 * 16] /* PC, PSTATE */ .endm .macro restore_registers ldp x1, x2, [sp, #16 * 16] /* PC, PSTATE */ msr elr_el1, x1 msr spsr_el1, x2 /* sp is not restored */ ldp x30, xzr, [sp, #16 * 15] /* x30, SP */ ldp x28, x29, [sp, #16 * 14] ldp x26, x27, [sp, #16 * 13] ldp x24, x25, [sp, #16 * 12] ldp x22, x23, [sp, #16 * 11] ldp x20, x21, [sp, #16 * 10] ldp x18, x19, [sp, #16 * 9] ldp x16, x17, [sp, #16 * 8] ldp x14, x15, [sp, #16 * 7] ldp x12, x13, [sp, #16 * 6] ldp x10, x11, [sp, #16 * 5] ldp x8, x9, [sp, #16 * 4] ldp x6, x7, [sp, #16 * 3] ldp x4, x5, [sp, #16 * 2] ldp x2, x3, [sp, #16 * 1] ldp x0, x1, [sp, #16 * 0] add sp, sp, #16 * 17 eret .endm .pushsection ".entry.text", "ax" .balign 0x800 .global vectors vectors: .popsection .set vector, 0 /* * Build an exception handler for vector and append a jump to it into * vectors (while making sure that it's 0x80 aligned). */ .macro HANDLER, label handler_\label: save_registers mov x0, sp mov x1, #vector bl route_exception restore_registers .pushsection ".entry.text", "ax" .balign 0x80 b handler_\label .popsection .set vector, vector + 1 .endm .macro HANDLER_INVALID .pushsection ".entry.text", "ax" .balign 0x80 /* This will abort so no need to save and restore registers. */ mov x0, #vector mov x1, #0 /* ec */ mov x2, #0 /* valid_ec */ b kvm_exit_unexpected_exception .popsection .set vector, vector + 1 .endm /* * Caution: be sure to not add anything between the declaration of vectors * above and these macro calls that will build the vectors table below it. */ HANDLER_INVALID // Synchronous EL1t HANDLER_INVALID // IRQ EL1t HANDLER_INVALID // FIQ EL1t HANDLER_INVALID // Error EL1t HANDLER el1h_sync // Synchronous EL1h HANDLER el1h_irq // IRQ EL1h HANDLER el1h_fiq // FIQ EL1h HANDLER el1h_error // Error EL1h HANDLER el0_sync_64 // Synchronous 64-bit EL0 HANDLER el0_irq_64 // IRQ 64-bit EL0 HANDLER el0_fiq_64 // FIQ 64-bit EL0 HANDLER el0_error_64 // Error 64-bit EL0 HANDLER el0_sync_32 // Synchronous 32-bit EL0 HANDLER el0_irq_32 // IRQ 32-bit EL0 HANDLER el0_fiq_32 // FIQ 32-bit EL0 HANDLER el0_error_32 // Error 32-bit EL0