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