blob: 8fd629a8af7ad79a40bd55bcaa32735e0606fca5 [file] [log] [blame]
Furquan Shaikh668316b2014-08-30 21:59:11 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2014 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Furquan Shaikh668316b2014-08-30 21:59:11 -070014 */
15
16/*
17 * transition_asm.S: This file handles the entry and exit from an exception
18 *
19 * Flow: exception --> exc_vectors --> exc_entry --> exc_dispatch -->
20 * exc_exit
21 * Transition Flow: transition --> trans_switch --> exc_exit
22 *
23 * |---| Exception Entry |---|
24 *
25 * On exception entry, it saves all the xregs on SP_ELx since SP_ELx is
26 * selected on entry. Some dummy pushes are performed to create space for
27 * elx_state structure. It then passes pointer to this saved set of regs and
28 * a unique id(for identifying exception) to exc_entry.
29 *
30 * |---| Exception Transition Dispatch |---|
31 *
32 * This is the C-component of exception entry. It does the work of initializing
33 * the exc_state registers. Finally it calls exception dispatch implemented by
34 * the user. This is point of no-return.
35 *
36 * |---| Exception Dispatch |---|
37 *
38 * User of this functionality is expected to implement exc_dispatch which
39 * acts as entry point for it. Once exception handling is complete, the user
40 * needs to call exc_exit with pointer to struct regs.
41 *
42 * |---| Exception Exit |---|
43 *
44 * Once exc_dispatch is done with handling the exception based on the id passed
45 * to it, it needs to call exc_exit with pointer to struct regs. This is done to
46 * unwind the exception stack by popping off all the xregs.
47 *
48 * |---| Exception Transition Exit |---|
49 *
50 * This routine makes SP_EL0 point to the regs structure passed and continues
51 * onto the exception exit routine described above. This is the reason that
52 * transition library does not handle initialization of SP_EL0 for the program
53 * to be executed.
54 */
55
56#define __ASSEMBLY__
57#include <arch/asm.h>
58#include <arch/lib_helpers.h>
59#include <arch/transition.h>
60
61.macro eentry lbl id
62 .align 7
63\lbl:
64 stp x29, x30, [sp, #STACK_PUSH_BYTES]!
65 bl exc_prologue
66 mov x1, \id
67 mov x0, sp
68 b exc_entry
69.endm
70
71/*
72 * exc_vectors: Entry point for an exception
73 */
74ENTRY_WITH_ALIGN(exc_vectors, 11)
75
Aaron Durbin4f89d972014-09-16 22:23:57 -050076eentry sync_curr_sp0, #EXC_VID_CUR_SP_EL0_SYNC
77eentry irq_curr_sp0, #EXC_VID_CUR_SP_EL0_IRQ
78eentry fiq_curr_sp0, #EXC_VID_CUR_SP_EL0_FIRQ
79eentry serror_curr_sp0, #EXC_VID_CUR_SP_EL0_SERR
80eentry sync_curr_spx, #EXC_VID_CUR_SP_ELX_SYNC
81eentry irq_curr_spx, #EXC_VID_CUR_SP_ELX_IRQ
82eentry fiq_curr_spx, #EXC_VID_CUR_SP_ELX_FIQ
83eentry serror_curr_spx, #EXC_VID_CUR_SP_ELX_SERR
84eentry sync_lower_64, #EXC_VID_LOW64_SYNC
85eentry irq_lower_64, #EXC_VID_LOW64_IRQ
86eentry fiq_lower_64, #EXC_VID_LOW64_FIQ
87eentry serror_lower_64, #EXC_VID_LOW64_SERR
88eentry sync_lower_32, #EXC_VID_LOW32_SYNC
89eentry irq_lower_32, #EXC_VID_LOW32_IRQ
90eentry fiq_lower_32, #EXC_VID_LOW32_FIQ
91eentry serror_lower_32, #EXC_VID_LOW32_SERR
Furquan Shaikh668316b2014-08-30 21:59:11 -070092
93ENDPROC(exc_vectors)
94
95ENTRY(exc_prologue)
96 stp x27, x28, [sp, #STACK_PUSH_BYTES]!
97 stp x25, x26, [sp, #STACK_PUSH_BYTES]!
98 stp x23, x24, [sp, #STACK_PUSH_BYTES]!
99 stp x21, x22, [sp, #STACK_PUSH_BYTES]!
100 stp x19, x20, [sp, #STACK_PUSH_BYTES]!
101 stp x17, x18, [sp, #STACK_PUSH_BYTES]!
102 stp x15, x16, [sp, #STACK_PUSH_BYTES]!
103 stp x13, x14, [sp, #STACK_PUSH_BYTES]!
104 stp x11, x12, [sp, #STACK_PUSH_BYTES]!
105 stp x9, x10, [sp, #STACK_PUSH_BYTES]!
106 stp x7, x8, [sp, #STACK_PUSH_BYTES]!
107 stp x5, x6, [sp, #STACK_PUSH_BYTES]!
108 stp x3, x4, [sp, #STACK_PUSH_BYTES]!
109 stp x1, x2, [sp, #STACK_PUSH_BYTES]!
110 /* xzr pushed as place holder for sp */
111 stp xzr, x0, [sp, #STACK_PUSH_BYTES]!
112 /*
113 * xzr pushed as place holder for:
114 * 1. sp_elx and elr
115 */
116 stp xzr, xzr, [sp, #STACK_PUSH_BYTES]!
117 /* 2. spsr and sp_el0 */
118 stp xzr, xzr, [sp, #STACK_PUSH_BYTES]!
119 ret
120ENDPROC(exc_prologue)
121
122/*
123 * trans_switch: Set SPSel to use SP_EL0
124 * x0 = regs structure
125 */
126ENTRY(trans_switch)
127 msr SPSel, #SPSR_USE_L
128 b exc_exit
129ENDPROC(trans_switch)
130
131/*
132 * exc_exit: Return from exception by restoring saved state of xregs
133 * x0 = regs structure
134 */
135ENTRY(exc_exit)
136 /* Unwind the stack by making sp point to regs structure */
137 mov sp, x0
138 /* Load registers x0-x30 */
139 ldp xzr, x0, [sp], #STACK_POP_BYTES
140 ldp x1, x2, [sp], #STACK_POP_BYTES
141 ldp x3, x4, [sp], #STACK_POP_BYTES
142 ldp x5, x6, [sp], #STACK_POP_BYTES
143 ldp x7, x8, [sp], #STACK_POP_BYTES
144 ldp x9, x10, [sp], #STACK_POP_BYTES
145 ldp x11, x12, [sp], #STACK_POP_BYTES
146 ldp x13, x14, [sp], #STACK_POP_BYTES
147 ldp x15, x16, [sp], #STACK_POP_BYTES
148 ldp x17, x18, [sp], #STACK_POP_BYTES
149 ldp x19, x20, [sp], #STACK_POP_BYTES
150 ldp x21, x22, [sp], #STACK_POP_BYTES
151 ldp x23, x24, [sp], #STACK_POP_BYTES
152 ldp x25, x26, [sp], #STACK_POP_BYTES
153 ldp x27, x28, [sp], #STACK_POP_BYTES
154 ldp x29, x30, [sp], #STACK_POP_BYTES
155 eret
156ENDPROC(exc_exit)
157
Julius Werner66a476a2015-10-12 16:45:21 -0700158/*
159 * exception_init_asm: Initialize VBAR and point SP_EL3 to exception stack.
160 * x0 = end of exception stack
161 */
162ENTRY(exception_init_asm)
163 msr SPSel, #SPSR_USE_H
164 mov sp, x0
165 msr SPSel, #SPSR_USE_L
166
Furquan Shaikh668316b2014-08-30 21:59:11 -0700167 adr x0, exc_vectors
168 write_current vbar, x0, x1
169 dsb sy
170 isb
171 ret
Julius Werner66a476a2015-10-12 16:45:21 -0700172ENDPROC(exception_init_asm)