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