blob: 73a6fb6c04a46360ba734f7888fe524e0538fb77 [file] [log] [blame]
Patrick Georgi0a3d4e02020-03-04 14:39:09 +01001/* SPDX-License-Identifier: GPL-2.0-only */
Furquan Shaikh668316b2014-08-30 21:59:11 -07002
3/*
4 * transition_asm.S: This file handles the entry and exit from an exception
5 *
6 * Flow: exception --> exc_vectors --> exc_entry --> exc_dispatch -->
7 * exc_exit
8 * Transition Flow: transition --> trans_switch --> exc_exit
9 *
10 * |---| Exception Entry |---|
11 *
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.
16 *
17 * |---| Exception Transition Dispatch |---|
18 *
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.
22 *
23 * |---| Exception Dispatch |---|
24 *
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.
28 *
29 * |---| Exception Exit |---|
30 *
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.
34 *
35 * |---| Exception Transition Exit |---|
36 *
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
40 * to be executed.
41 */
42
Furquan Shaikh668316b2014-08-30 21:59:11 -070043#include <arch/asm.h>
44#include <arch/lib_helpers.h>
45#include <arch/transition.h>
46
47.macro eentry lbl id
48 .align 7
49\lbl:
50 stp x29, x30, [sp, #STACK_PUSH_BYTES]!
51 bl exc_prologue
52 mov x1, \id
53 mov x0, sp
54 b exc_entry
55.endm
56
57/*
58 * exc_vectors: Entry point for an exception
59 */
60ENTRY_WITH_ALIGN(exc_vectors, 11)
61
Aaron Durbin4f89d972014-09-16 22:23:57 -050062eentry sync_curr_sp0, #EXC_VID_CUR_SP_EL0_SYNC
63eentry irq_curr_sp0, #EXC_VID_CUR_SP_EL0_IRQ
64eentry fiq_curr_sp0, #EXC_VID_CUR_SP_EL0_FIRQ
65eentry serror_curr_sp0, #EXC_VID_CUR_SP_EL0_SERR
66eentry sync_curr_spx, #EXC_VID_CUR_SP_ELX_SYNC
67eentry irq_curr_spx, #EXC_VID_CUR_SP_ELX_IRQ
68eentry fiq_curr_spx, #EXC_VID_CUR_SP_ELX_FIQ
69eentry serror_curr_spx, #EXC_VID_CUR_SP_ELX_SERR
70eentry sync_lower_64, #EXC_VID_LOW64_SYNC
71eentry irq_lower_64, #EXC_VID_LOW64_IRQ
72eentry fiq_lower_64, #EXC_VID_LOW64_FIQ
73eentry serror_lower_64, #EXC_VID_LOW64_SERR
74eentry sync_lower_32, #EXC_VID_LOW32_SYNC
75eentry irq_lower_32, #EXC_VID_LOW32_IRQ
76eentry fiq_lower_32, #EXC_VID_LOW32_FIQ
77eentry serror_lower_32, #EXC_VID_LOW32_SERR
Furquan Shaikh668316b2014-08-30 21:59:11 -070078
79ENDPROC(exc_vectors)
80
81ENTRY(exc_prologue)
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]!
98 /*
99 * xzr pushed as place holder for:
100 * 1. sp_elx and elr
101 */
102 stp xzr, xzr, [sp, #STACK_PUSH_BYTES]!
103 /* 2. spsr and sp_el0 */
104 stp xzr, xzr, [sp, #STACK_PUSH_BYTES]!
105 ret
106ENDPROC(exc_prologue)
107
108/*
109 * trans_switch: Set SPSel to use SP_EL0
110 * x0 = regs structure
111 */
112ENTRY(trans_switch)
Elyes HAOUAS6b727872016-09-03 08:28:48 +0200113 msr SPSel, #SPSR_USE_L
114 b exc_exit
Furquan Shaikh668316b2014-08-30 21:59:11 -0700115ENDPROC(trans_switch)
116
117/*
118 * exc_exit: Return from exception by restoring saved state of xregs
119 * x0 = regs structure
120 */
121ENTRY(exc_exit)
122 /* Unwind the stack by making sp point to regs structure */
123 mov sp, x0
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
141 eret
142ENDPROC(exc_exit)
143
Julius Werner66a476a2015-10-12 16:45:21 -0700144/*
145 * exception_init_asm: Initialize VBAR and point SP_EL3 to exception stack.
Julius Wernerbb345ab2019-12-03 22:47:01 -0800146 * Also unmask aborts now that we can report them. x0 = end of exception stack
Julius Werner66a476a2015-10-12 16:45:21 -0700147 */
148ENTRY(exception_init_asm)
149 msr SPSel, #SPSR_USE_H
150 mov sp, x0
151 msr SPSel, #SPSR_USE_L
152
Furquan Shaikh668316b2014-08-30 21:59:11 -0700153 adr x0, exc_vectors
Julius Werner0c5f61a2018-08-03 17:14:45 -0700154 msr vbar_el3, x0
Julius Wernerbb345ab2019-12-03 22:47:01 -0800155
156 msr DAIFClr, #0xf
157
Furquan Shaikh668316b2014-08-30 21:59:11 -0700158 dsb sy
159 isb
160 ret
Julius Werner66a476a2015-10-12 16:45:21 -0700161ENDPROC(exception_init_asm)