1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * transition_asm.S: This file handles the entry and exit from an exception
6 * Flow: exception --> exc_vectors --> exc_entry --> exc_dispatch -->
8 * Transition Flow: transition --> trans_switch --> exc_exit
10 * |---| Exception Entry |---|
12 * On exception entry, it saves all the xregs on SP_ELx since SP_ELx is
13 * selected on entry. Some dummy pushes are performed to create space for
14 * elx_state structure. It then passes pointer to this saved set of regs and
15 * a unique id(for identifying exception) to exc_entry.
17 * |---| Exception Transition Dispatch |---|
19 * This is the C-component of exception entry. It does the work of initializing
20 * the exc_state registers. Finally it calls exception dispatch implemented by
21 * the user. This is point of no-return.
23 * |---| Exception Dispatch |---|
25 * User of this functionality is expected to implement exc_dispatch which
26 * acts as entry point for it. Once exception handling is complete, the user
27 * needs to call exc_exit with pointer to struct regs.
29 * |---| Exception Exit |---|
31 * Once exc_dispatch is done with handling the exception based on the id passed
32 * to it, it needs to call exc_exit with pointer to struct regs. This is done to
33 * unwind the exception stack by popping off all the xregs.
35 * |---| Exception Transition Exit |---|
37 * This routine makes SP_EL0 point to the regs structure passed and continues
38 * onto the exception exit routine described above. This is the reason that
39 * transition library does not handle initialization of SP_EL0 for the program
44 #include <arch/lib_helpers.h>
45 #include <arch/transition.h>
50 stp x29, x30, [sp, #STACK_PUSH_BYTES]!
58 * exc_vectors: Entry point for an exception
60 ENTRY_WITH_ALIGN(exc_vectors, 11)
62 eentry sync_curr_sp0, #EXC_VID_CUR_SP_EL0_SYNC
63 eentry irq_curr_sp0, #EXC_VID_CUR_SP_EL0_IRQ
64 eentry fiq_curr_sp0, #EXC_VID_CUR_SP_EL0_FIRQ
65 eentry serror_curr_sp0, #EXC_VID_CUR_SP_EL0_SERR
66 eentry sync_curr_spx, #EXC_VID_CUR_SP_ELX_SYNC
67 eentry irq_curr_spx, #EXC_VID_CUR_SP_ELX_IRQ
68 eentry fiq_curr_spx, #EXC_VID_CUR_SP_ELX_FIQ
69 eentry serror_curr_spx, #EXC_VID_CUR_SP_ELX_SERR
70 eentry sync_lower_64, #EXC_VID_LOW64_SYNC
71 eentry irq_lower_64, #EXC_VID_LOW64_IRQ
72 eentry fiq_lower_64, #EXC_VID_LOW64_FIQ
73 eentry serror_lower_64, #EXC_VID_LOW64_SERR
74 eentry sync_lower_32, #EXC_VID_LOW32_SYNC
75 eentry irq_lower_32, #EXC_VID_LOW32_IRQ
76 eentry fiq_lower_32, #EXC_VID_LOW32_FIQ
77 eentry serror_lower_32, #EXC_VID_LOW32_SERR
82 stp x27, x28, [sp, #STACK_PUSH_BYTES]!
83 stp x25, x26, [sp, #STACK_PUSH_BYTES]!
84 stp x23, x24, [sp, #STACK_PUSH_BYTES]!
85 stp x21, x22, [sp, #STACK_PUSH_BYTES]!
86 stp x19, x20, [sp, #STACK_PUSH_BYTES]!
87 stp x17, x18, [sp, #STACK_PUSH_BYTES]!
88 stp x15, x16, [sp, #STACK_PUSH_BYTES]!
89 stp x13, x14, [sp, #STACK_PUSH_BYTES]!
90 stp x11, x12, [sp, #STACK_PUSH_BYTES]!
91 stp x9, x10, [sp, #STACK_PUSH_BYTES]!
92 stp x7, x8, [sp, #STACK_PUSH_BYTES]!
93 stp x5, x6, [sp, #STACK_PUSH_BYTES]!
94 stp x3, x4, [sp, #STACK_PUSH_BYTES]!
95 stp x1, x2, [sp, #STACK_PUSH_BYTES]!
96 /* xzr pushed as place holder for sp */
97 stp xzr, x0, [sp, #STACK_PUSH_BYTES]!
99 * xzr pushed as place holder for:
102 stp xzr, xzr, [sp, #STACK_PUSH_BYTES]!
103 /* 2. spsr and sp_el0 */
104 stp xzr, xzr, [sp, #STACK_PUSH_BYTES]!
106 ENDPROC(exc_prologue)
109 * trans_switch: Set SPSel to use SP_EL0
110 * x0 = regs structure
113 msr SPSel, #SPSR_USE_L
115 ENDPROC(trans_switch)
118 * exc_exit: Return from exception by restoring saved state of xregs
119 * x0 = regs structure
122 /* Unwind the stack by making sp point to regs structure */
124 /* Load registers x0-x30 */
125 ldp xzr, x0, [sp], #STACK_POP_BYTES
126 ldp x1, x2, [sp], #STACK_POP_BYTES
127 ldp x3, x4, [sp], #STACK_POP_BYTES
128 ldp x5, x6, [sp], #STACK_POP_BYTES
129 ldp x7, x8, [sp], #STACK_POP_BYTES
130 ldp x9, x10, [sp], #STACK_POP_BYTES
131 ldp x11, x12, [sp], #STACK_POP_BYTES
132 ldp x13, x14, [sp], #STACK_POP_BYTES
133 ldp x15, x16, [sp], #STACK_POP_BYTES
134 ldp x17, x18, [sp], #STACK_POP_BYTES
135 ldp x19, x20, [sp], #STACK_POP_BYTES
136 ldp x21, x22, [sp], #STACK_POP_BYTES
137 ldp x23, x24, [sp], #STACK_POP_BYTES
138 ldp x25, x26, [sp], #STACK_POP_BYTES
139 ldp x27, x28, [sp], #STACK_POP_BYTES
140 ldp x29, x30, [sp], #STACK_POP_BYTES
145 * exception_init_asm: Initialize VBAR and point SP_ELx to exception stack.
146 * Also unmask aborts now that we can report them. x0 = end of exception stack
148 ENTRY(exception_init_asm)
149 msr SPSel, #SPSR_USE_H
151 msr SPSel, #SPSR_USE_L
153 msr CURRENT_EL(vbar), x0
158 ENDPROC(exception_init_asm)