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