xref: /openbmc/u-boot/arch/arm/lib/vectors.S (revision ae485b54)
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
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>
13 */
14
15#include <config.h>
16
17/*
18 * 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/*
34 *************************************************************************
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
51	.section ".vectors", "ax"
52
53#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
70/*
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
80_start:
81#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
82	.word	CONFIG_SYS_DV_NOR_BOOT_CFG
83#endif
84	ARM_VECTORS
85#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */
86
87/*
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
105_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:
1351:
136	b	1b			/* hang and never return */
137
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:
143#ifdef IRAM_BASE_ADDR
144	.word   IRAM_BASE_ADDR + 0x20
145#else
146	.word	0x0badc0de
147#endif
148
149@
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
272
273	.align	5
274irq:
275	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
285#endif	/* CONFIG_SPL_BUILD */
286