]> git.sur5r.net Git - u-boot/blob - arch/arm/lib/vectors.S
arm: Do not clear LR on exception in SPL
[u-boot] / arch / arm / lib / vectors.S
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
128 undefined_instruction:
129 software_interrupt:
130 prefetch_abort:
131 data_abort:
132 not_used:
133 irq:
134 fiq:
135 1:
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
142 IRQ_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
243 undefined_instruction:
244         get_bad_stack
245         bad_save_user_regs
246         bl      do_undefined_instruction
247
248         .align  5
249 software_interrupt:
250         get_bad_stack
251         bad_save_user_regs
252         bl      do_software_interrupt
253
254         .align  5
255 prefetch_abort:
256         get_bad_stack
257         bad_save_user_regs
258         bl      do_prefetch_abort
259
260         .align  5
261 data_abort:
262         get_bad_stack
263         bad_save_user_regs
264         bl      do_data_abort
265
266         .align  5
267 not_used:
268         get_bad_stack
269         bad_save_user_regs
270         bl      do_not_used
271
272
273         .align  5
274 irq:
275         get_bad_stack
276         bad_save_user_regs
277         bl      do_irq
278
279         .align  5
280 fiq:
281         get_bad_stack
282         bad_save_user_regs
283         bl      do_fiq
284
285 #endif  /* CONFIG_SPL_BUILD */