141623c91SAlbert ARIBAUD/* 241623c91SAlbert ARIBAUD * vectors - Generic ARM exception table code 341623c91SAlbert ARIBAUD * 441623c91SAlbert ARIBAUD * Copyright (c) 1998 Dan Malek <dmalek@jlc.net> 541623c91SAlbert ARIBAUD * Copyright (c) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> 641623c91SAlbert ARIBAUD * Copyright (c) 2000 Wolfgang Denk <wd@denx.de> 741623c91SAlbert ARIBAUD * Copyright (c) 2001 Alex Züpke <azu@sysgo.de> 841623c91SAlbert ARIBAUD * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> 941623c91SAlbert ARIBAUD * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> 1041623c91SAlbert ARIBAUD * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> 1141623c91SAlbert ARIBAUD * Copyright (c) 2002 Kyle Harris <kharris@nexus-tech.net> 1241623c91SAlbert ARIBAUD * 1341623c91SAlbert ARIBAUD * SPDX-License-Identifier: GPL-2.0+ 1441623c91SAlbert ARIBAUD */ 1541623c91SAlbert ARIBAUD 16db993fc8SChristian Riesch#include <config.h> 17db993fc8SChristian Riesch 1841623c91SAlbert ARIBAUD/* 19733d51d5SPhilipp Tomsich * A macro to allow insertion of an ARM exception vector either 20733d51d5SPhilipp Tomsich * for the non-boot0 case or by a boot0-header. 21733d51d5SPhilipp Tomsich */ 22733d51d5SPhilipp Tomsich .macro ARM_VECTORS 23733d51d5SPhilipp Tomsich b reset 24733d51d5SPhilipp Tomsich ldr pc, _undefined_instruction 25733d51d5SPhilipp Tomsich ldr pc, _software_interrupt 26733d51d5SPhilipp Tomsich ldr pc, _prefetch_abort 27733d51d5SPhilipp Tomsich ldr pc, _data_abort 28733d51d5SPhilipp Tomsich ldr pc, _not_used 29733d51d5SPhilipp Tomsich ldr pc, _irq 30733d51d5SPhilipp Tomsich ldr pc, _fiq 31733d51d5SPhilipp Tomsich .endm 32733d51d5SPhilipp Tomsich 33733d51d5SPhilipp Tomsich 34733d51d5SPhilipp Tomsich/* 3541623c91SAlbert ARIBAUD ************************************************************************* 3641623c91SAlbert ARIBAUD * 3741623c91SAlbert ARIBAUD * Symbol _start is referenced elsewhere, so make it global 3841623c91SAlbert ARIBAUD * 3941623c91SAlbert ARIBAUD ************************************************************************* 4041623c91SAlbert ARIBAUD */ 4141623c91SAlbert ARIBAUD 4241623c91SAlbert ARIBAUD.globl _start 4341623c91SAlbert ARIBAUD 4441623c91SAlbert ARIBAUD/* 4541623c91SAlbert ARIBAUD ************************************************************************* 4641623c91SAlbert ARIBAUD * 4741623c91SAlbert ARIBAUD * Vectors have their own section so linker script can map them easily 4841623c91SAlbert ARIBAUD * 4941623c91SAlbert ARIBAUD ************************************************************************* 5041623c91SAlbert ARIBAUD */ 5141623c91SAlbert ARIBAUD 52c57a6423SGeorges Savoundararadj .section ".vectors", "ax" 5341623c91SAlbert ARIBAUD 54733d51d5SPhilipp Tomsich#if defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) 55733d51d5SPhilipp Tomsich/* 56733d51d5SPhilipp Tomsich * Various SoCs need something special and SoC-specific up front in 57733d51d5SPhilipp Tomsich * order to boot, allow them to set that in their boot0.h file and then 58733d51d5SPhilipp Tomsich * use it here. 59733d51d5SPhilipp Tomsich * 60733d51d5SPhilipp Tomsich * To allow a boot0 hook to insert a 'special' sequence after the vector 61733d51d5SPhilipp Tomsich * table (e.g. for the socfpga), the presence of a boot0 hook supresses 62733d51d5SPhilipp Tomsich * the below vector table and assumes that the vector table is filled in 63733d51d5SPhilipp Tomsich * by the boot0 hook. The requirements for a boot0 hook thus are: 64733d51d5SPhilipp Tomsich * (1) defines '_start:' as appropriate 65733d51d5SPhilipp Tomsich * (2) inserts the vector table using ARM_VECTORS as appropriate 66733d51d5SPhilipp Tomsich */ 67733d51d5SPhilipp Tomsich#include <asm/arch/boot0.h> 68733d51d5SPhilipp Tomsich 69733d51d5SPhilipp Tomsich#else 70733d51d5SPhilipp Tomsich 7141623c91SAlbert ARIBAUD/* 7241623c91SAlbert ARIBAUD ************************************************************************* 7341623c91SAlbert ARIBAUD * 7441623c91SAlbert ARIBAUD * Exception vectors as described in ARM reference manuals 7541623c91SAlbert ARIBAUD * 7641623c91SAlbert ARIBAUD * Uses indirect branch to allow reaching handlers anywhere in memory. 7741623c91SAlbert ARIBAUD * 7841623c91SAlbert ARIBAUD ************************************************************************* 7941623c91SAlbert ARIBAUD */ 8041623c91SAlbert ARIBAUD 81a7f99bf1SBenoît Thébaudeau_start: 8241623c91SAlbert ARIBAUD#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG 8341623c91SAlbert ARIBAUD .word CONFIG_SYS_DV_NOR_BOOT_CFG 8441623c91SAlbert ARIBAUD#endif 85733d51d5SPhilipp Tomsich ARM_VECTORS 86733d51d5SPhilipp Tomsich#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */ 87cdaa633fSAndre Przywara 8841623c91SAlbert ARIBAUD/* 8941623c91SAlbert ARIBAUD ************************************************************************* 9041623c91SAlbert ARIBAUD * 9141623c91SAlbert ARIBAUD * Indirect vectors table 9241623c91SAlbert ARIBAUD * 9341623c91SAlbert ARIBAUD * Symbols referenced here must be defined somewhere else 9441623c91SAlbert ARIBAUD * 9541623c91SAlbert ARIBAUD ************************************************************************* 9641623c91SAlbert ARIBAUD */ 9741623c91SAlbert ARIBAUD 9841623c91SAlbert ARIBAUD .globl _undefined_instruction 9941623c91SAlbert ARIBAUD .globl _software_interrupt 10041623c91SAlbert ARIBAUD .globl _prefetch_abort 10141623c91SAlbert ARIBAUD .globl _data_abort 10241623c91SAlbert ARIBAUD .globl _not_used 10341623c91SAlbert ARIBAUD .globl _irq 10441623c91SAlbert ARIBAUD .globl _fiq 10541623c91SAlbert ARIBAUD 10641623c91SAlbert ARIBAUD_undefined_instruction: .word undefined_instruction 10741623c91SAlbert ARIBAUD_software_interrupt: .word software_interrupt 10841623c91SAlbert ARIBAUD_prefetch_abort: .word prefetch_abort 10941623c91SAlbert ARIBAUD_data_abort: .word data_abort 11041623c91SAlbert ARIBAUD_not_used: .word not_used 11141623c91SAlbert ARIBAUD_irq: .word irq 11241623c91SAlbert ARIBAUD_fiq: .word fiq 11341623c91SAlbert ARIBAUD 11441623c91SAlbert ARIBAUD .balignl 16,0xdeadbeef 11541623c91SAlbert ARIBAUD 11641623c91SAlbert ARIBAUD/* 11741623c91SAlbert ARIBAUD ************************************************************************* 11841623c91SAlbert ARIBAUD * 11941623c91SAlbert ARIBAUD * Interrupt handling 12041623c91SAlbert ARIBAUD * 12141623c91SAlbert ARIBAUD ************************************************************************* 12241623c91SAlbert ARIBAUD */ 12341623c91SAlbert ARIBAUD 12441623c91SAlbert ARIBAUD/* SPL interrupt handling: just hang */ 12541623c91SAlbert ARIBAUD 12641623c91SAlbert ARIBAUD#ifdef CONFIG_SPL_BUILD 12741623c91SAlbert ARIBAUD 12841623c91SAlbert ARIBAUD .align 5 12941623c91SAlbert ARIBAUDundefined_instruction: 13041623c91SAlbert ARIBAUDsoftware_interrupt: 13141623c91SAlbert ARIBAUDprefetch_abort: 13241623c91SAlbert ARIBAUDdata_abort: 13341623c91SAlbert ARIBAUDnot_used: 13441623c91SAlbert ARIBAUDirq: 13541623c91SAlbert ARIBAUDfiq: 13641623c91SAlbert ARIBAUD1: 13741623c91SAlbert ARIBAUD bl 1b /* hang and never return */ 13841623c91SAlbert ARIBAUD 13941623c91SAlbert ARIBAUD#else /* !CONFIG_SPL_BUILD */ 14041623c91SAlbert ARIBAUD 14141623c91SAlbert ARIBAUD/* IRQ stack memory (calculated at run-time) + 8 bytes */ 14241623c91SAlbert ARIBAUD.globl IRQ_STACK_START_IN 14341623c91SAlbert ARIBAUDIRQ_STACK_START_IN: 14469c5d76fSLothar Waßmann#ifdef IRAM_BASE_ADDR 14569c5d76fSLothar Waßmann .word IRAM_BASE_ADDR + 0x20 14669c5d76fSLothar Waßmann#else 14741623c91SAlbert ARIBAUD .word 0x0badc0de 14869c5d76fSLothar Waßmann#endif 14941623c91SAlbert ARIBAUD 150*7cef7918SJoseph Chen#if CONFIG_IS_ENABLED(IRQ) 151fa40f8a0SJoseph Chen/* IRQ stack memory (calculated at run-time) */ 152fa40f8a0SJoseph Chen.globl IRQ_STACK_START 153fa40f8a0SJoseph ChenIRQ_STACK_START: 154fa40f8a0SJoseph Chen .word 0x0badc0de 155fa40f8a0SJoseph Chen#endif 156fa40f8a0SJoseph Chen 15741623c91SAlbert ARIBAUD@ 15841623c91SAlbert ARIBAUD@ IRQ stack frame. 15941623c91SAlbert ARIBAUD@ 16041623c91SAlbert ARIBAUD#define S_FRAME_SIZE 72 16141623c91SAlbert ARIBAUD 16241623c91SAlbert ARIBAUD#define S_OLD_R0 68 16341623c91SAlbert ARIBAUD#define S_PSR 64 16441623c91SAlbert ARIBAUD#define S_PC 60 16541623c91SAlbert ARIBAUD#define S_LR 56 16641623c91SAlbert ARIBAUD#define S_SP 52 16741623c91SAlbert ARIBAUD 16841623c91SAlbert ARIBAUD#define S_IP 48 16941623c91SAlbert ARIBAUD#define S_FP 44 17041623c91SAlbert ARIBAUD#define S_R10 40 17141623c91SAlbert ARIBAUD#define S_R9 36 17241623c91SAlbert ARIBAUD#define S_R8 32 17341623c91SAlbert ARIBAUD#define S_R7 28 17441623c91SAlbert ARIBAUD#define S_R6 24 17541623c91SAlbert ARIBAUD#define S_R5 20 17641623c91SAlbert ARIBAUD#define S_R4 16 17741623c91SAlbert ARIBAUD#define S_R3 12 17841623c91SAlbert ARIBAUD#define S_R2 8 17941623c91SAlbert ARIBAUD#define S_R1 4 18041623c91SAlbert ARIBAUD#define S_R0 0 18141623c91SAlbert ARIBAUD 1829fa74d15SJoseph Chen#define MODE_IRQ 0x12 18341623c91SAlbert ARIBAUD#define MODE_SVC 0x13 18441623c91SAlbert ARIBAUD#define I_BIT 0x80 18541623c91SAlbert ARIBAUD 18641623c91SAlbert ARIBAUD/* 18741623c91SAlbert ARIBAUD * use bad_save_user_regs for abort/prefetch/undef/swi ... 18841623c91SAlbert ARIBAUD * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 18941623c91SAlbert ARIBAUD */ 19041623c91SAlbert ARIBAUD 19141623c91SAlbert ARIBAUD .macro bad_save_user_regs 19241623c91SAlbert ARIBAUD @ carve out a frame on current user stack 19341623c91SAlbert ARIBAUD sub sp, sp, #S_FRAME_SIZE 19441623c91SAlbert ARIBAUD stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 19541623c91SAlbert ARIBAUD ldr r2, IRQ_STACK_START_IN 19641623c91SAlbert ARIBAUD @ get values for "aborted" pc and cpsr (into parm regs) 19741623c91SAlbert ARIBAUD ldmia r2, {r2 - r3} 19841623c91SAlbert ARIBAUD add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 19941623c91SAlbert ARIBAUD add r5, sp, #S_SP 20041623c91SAlbert ARIBAUD mov r1, lr 20141623c91SAlbert ARIBAUD stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 20241623c91SAlbert ARIBAUD mov r0, sp @ save current stack into r0 (param register) 20341623c91SAlbert ARIBAUD .endm 20441623c91SAlbert ARIBAUD 20541623c91SAlbert ARIBAUD .macro irq_save_user_regs 20641623c91SAlbert ARIBAUD sub sp, sp, #S_FRAME_SIZE 20741623c91SAlbert ARIBAUD stmia sp, {r0 - r12} @ Calling r0-r12 20841623c91SAlbert ARIBAUD @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. 20941623c91SAlbert ARIBAUD add r8, sp, #S_PC 2109fa74d15SJoseph Chen 2119fa74d15SJoseph Chen cps #MODE_SVC @ SVC-Mode 2129fa74d15SJoseph Chen isb 2139fa74d15SJoseph Chen mov r1, sp @ svc_sp 2149fa74d15SJoseph Chen mov r2, lr @ svc_lr 2159fa74d15SJoseph Chen cps #MODE_IRQ @ IRQ-Mode 2169fa74d15SJoseph Chen isb 2179fa74d15SJoseph Chen 2189fa74d15SJoseph Chen stmdb r8, {r1, r2}^ @ Calling svc_sp, svc_lr 21941623c91SAlbert ARIBAUD str lr, [r8, #0] @ Save calling PC 22041623c91SAlbert ARIBAUD mrs r6, spsr 22141623c91SAlbert ARIBAUD str r6, [r8, #4] @ Save CPSR 22241623c91SAlbert ARIBAUD str r0, [r8, #8] @ Save OLD_R0 22341623c91SAlbert ARIBAUD mov r0, sp 22441623c91SAlbert ARIBAUD .endm 22541623c91SAlbert ARIBAUD 22641623c91SAlbert ARIBAUD .macro irq_restore_user_regs 22741623c91SAlbert ARIBAUD ldmia sp, {r0 - lr}^ @ Calling r0 - lr 22841623c91SAlbert ARIBAUD mov r0, r0 22941623c91SAlbert ARIBAUD ldr lr, [sp, #S_PC] @ Get PC 23041623c91SAlbert ARIBAUD add sp, sp, #S_FRAME_SIZE 23141623c91SAlbert ARIBAUD subs pc, lr, #4 @ return & move spsr_svc into cpsr 23241623c91SAlbert ARIBAUD .endm 23341623c91SAlbert ARIBAUD 23441623c91SAlbert ARIBAUD .macro get_bad_stack 23541623c91SAlbert ARIBAUD ldr r13, IRQ_STACK_START_IN @ setup our mode stack 23641623c91SAlbert ARIBAUD 23741623c91SAlbert ARIBAUD str lr, [r13] @ save caller lr in position 0 of saved stack 23841623c91SAlbert ARIBAUD mrs lr, spsr @ get the spsr 23941623c91SAlbert ARIBAUD str lr, [r13, #4] @ save spsr in position 1 of saved stack 24041623c91SAlbert ARIBAUD mov r13, #MODE_SVC @ prepare SVC-Mode 24141623c91SAlbert ARIBAUD @ msr spsr_c, r13 24241623c91SAlbert ARIBAUD msr spsr, r13 @ switch modes, make sure moves will execute 24341623c91SAlbert ARIBAUD mov lr, pc @ capture return pc 24441623c91SAlbert ARIBAUD movs pc, lr @ jump to next instruction & switch modes. 24541623c91SAlbert ARIBAUD .endm 24641623c91SAlbert ARIBAUD 24741623c91SAlbert ARIBAUD .macro get_irq_stack @ setup IRQ stack 24841623c91SAlbert ARIBAUD ldr sp, IRQ_STACK_START 24941623c91SAlbert ARIBAUD .endm 25041623c91SAlbert ARIBAUD 25141623c91SAlbert ARIBAUD .macro get_fiq_stack @ setup FIQ stack 25241623c91SAlbert ARIBAUD ldr sp, FIQ_STACK_START 25341623c91SAlbert ARIBAUD .endm 25441623c91SAlbert ARIBAUD 25541623c91SAlbert ARIBAUD/* 25641623c91SAlbert ARIBAUD * exception handlers 25741623c91SAlbert ARIBAUD */ 25841623c91SAlbert ARIBAUD 25941623c91SAlbert ARIBAUD .align 5 26041623c91SAlbert ARIBAUDundefined_instruction: 26141623c91SAlbert ARIBAUD get_bad_stack 26241623c91SAlbert ARIBAUD bad_save_user_regs 26341623c91SAlbert ARIBAUD bl do_undefined_instruction 26441623c91SAlbert ARIBAUD 26541623c91SAlbert ARIBAUD .align 5 26641623c91SAlbert ARIBAUDsoftware_interrupt: 26741623c91SAlbert ARIBAUD get_bad_stack 26841623c91SAlbert ARIBAUD bad_save_user_regs 26941623c91SAlbert ARIBAUD bl do_software_interrupt 27041623c91SAlbert ARIBAUD 27141623c91SAlbert ARIBAUD .align 5 27241623c91SAlbert ARIBAUDprefetch_abort: 27341623c91SAlbert ARIBAUD get_bad_stack 27441623c91SAlbert ARIBAUD bad_save_user_regs 27541623c91SAlbert ARIBAUD bl do_prefetch_abort 27641623c91SAlbert ARIBAUD 27741623c91SAlbert ARIBAUD .align 5 27841623c91SAlbert ARIBAUDdata_abort: 27941623c91SAlbert ARIBAUD get_bad_stack 28041623c91SAlbert ARIBAUD bad_save_user_regs 28141623c91SAlbert ARIBAUD bl do_data_abort 28241623c91SAlbert ARIBAUD 28341623c91SAlbert ARIBAUD .align 5 28441623c91SAlbert ARIBAUDnot_used: 28541623c91SAlbert ARIBAUD get_bad_stack 28641623c91SAlbert ARIBAUD bad_save_user_regs 28741623c91SAlbert ARIBAUD bl do_not_used 28841623c91SAlbert ARIBAUD 28941623c91SAlbert ARIBAUD 29041623c91SAlbert ARIBAUD .align 5 29141623c91SAlbert ARIBAUDirq: 292*7cef7918SJoseph Chen#if CONFIG_IS_ENABLED(IRQ) 293fa40f8a0SJoseph Chen get_irq_stack 294fa40f8a0SJoseph Chen irq_save_user_regs 295fa40f8a0SJoseph Chen bl do_irq 296fa40f8a0SJoseph Chen irq_restore_user_regs 297fa40f8a0SJoseph Chen#else 29841623c91SAlbert ARIBAUD get_bad_stack 29941623c91SAlbert ARIBAUD bad_save_user_regs 30041623c91SAlbert ARIBAUD bl do_irq 301fa40f8a0SJoseph Chen#endif 30241623c91SAlbert ARIBAUD 30341623c91SAlbert ARIBAUD .align 5 30441623c91SAlbert ARIBAUDfiq: 30541623c91SAlbert ARIBAUD get_bad_stack 30641623c91SAlbert ARIBAUD bad_save_user_regs 30741623c91SAlbert ARIBAUD bl do_fiq 30841623c91SAlbert ARIBAUD 30941623c91SAlbert ARIBAUD#endif /* CONFIG_SPL_BUILD */ 310