blob: d629cb1dc2d2f40dc02c99ae243dd9482de4eb8d [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
22 b reset
23 ldr pc, _undefined_instruction
24 ldr pc, _software_interrupt
25 ldr pc, _prefetch_abort
26 ldr pc, _data_abort
27 ldr pc, _not_used
28 ldr pc, _irq
29 ldr pc, _fiq
30 .endm
31
32
33/*
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020034 *************************************************************************
35 *
36 * Symbol _start is referenced elsewhere, so make it global
37 *
38 *************************************************************************
39 */
40
41.globl _start
42
43/*
44 *************************************************************************
45 *
46 * Vectors have their own section so linker script can map them easily
47 *
48 *************************************************************************
49 */
50
Georges Savoundararadjc3810842014-10-28 23:16:10 +010051 .section ".vectors", "ax"
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020052
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020053#if defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK)
54/*
55 * Various SoCs need something special and SoC-specific up front in
56 * order to boot, allow them to set that in their boot0.h file and then
57 * use it here.
58 *
59 * To allow a boot0 hook to insert a 'special' sequence after the vector
60 * table (e.g. for the socfpga), the presence of a boot0 hook supresses
61 * the below vector table and assumes that the vector table is filled in
62 * by the boot0 hook. The requirements for a boot0 hook thus are:
63 * (1) defines '_start:' as appropriate
64 * (2) inserts the vector table using ARM_VECTORS as appropriate
65 */
66#include <asm/arch/boot0.h>
67
68#else
69
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020070/*
71 *************************************************************************
72 *
73 * Exception vectors as described in ARM reference manuals
74 *
75 * Uses indirect branch to allow reaching handlers anywhere in memory.
76 *
77 *************************************************************************
78 */
79
Benoît Thébaudeaudf66ec62014-09-03 23:32:34 +020080_start:
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020081#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
82 .word CONFIG_SYS_DV_NOR_BOOT_CFG
83#endif
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020084 ARM_VECTORS
85#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */
Andre Przywara48321ba2016-05-31 10:45:06 -070086
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020087/*
88 *************************************************************************
89 *
90 * Indirect vectors table
91 *
92 * Symbols referenced here must be defined somewhere else
93 *
94 *************************************************************************
95 */
96
97 .globl _undefined_instruction
98 .globl _software_interrupt
99 .globl _prefetch_abort
100 .globl _data_abort
101 .globl _not_used
102 .globl _irq
103 .globl _fiq
104
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200105_undefined_instruction: .word undefined_instruction
106_software_interrupt: .word software_interrupt
107_prefetch_abort: .word prefetch_abort
108_data_abort: .word data_abort
109_not_used: .word not_used
110_irq: .word irq
111_fiq: .word fiq
112
113 .balignl 16,0xdeadbeef
114
115/*
116 *************************************************************************
117 *
118 * Interrupt handling
119 *
120 *************************************************************************
121 */
122
123/* SPL interrupt handling: just hang */
124
125#ifdef CONFIG_SPL_BUILD
126
127 .align 5
128undefined_instruction:
129software_interrupt:
130prefetch_abort:
131data_abort:
132not_used:
133irq:
134fiq:
Albert ARIBAUD9852cc62014-04-15 16:13:51 +02001351:
Andrew F. Davisdf1f7e22018-06-11 14:04:17 -0500136 b 1b /* hang and never return */
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200137
138#else /* !CONFIG_SPL_BUILD */
139
140/* IRQ stack memory (calculated at run-time) + 8 bytes */
141.globl IRQ_STACK_START_IN
142IRQ_STACK_START_IN:
Lothar Waßmannedb1a3f2017-06-08 10:16:36 +0200143#ifdef IRAM_BASE_ADDR
144 .word IRAM_BASE_ADDR + 0x20
145#else
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200146 .word 0x0badc0de
Lothar Waßmannedb1a3f2017-06-08 10:16:36 +0200147#endif
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200148
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200149@
150@ IRQ stack frame.
151@
152#define S_FRAME_SIZE 72
153
154#define S_OLD_R0 68
155#define S_PSR 64
156#define S_PC 60
157#define S_LR 56
158#define S_SP 52
159
160#define S_IP 48
161#define S_FP 44
162#define S_R10 40
163#define S_R9 36
164#define S_R8 32
165#define S_R7 28
166#define S_R6 24
167#define S_R5 20
168#define S_R4 16
169#define S_R3 12
170#define S_R2 8
171#define S_R1 4
172#define S_R0 0
173
174#define MODE_SVC 0x13
175#define I_BIT 0x80
176
177/*
178 * use bad_save_user_regs for abort/prefetch/undef/swi ...
179 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
180 */
181
182 .macro bad_save_user_regs
183 @ carve out a frame on current user stack
184 sub sp, sp, #S_FRAME_SIZE
185 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
186 ldr r2, IRQ_STACK_START_IN
187 @ get values for "aborted" pc and cpsr (into parm regs)
188 ldmia r2, {r2 - r3}
189 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
190 add r5, sp, #S_SP
191 mov r1, lr
192 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
193 mov r0, sp @ save current stack into r0 (param register)
194 .endm
195
196 .macro irq_save_user_regs
197 sub sp, sp, #S_FRAME_SIZE
198 stmia sp, {r0 - r12} @ Calling r0-r12
199 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
200 add r8, sp, #S_PC
201 stmdb r8, {sp, lr}^ @ Calling SP, LR
202 str lr, [r8, #0] @ Save calling PC
203 mrs r6, spsr
204 str r6, [r8, #4] @ Save CPSR
205 str r0, [r8, #8] @ Save OLD_R0
206 mov r0, sp
207 .endm
208
209 .macro irq_restore_user_regs
210 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
211 mov r0, r0
212 ldr lr, [sp, #S_PC] @ Get PC
213 add sp, sp, #S_FRAME_SIZE
214 subs pc, lr, #4 @ return & move spsr_svc into cpsr
215 .endm
216
217 .macro get_bad_stack
218 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
219
220 str lr, [r13] @ save caller lr in position 0 of saved stack
221 mrs lr, spsr @ get the spsr
222 str lr, [r13, #4] @ save spsr in position 1 of saved stack
223 mov r13, #MODE_SVC @ prepare SVC-Mode
224 @ msr spsr_c, r13
225 msr spsr, r13 @ switch modes, make sure moves will execute
226 mov lr, pc @ capture return pc
227 movs pc, lr @ jump to next instruction & switch modes.
228 .endm
229
230 .macro get_irq_stack @ setup IRQ stack
231 ldr sp, IRQ_STACK_START
232 .endm
233
234 .macro get_fiq_stack @ setup FIQ stack
235 ldr sp, FIQ_STACK_START
236 .endm
237
238/*
239 * exception handlers
240 */
241
242 .align 5
243undefined_instruction:
244 get_bad_stack
245 bad_save_user_regs
246 bl do_undefined_instruction
247
248 .align 5
249software_interrupt:
250 get_bad_stack
251 bad_save_user_regs
252 bl do_software_interrupt
253
254 .align 5
255prefetch_abort:
256 get_bad_stack
257 bad_save_user_regs
258 bl do_prefetch_abort
259
260 .align 5
261data_abort:
262 get_bad_stack
263 bad_save_user_regs
264 bl do_data_abort
265
266 .align 5
267not_used:
268 get_bad_stack
269 bad_save_user_regs
270 bl do_not_used
271
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200272
273 .align 5
274irq:
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200275 get_bad_stack
276 bad_save_user_regs
277 bl do_irq
278
279 .align 5
280fiq:
281 get_bad_stack
282 bad_save_user_regs
283 bl do_fiq
284
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200285#endif /* CONFIG_SPL_BUILD */