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: 120 1211: 122 bl 1b /* hang and never return */ 123 124#else /* !CONFIG_SPL_BUILD */ 125 126/* IRQ stack memory (calculated at run-time) + 8 bytes */ 127.globl IRQ_STACK_START_IN 128IRQ_STACK_START_IN: 129 .word 0x0badc0de 130 131#ifdef CONFIG_USE_IRQ 132/* IRQ stack memory (calculated at run-time) */ 133.globl IRQ_STACK_START 134IRQ_STACK_START: 135 .word 0x0badc0de 136 137/* IRQ stack memory (calculated at run-time) */ 138.globl FIQ_STACK_START 139FIQ_STACK_START: 140 .word 0x0badc0de 141 142#endif /* CONFIG_USE_IRQ */ 143 144@ 145@ IRQ stack frame. 146@ 147#define S_FRAME_SIZE 72 148 149#define S_OLD_R0 68 150#define S_PSR 64 151#define S_PC 60 152#define S_LR 56 153#define S_SP 52 154 155#define S_IP 48 156#define S_FP 44 157#define S_R10 40 158#define S_R9 36 159#define S_R8 32 160#define S_R7 28 161#define S_R6 24 162#define S_R5 20 163#define S_R4 16 164#define S_R3 12 165#define S_R2 8 166#define S_R1 4 167#define S_R0 0 168 169#define MODE_SVC 0x13 170#define I_BIT 0x80 171 172/* 173 * use bad_save_user_regs for abort/prefetch/undef/swi ... 174 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 175 */ 176 177 .macro bad_save_user_regs 178 @ carve out a frame on current user stack 179 sub sp, sp, #S_FRAME_SIZE 180 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 181 ldr r2, IRQ_STACK_START_IN 182 @ get values for "aborted" pc and cpsr (into parm regs) 183 ldmia r2, {r2 - r3} 184 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 185 add r5, sp, #S_SP 186 mov r1, lr 187 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 188 mov r0, sp @ save current stack into r0 (param register) 189 .endm 190 191 .macro irq_save_user_regs 192 sub sp, sp, #S_FRAME_SIZE 193 stmia sp, {r0 - r12} @ Calling r0-r12 194 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. 195 add r8, sp, #S_PC 196 stmdb r8, {sp, lr}^ @ Calling SP, LR 197 str lr, [r8, #0] @ Save calling PC 198 mrs r6, spsr 199 str r6, [r8, #4] @ Save CPSR 200 str r0, [r8, #8] @ Save OLD_R0 201 mov r0, sp 202 .endm 203 204 .macro irq_restore_user_regs 205 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 206 mov r0, r0 207 ldr lr, [sp, #S_PC] @ Get PC 208 add sp, sp, #S_FRAME_SIZE 209 subs pc, lr, #4 @ return & move spsr_svc into cpsr 210 .endm 211 212 .macro get_bad_stack 213 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 214 215 str lr, [r13] @ save caller lr in position 0 of saved stack 216 mrs lr, spsr @ get the spsr 217 str lr, [r13, #4] @ save spsr in position 1 of saved stack 218 mov r13, #MODE_SVC @ prepare SVC-Mode 219 @ msr spsr_c, r13 220 msr spsr, r13 @ switch modes, make sure moves will execute 221 mov lr, pc @ capture return pc 222 movs pc, lr @ jump to next instruction & switch modes. 223 .endm 224 225 .macro get_irq_stack @ setup IRQ stack 226 ldr sp, IRQ_STACK_START 227 .endm 228 229 .macro get_fiq_stack @ setup FIQ stack 230 ldr sp, FIQ_STACK_START 231 .endm 232 233/* 234 * exception handlers 235 */ 236 237 .align 5 238undefined_instruction: 239 get_bad_stack 240 bad_save_user_regs 241 bl do_undefined_instruction 242 243 .align 5 244software_interrupt: 245 get_bad_stack 246 bad_save_user_regs 247 bl do_software_interrupt 248 249 .align 5 250prefetch_abort: 251 get_bad_stack 252 bad_save_user_regs 253 bl do_prefetch_abort 254 255 .align 5 256data_abort: 257 get_bad_stack 258 bad_save_user_regs 259 bl do_data_abort 260 261 .align 5 262not_used: 263 get_bad_stack 264 bad_save_user_regs 265 bl do_not_used 266 267#ifdef CONFIG_USE_IRQ 268 269 .align 5 270irq: 271 get_irq_stack 272 irq_save_user_regs 273 bl do_irq 274 irq_restore_user_regs 275 276 .align 5 277fiq: 278 get_fiq_stack 279 /* someone ought to write a more effiction fiq_save_user_regs */ 280 irq_save_user_regs 281 bl do_fiq 282 irq_restore_user_regs 283 284#else 285 286 .align 5 287irq: 288 get_bad_stack 289 bad_save_user_regs 290 bl do_irq 291 292 .align 5 293fiq: 294 get_bad_stack 295 bad_save_user_regs 296 bl do_fiq 297 298#endif /* CONFIG_USE_IRQ */ 299 300#endif /* CONFIG_SPL_BUILD */ 301