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