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