blob: 56f36815582b9e3492828e511e41fb951f33af72 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0+ */
Albert ARIBAUD9852cc62014-04-15 16:13:51 +02002/*
3 * vectors - Generic ARM exception table code
4 *
5 * Copyright (c) 1998 Dan Malek <dmalek@jlc.net>
6 * Copyright (c) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
7 * Copyright (c) 2000 Wolfgang Denk <wd@denx.de>
8 * Copyright (c) 2001 Alex Züpke <azu@sysgo.de>
9 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
10 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
11 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
12 * Copyright (c) 2002 Kyle Harris <kharris@nexus-tech.net>
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020013 */
14
Christian Riesch80c5a532014-07-07 11:07:25 +020015#include <config.h>
16
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020017/*
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020018 * A macro to allow insertion of an ARM exception vector either
19 * for the non-boot0 case or by a boot0-header.
20 */
21 .macro ARM_VECTORS
Lokesh Vutlad9805842018-08-27 15:57:10 +053022#ifdef CONFIG_ARCH_K3
23 ldr pc, _reset
24#else
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020025 b reset
Lokesh Vutlad9805842018-08-27 15:57:10 +053026#endif
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020027 ldr pc, _undefined_instruction
28 ldr pc, _software_interrupt
29 ldr pc, _prefetch_abort
30 ldr pc, _data_abort
31 ldr pc, _not_used
32 ldr pc, _irq
33 ldr pc, _fiq
34 .endm
35
36
37/*
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020038 *************************************************************************
39 *
40 * Symbol _start is referenced elsewhere, so make it global
41 *
42 *************************************************************************
43 */
44
45.globl _start
46
47/*
48 *************************************************************************
49 *
50 * Vectors have their own section so linker script can map them easily
51 *
52 *************************************************************************
53 */
54
Georges Savoundararadjc3810842014-10-28 23:16:10 +010055 .section ".vectors", "ax"
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020056
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020057#if defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK)
58/*
59 * Various SoCs need something special and SoC-specific up front in
60 * order to boot, allow them to set that in their boot0.h file and then
61 * use it here.
62 *
63 * To allow a boot0 hook to insert a 'special' sequence after the vector
64 * table (e.g. for the socfpga), the presence of a boot0 hook supresses
65 * the below vector table and assumes that the vector table is filled in
66 * by the boot0 hook. The requirements for a boot0 hook thus are:
67 * (1) defines '_start:' as appropriate
68 * (2) inserts the vector table using ARM_VECTORS as appropriate
69 */
70#include <asm/arch/boot0.h>
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020071#else
72
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020073/*
74 *************************************************************************
75 *
76 * Exception vectors as described in ARM reference manuals
77 *
78 * Uses indirect branch to allow reaching handlers anywhere in memory.
79 *
80 *************************************************************************
81 */
82
Benoît Thébaudeaudf66ec62014-09-03 23:32:34 +020083_start:
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020084#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
85 .word CONFIG_SYS_DV_NOR_BOOT_CFG
86#endif
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020087 ARM_VECTORS
88#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */
Andre Przywara48321ba2016-05-31 10:45:06 -070089
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020090/*
91 *************************************************************************
92 *
93 * Indirect vectors table
94 *
95 * Symbols referenced here must be defined somewhere else
96 *
97 *************************************************************************
98 */
99
Lokesh Vutlad9805842018-08-27 15:57:10 +0530100 .globl _reset
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200101 .globl _undefined_instruction
102 .globl _software_interrupt
103 .globl _prefetch_abort
104 .globl _data_abort
105 .globl _not_used
106 .globl _irq
107 .globl _fiq
108
Lokesh Vutlad9805842018-08-27 15:57:10 +0530109#ifdef CONFIG_ARCH_K3
110_reset: .word reset
111#endif
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200112_undefined_instruction: .word undefined_instruction
113_software_interrupt: .word software_interrupt
114_prefetch_abort: .word prefetch_abort
115_data_abort: .word data_abort
116_not_used: .word not_used
117_irq: .word irq
118_fiq: .word fiq
119
120 .balignl 16,0xdeadbeef
121
122/*
123 *************************************************************************
124 *
125 * Interrupt handling
126 *
127 *************************************************************************
128 */
129
130/* SPL interrupt handling: just hang */
131
132#ifdef CONFIG_SPL_BUILD
133
134 .align 5
135undefined_instruction:
136software_interrupt:
137prefetch_abort:
138data_abort:
139not_used:
140irq:
141fiq:
Albert ARIBAUD9852cc62014-04-15 16:13:51 +02001421:
Andrew F. Davisdf1f7e22018-06-11 14:04:17 -0500143 b 1b /* hang and never return */
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200144
145#else /* !CONFIG_SPL_BUILD */
146
147/* IRQ stack memory (calculated at run-time) + 8 bytes */
148.globl IRQ_STACK_START_IN
149IRQ_STACK_START_IN:
Lothar Waßmannedb1a3f2017-06-08 10:16:36 +0200150#ifdef IRAM_BASE_ADDR
151 .word IRAM_BASE_ADDR + 0x20
152#else
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200153 .word 0x0badc0de
Lothar Waßmannedb1a3f2017-06-08 10:16:36 +0200154#endif
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200155
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200156@
157@ IRQ stack frame.
158@
159#define S_FRAME_SIZE 72
160
161#define S_OLD_R0 68
162#define S_PSR 64
163#define S_PC 60
164#define S_LR 56
165#define S_SP 52
166
167#define S_IP 48
168#define S_FP 44
169#define S_R10 40
170#define S_R9 36
171#define S_R8 32
172#define S_R7 28
173#define S_R6 24
174#define S_R5 20
175#define S_R4 16
176#define S_R3 12
177#define S_R2 8
178#define S_R1 4
179#define S_R0 0
180
181#define MODE_SVC 0x13
182#define I_BIT 0x80
183
184/*
185 * use bad_save_user_regs for abort/prefetch/undef/swi ...
186 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
187 */
188
189 .macro bad_save_user_regs
190 @ carve out a frame on current user stack
191 sub sp, sp, #S_FRAME_SIZE
192 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
193 ldr r2, IRQ_STACK_START_IN
194 @ get values for "aborted" pc and cpsr (into parm regs)
195 ldmia r2, {r2 - r3}
196 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
197 add r5, sp, #S_SP
198 mov r1, lr
199 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
200 mov r0, sp @ save current stack into r0 (param register)
201 .endm
202
203 .macro irq_save_user_regs
204 sub sp, sp, #S_FRAME_SIZE
205 stmia sp, {r0 - r12} @ Calling r0-r12
206 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
207 add r8, sp, #S_PC
208 stmdb r8, {sp, lr}^ @ Calling SP, LR
209 str lr, [r8, #0] @ Save calling PC
210 mrs r6, spsr
211 str r6, [r8, #4] @ Save CPSR
212 str r0, [r8, #8] @ Save OLD_R0
213 mov r0, sp
214 .endm
215
216 .macro irq_restore_user_regs
217 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
218 mov r0, r0
219 ldr lr, [sp, #S_PC] @ Get PC
220 add sp, sp, #S_FRAME_SIZE
221 subs pc, lr, #4 @ return & move spsr_svc into cpsr
222 .endm
223
224 .macro get_bad_stack
225 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
226
227 str lr, [r13] @ save caller lr in position 0 of saved stack
228 mrs lr, spsr @ get the spsr
229 str lr, [r13, #4] @ save spsr in position 1 of saved stack
230 mov r13, #MODE_SVC @ prepare SVC-Mode
231 @ msr spsr_c, r13
232 msr spsr, r13 @ switch modes, make sure moves will execute
233 mov lr, pc @ capture return pc
234 movs pc, lr @ jump to next instruction & switch modes.
235 .endm
236
237 .macro get_irq_stack @ setup IRQ stack
238 ldr sp, IRQ_STACK_START
239 .endm
240
241 .macro get_fiq_stack @ setup FIQ stack
242 ldr sp, FIQ_STACK_START
243 .endm
244
245/*
246 * exception handlers
247 */
248
249 .align 5
250undefined_instruction:
251 get_bad_stack
252 bad_save_user_regs
253 bl do_undefined_instruction
254
255 .align 5
256software_interrupt:
257 get_bad_stack
258 bad_save_user_regs
259 bl do_software_interrupt
260
261 .align 5
262prefetch_abort:
263 get_bad_stack
264 bad_save_user_regs
265 bl do_prefetch_abort
266
267 .align 5
268data_abort:
269 get_bad_stack
270 bad_save_user_regs
271 bl do_data_abort
272
273 .align 5
274not_used:
275 get_bad_stack
276 bad_save_user_regs
277 bl do_not_used
278
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200279
280 .align 5
281irq:
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200282 get_bad_stack
283 bad_save_user_regs
284 bl do_irq
285
286 .align 5
287fiq:
288 get_bad_stack
289 bad_save_user_regs
290 bl do_fiq
291
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200292#endif /* CONFIG_SPL_BUILD */