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