blob: e6538eff43360f9118af07c4163b154cfad66ecd [file] [log] [blame]
Albert ARIBAUD41623c92014-04-15 16:13:51 +02001/*
2 * vectors - Generic ARM exception table code
3 *
4 * Copyright (c) 1998 Dan Malek <dmalek@jlc.net>
5 * Copyright (c) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
6 * Copyright (c) 2000 Wolfgang Denk <wd@denx.de>
7 * Copyright (c) 2001 Alex Züpke <azu@sysgo.de>
8 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
9 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
10 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
11 * Copyright (c) 2002 Kyle Harris <kharris@nexus-tech.net>
12 *
13 * SPDX-License-Identifier: GPL-2.0+
14 */
15
16/*
17 *************************************************************************
18 *
19 * Symbol _start is referenced elsewhere, so make it global
20 *
21 *************************************************************************
22 */
23
24.globl _start
25
26/*
27 *************************************************************************
28 *
29 * Vectors have their own section so linker script can map them easily
30 *
31 *************************************************************************
32 */
33
34 .section ".vectors", "x"
35
36/*
37 *************************************************************************
38 *
39 * Exception vectors as described in ARM reference manuals
40 *
41 * Uses indirect branch to allow reaching handlers anywhere in memory.
42 *
43 *************************************************************************
44 */
45
Albert ARIBAUD41623c92014-04-15 16:13:51 +020046#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
47 .word CONFIG_SYS_DV_NOR_BOOT_CFG
48#endif
49
50_start:
51 ldr pc, _reset
52 ldr pc, _undefined_instruction
53 ldr pc, _software_interrupt
54 ldr pc, _prefetch_abort
55 ldr pc, _data_abort
56 ldr pc, _not_used
57 ldr pc, _irq
58 ldr pc, _fiq
59
60/*
61 *************************************************************************
62 *
63 * Indirect vectors table
64 *
65 * Symbols referenced here must be defined somewhere else
66 *
67 *************************************************************************
68 */
69
70 .globl _undefined_instruction
71 .globl _software_interrupt
72 .globl _prefetch_abort
73 .globl _data_abort
74 .globl _not_used
75 .globl _irq
76 .globl _fiq
77
78_reset: .word reset
79_undefined_instruction: .word undefined_instruction
80_software_interrupt: .word software_interrupt
81_prefetch_abort: .word prefetch_abort
82_data_abort: .word data_abort
83_not_used: .word not_used
84_irq: .word irq
85_fiq: .word fiq
86
87 .balignl 16,0xdeadbeef
88
89/*
90 *************************************************************************
91 *
92 * Interrupt handling
93 *
94 *************************************************************************
95 */
96
97/* SPL interrupt handling: just hang */
98
99#ifdef CONFIG_SPL_BUILD
100
101 .align 5
102undefined_instruction:
103software_interrupt:
104prefetch_abort:
105data_abort:
106not_used:
107irq:
108fiq:
109
1101:
111 bl 1b /* hang and never return */
112
113#else /* !CONFIG_SPL_BUILD */
114
115/* IRQ stack memory (calculated at run-time) + 8 bytes */
116.globl IRQ_STACK_START_IN
117IRQ_STACK_START_IN:
118 .word 0x0badc0de
119
120#ifdef CONFIG_USE_IRQ
121/* IRQ stack memory (calculated at run-time) */
122.globl IRQ_STACK_START
123IRQ_STACK_START:
124 .word 0x0badc0de
125
126/* IRQ stack memory (calculated at run-time) */
127.globl FIQ_STACK_START
128FIQ_STACK_START:
129 .word 0x0badc0de
130
131#endif /* CONFIG_USE_IRQ */
132
133@
134@ IRQ stack frame.
135@
136#define S_FRAME_SIZE 72
137
138#define S_OLD_R0 68
139#define S_PSR 64
140#define S_PC 60
141#define S_LR 56
142#define S_SP 52
143
144#define S_IP 48
145#define S_FP 44
146#define S_R10 40
147#define S_R9 36
148#define S_R8 32
149#define S_R7 28
150#define S_R6 24
151#define S_R5 20
152#define S_R4 16
153#define S_R3 12
154#define S_R2 8
155#define S_R1 4
156#define S_R0 0
157
158#define MODE_SVC 0x13
159#define I_BIT 0x80
160
161/*
162 * use bad_save_user_regs for abort/prefetch/undef/swi ...
163 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
164 */
165
166 .macro bad_save_user_regs
167 @ carve out a frame on current user stack
168 sub sp, sp, #S_FRAME_SIZE
169 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
170 ldr r2, IRQ_STACK_START_IN
171 @ get values for "aborted" pc and cpsr (into parm regs)
172 ldmia r2, {r2 - r3}
173 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
174 add r5, sp, #S_SP
175 mov r1, lr
176 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
177 mov r0, sp @ save current stack into r0 (param register)
178 .endm
179
180 .macro irq_save_user_regs
181 sub sp, sp, #S_FRAME_SIZE
182 stmia sp, {r0 - r12} @ Calling r0-r12
183 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
184 add r8, sp, #S_PC
185 stmdb r8, {sp, lr}^ @ Calling SP, LR
186 str lr, [r8, #0] @ Save calling PC
187 mrs r6, spsr
188 str r6, [r8, #4] @ Save CPSR
189 str r0, [r8, #8] @ Save OLD_R0
190 mov r0, sp
191 .endm
192
193 .macro irq_restore_user_regs
194 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
195 mov r0, r0
196 ldr lr, [sp, #S_PC] @ Get PC
197 add sp, sp, #S_FRAME_SIZE
198 subs pc, lr, #4 @ return & move spsr_svc into cpsr
199 .endm
200
201 .macro get_bad_stack
202 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
203
204 str lr, [r13] @ save caller lr in position 0 of saved stack
205 mrs lr, spsr @ get the spsr
206 str lr, [r13, #4] @ save spsr in position 1 of saved stack
207 mov r13, #MODE_SVC @ prepare SVC-Mode
208 @ msr spsr_c, r13
209 msr spsr, r13 @ switch modes, make sure moves will execute
210 mov lr, pc @ capture return pc
211 movs pc, lr @ jump to next instruction & switch modes.
212 .endm
213
214 .macro get_irq_stack @ setup IRQ stack
215 ldr sp, IRQ_STACK_START
216 .endm
217
218 .macro get_fiq_stack @ setup FIQ stack
219 ldr sp, FIQ_STACK_START
220 .endm
221
222/*
223 * exception handlers
224 */
225
226 .align 5
227undefined_instruction:
228 get_bad_stack
229 bad_save_user_regs
230 bl do_undefined_instruction
231
232 .align 5
233software_interrupt:
234 get_bad_stack
235 bad_save_user_regs
236 bl do_software_interrupt
237
238 .align 5
239prefetch_abort:
240 get_bad_stack
241 bad_save_user_regs
242 bl do_prefetch_abort
243
244 .align 5
245data_abort:
246 get_bad_stack
247 bad_save_user_regs
248 bl do_data_abort
249
250 .align 5
251not_used:
252 get_bad_stack
253 bad_save_user_regs
254 bl do_not_used
255
256#ifdef CONFIG_USE_IRQ
257
258 .align 5
259irq:
260 get_irq_stack
261 irq_save_user_regs
262 bl do_irq
263 irq_restore_user_regs
264
265 .align 5
266fiq:
267 get_fiq_stack
268 /* someone ought to write a more effiction fiq_save_user_regs */
269 irq_save_user_regs
270 bl do_fiq
271 irq_restore_user_regs
272
273#else
274
275 .align 5
276irq:
277 get_bad_stack
278 bad_save_user_regs
279 bl do_irq
280
281 .align 5
282fiq:
283 get_bad_stack
284 bad_save_user_regs
285 bl do_fiq
286
287#endif /* CONFIG_USE_IRQ */
288
289#endif /* CONFIG_SPL_BUILD */