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