diff options
Diffstat (limited to 'roms/u-boot/arch/arm/lib/vectors.S')
-rw-r--r-- | roms/u-boot/arch/arm/lib/vectors.S | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/lib/vectors.S b/roms/u-boot/arch/arm/lib/vectors.S new file mode 100644 index 000000000..56f368155 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/vectors.S @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * vectors - Generic ARM exception table code + * + * Copyright (c) 1998 Dan Malek <dmalek@jlc.net> + * Copyright (c) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (c) 2000 Wolfgang Denk <wd@denx.de> + * Copyright (c) 2001 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2002 Kyle Harris <kharris@nexus-tech.net> + */ + +#include <config.h> + +/* + * A macro to allow insertion of an ARM exception vector either + * for the non-boot0 case or by a boot0-header. + */ + .macro ARM_VECTORS +#ifdef CONFIG_ARCH_K3 + ldr pc, _reset +#else + b reset +#endif + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + .endm + + +/* + ************************************************************************* + * + * Symbol _start is referenced elsewhere, so make it global + * + ************************************************************************* + */ + +.globl _start + +/* + ************************************************************************* + * + * Vectors have their own section so linker script can map them easily + * + ************************************************************************* + */ + + .section ".vectors", "ax" + +#if defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) +/* + * Various SoCs need something special and SoC-specific up front in + * order to boot, allow them to set that in their boot0.h file and then + * use it here. + * + * To allow a boot0 hook to insert a 'special' sequence after the vector + * table (e.g. for the socfpga), the presence of a boot0 hook supresses + * the below vector table and assumes that the vector table is filled in + * by the boot0 hook. The requirements for a boot0 hook thus are: + * (1) defines '_start:' as appropriate + * (2) inserts the vector table using ARM_VECTORS as appropriate + */ +#include <asm/arch/boot0.h> +#else + +/* + ************************************************************************* + * + * Exception vectors as described in ARM reference manuals + * + * Uses indirect branch to allow reaching handlers anywhere in memory. + * + ************************************************************************* + */ + +_start: +#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG + .word CONFIG_SYS_DV_NOR_BOOT_CFG +#endif + ARM_VECTORS +#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */ + +/* + ************************************************************************* + * + * Indirect vectors table + * + * Symbols referenced here must be defined somewhere else + * + ************************************************************************* + */ + + .globl _reset + .globl _undefined_instruction + .globl _software_interrupt + .globl _prefetch_abort + .globl _data_abort + .globl _not_used + .globl _irq + .globl _fiq + +#ifdef CONFIG_ARCH_K3 +_reset: .word reset +#endif +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq + + .balignl 16,0xdeadbeef + +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +/* SPL interrupt handling: just hang */ + +#ifdef CONFIG_SPL_BUILD + + .align 5 +undefined_instruction: +software_interrupt: +prefetch_abort: +data_abort: +not_used: +irq: +fiq: +1: + b 1b /* hang and never return */ + +#else /* !CONFIG_SPL_BUILD */ + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: +#ifdef IRAM_BASE_ADDR + .word IRAM_BASE_ADDR + 0x20 +#else + .word 0x0badc0de +#endif + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + @ carve out a frame on current user stack + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 + ldr r2, IRQ_STACK_START_IN + @ get values for "aborted" pc and cpsr (into parm regs) + ldmia r2, {r2 - r3} + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp @ save current stack into r0 (param register) + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + + str lr, [r13] @ save caller lr in position 0 of saved stack + mrs lr, spsr @ get the spsr + str lr, [r13, #4] @ save spsr in position 1 of saved stack + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 @ switch modes, make sure moves will execute + mov lr, pc @ capture return pc + movs pc, lr @ jump to next instruction & switch modes. + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif /* CONFIG_SPL_BUILD */ |