blob: 20f485142ef55c2d998eea59ec39fb836acef633 [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 */
Kever Yangb8c82e02019-03-28 11:01:22 +080070#ifdef CONFIG_ARCH_ROCKCHIP
71#include <asm/arch-rockchip/boot0.h>
72#else
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020073#include <asm/arch/boot0.h>
Kever Yangb8c82e02019-03-28 11:01:22 +080074#endif
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020075#else
76
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020077/*
78 *************************************************************************
79 *
80 * Exception vectors as described in ARM reference manuals
81 *
82 * Uses indirect branch to allow reaching handlers anywhere in memory.
83 *
84 *************************************************************************
85 */
86
Benoît Thébaudeaudf66ec62014-09-03 23:32:34 +020087_start:
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020088#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
89 .word CONFIG_SYS_DV_NOR_BOOT_CFG
90#endif
Philipp Tomsichcc00f0e2017-10-10 16:21:01 +020091 ARM_VECTORS
92#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */
Andre Przywara48321ba2016-05-31 10:45:06 -070093
Albert ARIBAUD9852cc62014-04-15 16:13:51 +020094/*
95 *************************************************************************
96 *
97 * Indirect vectors table
98 *
99 * Symbols referenced here must be defined somewhere else
100 *
101 *************************************************************************
102 */
103
Lokesh Vutlad9805842018-08-27 15:57:10 +0530104 .globl _reset
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200105 .globl _undefined_instruction
106 .globl _software_interrupt
107 .globl _prefetch_abort
108 .globl _data_abort
109 .globl _not_used
110 .globl _irq
111 .globl _fiq
112
Lokesh Vutlad9805842018-08-27 15:57:10 +0530113#ifdef CONFIG_ARCH_K3
114_reset: .word reset
115#endif
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200116_undefined_instruction: .word undefined_instruction
117_software_interrupt: .word software_interrupt
118_prefetch_abort: .word prefetch_abort
119_data_abort: .word data_abort
120_not_used: .word not_used
121_irq: .word irq
122_fiq: .word fiq
123
124 .balignl 16,0xdeadbeef
125
126/*
127 *************************************************************************
128 *
129 * Interrupt handling
130 *
131 *************************************************************************
132 */
133
134/* SPL interrupt handling: just hang */
135
136#ifdef CONFIG_SPL_BUILD
137
138 .align 5
139undefined_instruction:
140software_interrupt:
141prefetch_abort:
142data_abort:
143not_used:
144irq:
145fiq:
Albert ARIBAUD9852cc62014-04-15 16:13:51 +02001461:
Andrew F. Davisdf1f7e22018-06-11 14:04:17 -0500147 b 1b /* hang and never return */
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200148
149#else /* !CONFIG_SPL_BUILD */
150
151/* IRQ stack memory (calculated at run-time) + 8 bytes */
152.globl IRQ_STACK_START_IN
153IRQ_STACK_START_IN:
Lothar Waßmannedb1a3f2017-06-08 10:16:36 +0200154#ifdef IRAM_BASE_ADDR
155 .word IRAM_BASE_ADDR + 0x20
156#else
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200157 .word 0x0badc0de
Lothar Waßmannedb1a3f2017-06-08 10:16:36 +0200158#endif
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200159
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200160@
161@ IRQ stack frame.
162@
163#define S_FRAME_SIZE 72
164
165#define S_OLD_R0 68
166#define S_PSR 64
167#define S_PC 60
168#define S_LR 56
169#define S_SP 52
170
171#define S_IP 48
172#define S_FP 44
173#define S_R10 40
174#define S_R9 36
175#define S_R8 32
176#define S_R7 28
177#define S_R6 24
178#define S_R5 20
179#define S_R4 16
180#define S_R3 12
181#define S_R2 8
182#define S_R1 4
183#define S_R0 0
184
185#define MODE_SVC 0x13
186#define I_BIT 0x80
187
188/*
189 * use bad_save_user_regs for abort/prefetch/undef/swi ...
190 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
191 */
192
193 .macro bad_save_user_regs
194 @ carve out a frame on current user stack
195 sub sp, sp, #S_FRAME_SIZE
196 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
197 ldr r2, IRQ_STACK_START_IN
198 @ get values for "aborted" pc and cpsr (into parm regs)
199 ldmia r2, {r2 - r3}
200 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
201 add r5, sp, #S_SP
202 mov r1, lr
203 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
204 mov r0, sp @ save current stack into r0 (param register)
205 .endm
206
207 .macro irq_save_user_regs
208 sub sp, sp, #S_FRAME_SIZE
209 stmia sp, {r0 - r12} @ Calling r0-r12
210 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
211 add r8, sp, #S_PC
212 stmdb r8, {sp, lr}^ @ Calling SP, LR
213 str lr, [r8, #0] @ Save calling PC
214 mrs r6, spsr
215 str r6, [r8, #4] @ Save CPSR
216 str r0, [r8, #8] @ Save OLD_R0
217 mov r0, sp
218 .endm
219
220 .macro irq_restore_user_regs
221 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
222 mov r0, r0
223 ldr lr, [sp, #S_PC] @ Get PC
224 add sp, sp, #S_FRAME_SIZE
225 subs pc, lr, #4 @ return & move spsr_svc into cpsr
226 .endm
227
228 .macro get_bad_stack
229 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
230
231 str lr, [r13] @ save caller lr in position 0 of saved stack
232 mrs lr, spsr @ get the spsr
233 str lr, [r13, #4] @ save spsr in position 1 of saved stack
234 mov r13, #MODE_SVC @ prepare SVC-Mode
235 @ msr spsr_c, r13
236 msr spsr, r13 @ switch modes, make sure moves will execute
237 mov lr, pc @ capture return pc
238 movs pc, lr @ jump to next instruction & switch modes.
239 .endm
240
241 .macro get_irq_stack @ setup IRQ stack
242 ldr sp, IRQ_STACK_START
243 .endm
244
245 .macro get_fiq_stack @ setup FIQ stack
246 ldr sp, FIQ_STACK_START
247 .endm
248
249/*
250 * exception handlers
251 */
252
253 .align 5
254undefined_instruction:
255 get_bad_stack
256 bad_save_user_regs
257 bl do_undefined_instruction
258
259 .align 5
260software_interrupt:
261 get_bad_stack
262 bad_save_user_regs
263 bl do_software_interrupt
264
265 .align 5
266prefetch_abort:
267 get_bad_stack
268 bad_save_user_regs
269 bl do_prefetch_abort
270
271 .align 5
272data_abort:
273 get_bad_stack
274 bad_save_user_regs
275 bl do_data_abort
276
277 .align 5
278not_used:
279 get_bad_stack
280 bad_save_user_regs
281 bl do_not_used
282
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200283
284 .align 5
285irq:
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200286 get_bad_stack
287 bad_save_user_regs
288 bl do_irq
289
290 .align 5
291fiq:
292 get_bad_stack
293 bad_save_user_regs
294 bl do_fiq
295
Albert ARIBAUD9852cc62014-04-15 16:13:51 +0200296#endif /* CONFIG_SPL_BUILD */