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