.section .text.vectors,"ax" .equ EXCEPTION_FRAME_SIZE, {frame_size} .equ EXCEPTION_X3_OFFSET, {x3_offset} .equ EXCEPTION_SP_OFFSET, {sp_offset} .equ EXCEPTION_CANARY_OFFSET, {canary_offset} .equ EXCEPTION_CANARY_VALUE, {canary_value} .balign 2048 .global __vectors_start __vectors_start: // Four source groups, each with synchronous, IRQ, FIQ and SError slots. .set vector_slot, 0 .rept 16 .balign 128 .if vector_slot == 9 .if {el0_irq} // Real lower-EL AArch64 IRQ: save EL0 state and ERET via // the guarded IrqContext path, not the fatal exception frame. b __user_irq_entry .endif .endif .if vector_slot == 8 .if {user_syscall} b __user_syscall_sync_entry .else .if {user_test} // First EL0 SVC experiment: SP_EL1 is the safe handler stack. b __user_first_sync_entry .endif .endif .endif .if vector_slot < 4 .if {guard_test} .if vector_slot == 0 // EL1t task fault: hardware selects the surviving SP_EL1. b __task_guard_sync_entry .else b .Lexception_park .endif .else // SP_EL0 has no dedicated exception stack in normal images. b .Lexception_park .endif .else .if {return_test} .if vector_slot == 4 // Isolated SVC/ERET test; real IRQ slots still stay fatal. b __return_sync_entry .else sub sp, sp, #EXCEPTION_FRAME_SIZE str x3, [sp, #EXCEPTION_X3_OFFSET] mov x3, #vector_slot b __exception_entry .endif .else .if {sgi_test} .if vector_slot == 5 // Isolated SGI, timer, or unknown-source experiment. b __return_irq_entry .else sub sp, sp, #EXCEPTION_FRAME_SIZE str x3, [sp, #EXCEPTION_X3_OFFSET] mov x3, #vector_slot b __exception_entry .endif .else sub sp, sp, #EXCEPTION_FRAME_SIZE str x3, [sp, #EXCEPTION_X3_OFFSET] mov x3, #vector_slot b __exception_entry .endif .endif .endif .set vector_slot, vector_slot + 1 .endr .balign 128 __exception_entry: // Save x0..x30 before using them as Rust arguments. x3 was saved in its // vector slot before it became the slot number. This is a fatal frame; // returning to the interrupted instruction is not supported yet. stp x0, x1, [sp, #0] str x2, [sp, #16] stp x4, x5, [sp, #32] stp x6, x7, [sp, #48] stp x8, x9, [sp, #64] stp x10, x11, [sp, #80] stp x12, x13, [sp, #96] stp x14, x15, [sp, #112] stp x16, x17, [sp, #128] stp x18, x19, [sp, #144] stp x20, x21, [sp, #160] stp x22, x23, [sp, #176] stp x24, x25, [sp, #192] stp x26, x27, [sp, #208] stp x28, x29, [sp, #224] str x30, [sp, #240] add x4, sp, #EXCEPTION_FRAME_SIZE str x4, [sp, #EXCEPTION_SP_OFFSET] mov x4, #EXCEPTION_CANARY_VALUE str x4, [sp, #EXCEPTION_CANARY_OFFSET] mrs x0, CurrentEL cmp x0, #4 b.eq .Lfrom_el1 cmp x0, #8 b.eq .Lfrom_el2 b .Lexception_park .Lfrom_el1: mov x0, #1 mrs x1, ESR_EL1 mrs x2, ELR_EL1 mrs x5, SPSR_EL1 mov x4, sp b kernel_exception .Lfrom_el2: mov x0, #2 mrs x1, ESR_EL2 mrs x2, ELR_EL2 mrs x5, SPSR_EL2 mov x4, sp b kernel_exception .Lexception_park: wfe b .Lexception_park