xref: /openbmc/u-boot/arch/arm/lib/vectors.S (revision a7f99bf1)
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/*
1941623c91SAlbert ARIBAUD *************************************************************************
2041623c91SAlbert ARIBAUD *
2141623c91SAlbert ARIBAUD * Symbol _start is referenced elsewhere, so make it global
2241623c91SAlbert ARIBAUD *
2341623c91SAlbert ARIBAUD *************************************************************************
2441623c91SAlbert ARIBAUD */
2541623c91SAlbert ARIBAUD
2641623c91SAlbert ARIBAUD.globl _start
2741623c91SAlbert ARIBAUD
2841623c91SAlbert ARIBAUD/*
2941623c91SAlbert ARIBAUD *************************************************************************
3041623c91SAlbert ARIBAUD *
3141623c91SAlbert ARIBAUD * Vectors have their own section so linker script can map them easily
3241623c91SAlbert ARIBAUD *
3341623c91SAlbert ARIBAUD *************************************************************************
3441623c91SAlbert ARIBAUD */
3541623c91SAlbert ARIBAUD
3641623c91SAlbert ARIBAUD	.section ".vectors", "x"
3741623c91SAlbert ARIBAUD
3841623c91SAlbert ARIBAUD/*
3941623c91SAlbert ARIBAUD *************************************************************************
4041623c91SAlbert ARIBAUD *
4141623c91SAlbert ARIBAUD * Exception vectors as described in ARM reference manuals
4241623c91SAlbert ARIBAUD *
4341623c91SAlbert ARIBAUD * Uses indirect branch to allow reaching handlers anywhere in memory.
4441623c91SAlbert ARIBAUD *
4541623c91SAlbert ARIBAUD *************************************************************************
4641623c91SAlbert ARIBAUD */
4741623c91SAlbert ARIBAUD
48*a7f99bf1SBenoît Thébaudeau_start:
49*a7f99bf1SBenoît Thébaudeau
5041623c91SAlbert ARIBAUD#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
5141623c91SAlbert ARIBAUD	.word	CONFIG_SYS_DV_NOR_BOOT_CFG
5241623c91SAlbert ARIBAUD#endif
5341623c91SAlbert ARIBAUD
5458f9e1aeSBenoît Thébaudeau	b	reset
5541623c91SAlbert ARIBAUD	ldr	pc, _undefined_instruction
5641623c91SAlbert ARIBAUD	ldr	pc, _software_interrupt
5741623c91SAlbert ARIBAUD	ldr	pc, _prefetch_abort
5841623c91SAlbert ARIBAUD	ldr	pc, _data_abort
5941623c91SAlbert ARIBAUD	ldr	pc, _not_used
6041623c91SAlbert ARIBAUD	ldr	pc, _irq
6141623c91SAlbert ARIBAUD	ldr	pc, _fiq
6241623c91SAlbert ARIBAUD
6341623c91SAlbert ARIBAUD/*
6441623c91SAlbert ARIBAUD *************************************************************************
6541623c91SAlbert ARIBAUD *
6641623c91SAlbert ARIBAUD * Indirect vectors table
6741623c91SAlbert ARIBAUD *
6841623c91SAlbert ARIBAUD * Symbols referenced here must be defined somewhere else
6941623c91SAlbert ARIBAUD *
7041623c91SAlbert ARIBAUD *************************************************************************
7141623c91SAlbert ARIBAUD */
7241623c91SAlbert ARIBAUD
7341623c91SAlbert ARIBAUD	.globl	_undefined_instruction
7441623c91SAlbert ARIBAUD	.globl	_software_interrupt
7541623c91SAlbert ARIBAUD	.globl	_prefetch_abort
7641623c91SAlbert ARIBAUD	.globl	_data_abort
7741623c91SAlbert ARIBAUD	.globl	_not_used
7841623c91SAlbert ARIBAUD	.globl	_irq
7941623c91SAlbert ARIBAUD	.globl	_fiq
8041623c91SAlbert ARIBAUD
8141623c91SAlbert ARIBAUD_undefined_instruction:	.word undefined_instruction
8241623c91SAlbert ARIBAUD_software_interrupt:	.word software_interrupt
8341623c91SAlbert ARIBAUD_prefetch_abort:	.word prefetch_abort
8441623c91SAlbert ARIBAUD_data_abort:		.word data_abort
8541623c91SAlbert ARIBAUD_not_used:		.word not_used
8641623c91SAlbert ARIBAUD_irq:			.word irq
8741623c91SAlbert ARIBAUD_fiq:			.word fiq
8841623c91SAlbert ARIBAUD
8941623c91SAlbert ARIBAUD	.balignl 16,0xdeadbeef
9041623c91SAlbert ARIBAUD
9141623c91SAlbert ARIBAUD/*
9241623c91SAlbert ARIBAUD *************************************************************************
9341623c91SAlbert ARIBAUD *
9441623c91SAlbert ARIBAUD * Interrupt handling
9541623c91SAlbert ARIBAUD *
9641623c91SAlbert ARIBAUD *************************************************************************
9741623c91SAlbert ARIBAUD */
9841623c91SAlbert ARIBAUD
9941623c91SAlbert ARIBAUD/* SPL interrupt handling: just hang */
10041623c91SAlbert ARIBAUD
10141623c91SAlbert ARIBAUD#ifdef CONFIG_SPL_BUILD
10241623c91SAlbert ARIBAUD
10341623c91SAlbert ARIBAUD	.align	5
10441623c91SAlbert ARIBAUDundefined_instruction:
10541623c91SAlbert ARIBAUDsoftware_interrupt:
10641623c91SAlbert ARIBAUDprefetch_abort:
10741623c91SAlbert ARIBAUDdata_abort:
10841623c91SAlbert ARIBAUDnot_used:
10941623c91SAlbert ARIBAUDirq:
11041623c91SAlbert ARIBAUDfiq:
11141623c91SAlbert ARIBAUD
11241623c91SAlbert ARIBAUD1:
11341623c91SAlbert ARIBAUD	bl	1b			/* hang and never return */
11441623c91SAlbert ARIBAUD
11541623c91SAlbert ARIBAUD#else	/* !CONFIG_SPL_BUILD */
11641623c91SAlbert ARIBAUD
11741623c91SAlbert ARIBAUD/* IRQ stack memory (calculated at run-time) + 8 bytes */
11841623c91SAlbert ARIBAUD.globl IRQ_STACK_START_IN
11941623c91SAlbert ARIBAUDIRQ_STACK_START_IN:
12041623c91SAlbert ARIBAUD	.word	0x0badc0de
12141623c91SAlbert ARIBAUD
12241623c91SAlbert ARIBAUD#ifdef CONFIG_USE_IRQ
12341623c91SAlbert ARIBAUD/* IRQ stack memory (calculated at run-time) */
12441623c91SAlbert ARIBAUD.globl IRQ_STACK_START
12541623c91SAlbert ARIBAUDIRQ_STACK_START:
12641623c91SAlbert ARIBAUD	.word	0x0badc0de
12741623c91SAlbert ARIBAUD
12841623c91SAlbert ARIBAUD/* IRQ stack memory (calculated at run-time) */
12941623c91SAlbert ARIBAUD.globl FIQ_STACK_START
13041623c91SAlbert ARIBAUDFIQ_STACK_START:
13141623c91SAlbert ARIBAUD	.word 0x0badc0de
13241623c91SAlbert ARIBAUD
13341623c91SAlbert ARIBAUD#endif /* CONFIG_USE_IRQ */
13441623c91SAlbert ARIBAUD
13541623c91SAlbert ARIBAUD@
13641623c91SAlbert ARIBAUD@ IRQ stack frame.
13741623c91SAlbert ARIBAUD@
13841623c91SAlbert ARIBAUD#define S_FRAME_SIZE	72
13941623c91SAlbert ARIBAUD
14041623c91SAlbert ARIBAUD#define S_OLD_R0	68
14141623c91SAlbert ARIBAUD#define S_PSR		64
14241623c91SAlbert ARIBAUD#define S_PC		60
14341623c91SAlbert ARIBAUD#define S_LR		56
14441623c91SAlbert ARIBAUD#define S_SP		52
14541623c91SAlbert ARIBAUD
14641623c91SAlbert ARIBAUD#define S_IP		48
14741623c91SAlbert ARIBAUD#define S_FP		44
14841623c91SAlbert ARIBAUD#define S_R10		40
14941623c91SAlbert ARIBAUD#define S_R9		36
15041623c91SAlbert ARIBAUD#define S_R8		32
15141623c91SAlbert ARIBAUD#define S_R7		28
15241623c91SAlbert ARIBAUD#define S_R6		24
15341623c91SAlbert ARIBAUD#define S_R5		20
15441623c91SAlbert ARIBAUD#define S_R4		16
15541623c91SAlbert ARIBAUD#define S_R3		12
15641623c91SAlbert ARIBAUD#define S_R2		8
15741623c91SAlbert ARIBAUD#define S_R1		4
15841623c91SAlbert ARIBAUD#define S_R0		0
15941623c91SAlbert ARIBAUD
16041623c91SAlbert ARIBAUD#define MODE_SVC 0x13
16141623c91SAlbert ARIBAUD#define I_BIT	 0x80
16241623c91SAlbert ARIBAUD
16341623c91SAlbert ARIBAUD/*
16441623c91SAlbert ARIBAUD * use bad_save_user_regs for abort/prefetch/undef/swi ...
16541623c91SAlbert ARIBAUD * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
16641623c91SAlbert ARIBAUD */
16741623c91SAlbert ARIBAUD
16841623c91SAlbert ARIBAUD	.macro	bad_save_user_regs
16941623c91SAlbert ARIBAUD	@ carve out a frame on current user stack
17041623c91SAlbert ARIBAUD	sub	sp, sp, #S_FRAME_SIZE
17141623c91SAlbert ARIBAUD	stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12
17241623c91SAlbert ARIBAUD	ldr	r2, IRQ_STACK_START_IN
17341623c91SAlbert ARIBAUD	@ get values for "aborted" pc and cpsr (into parm regs)
17441623c91SAlbert ARIBAUD	ldmia	r2, {r2 - r3}
17541623c91SAlbert ARIBAUD	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
17641623c91SAlbert ARIBAUD	add	r5, sp, #S_SP
17741623c91SAlbert ARIBAUD	mov	r1, lr
17841623c91SAlbert ARIBAUD	stmia	r5, {r0 - r3}	@ save sp_SVC, lr_SVC, pc, cpsr
17941623c91SAlbert ARIBAUD	mov	r0, sp		@ save current stack into r0 (param register)
18041623c91SAlbert ARIBAUD	.endm
18141623c91SAlbert ARIBAUD
18241623c91SAlbert ARIBAUD	.macro	irq_save_user_regs
18341623c91SAlbert ARIBAUD	sub	sp, sp, #S_FRAME_SIZE
18441623c91SAlbert ARIBAUD	stmia	sp, {r0 - r12}			@ Calling r0-r12
18541623c91SAlbert ARIBAUD	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
18641623c91SAlbert ARIBAUD	add	r8, sp, #S_PC
18741623c91SAlbert ARIBAUD	stmdb	r8, {sp, lr}^		@ Calling SP, LR
18841623c91SAlbert ARIBAUD	str	lr, [r8, #0]		@ Save calling PC
18941623c91SAlbert ARIBAUD	mrs	r6, spsr
19041623c91SAlbert ARIBAUD	str	r6, [r8, #4]		@ Save CPSR
19141623c91SAlbert ARIBAUD	str	r0, [r8, #8]		@ Save OLD_R0
19241623c91SAlbert ARIBAUD	mov	r0, sp
19341623c91SAlbert ARIBAUD	.endm
19441623c91SAlbert ARIBAUD
19541623c91SAlbert ARIBAUD	.macro	irq_restore_user_regs
19641623c91SAlbert ARIBAUD	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
19741623c91SAlbert ARIBAUD	mov	r0, r0
19841623c91SAlbert ARIBAUD	ldr	lr, [sp, #S_PC]			@ Get PC
19941623c91SAlbert ARIBAUD	add	sp, sp, #S_FRAME_SIZE
20041623c91SAlbert ARIBAUD	subs	pc, lr, #4		@ return & move spsr_svc into cpsr
20141623c91SAlbert ARIBAUD	.endm
20241623c91SAlbert ARIBAUD
20341623c91SAlbert ARIBAUD	.macro get_bad_stack
20441623c91SAlbert ARIBAUD	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
20541623c91SAlbert ARIBAUD
20641623c91SAlbert ARIBAUD	str	lr, [r13]	@ save caller lr in position 0 of saved stack
20741623c91SAlbert ARIBAUD	mrs	lr, spsr	@ get the spsr
20841623c91SAlbert ARIBAUD	str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
20941623c91SAlbert ARIBAUD	mov	r13, #MODE_SVC	@ prepare SVC-Mode
21041623c91SAlbert ARIBAUD	@ msr	spsr_c, r13
21141623c91SAlbert ARIBAUD	msr	spsr, r13	@ switch modes, make sure moves will execute
21241623c91SAlbert ARIBAUD	mov	lr, pc		@ capture return pc
21341623c91SAlbert ARIBAUD	movs	pc, lr		@ jump to next instruction & switch modes.
21441623c91SAlbert ARIBAUD	.endm
21541623c91SAlbert ARIBAUD
21641623c91SAlbert ARIBAUD	.macro get_irq_stack			@ setup IRQ stack
21741623c91SAlbert ARIBAUD	ldr	sp, IRQ_STACK_START
21841623c91SAlbert ARIBAUD	.endm
21941623c91SAlbert ARIBAUD
22041623c91SAlbert ARIBAUD	.macro get_fiq_stack			@ setup FIQ stack
22141623c91SAlbert ARIBAUD	ldr	sp, FIQ_STACK_START
22241623c91SAlbert ARIBAUD	.endm
22341623c91SAlbert ARIBAUD
22441623c91SAlbert ARIBAUD/*
22541623c91SAlbert ARIBAUD * exception handlers
22641623c91SAlbert ARIBAUD */
22741623c91SAlbert ARIBAUD
22841623c91SAlbert ARIBAUD	.align  5
22941623c91SAlbert ARIBAUDundefined_instruction:
23041623c91SAlbert ARIBAUD	get_bad_stack
23141623c91SAlbert ARIBAUD	bad_save_user_regs
23241623c91SAlbert ARIBAUD	bl	do_undefined_instruction
23341623c91SAlbert ARIBAUD
23441623c91SAlbert ARIBAUD	.align	5
23541623c91SAlbert ARIBAUDsoftware_interrupt:
23641623c91SAlbert ARIBAUD	get_bad_stack
23741623c91SAlbert ARIBAUD	bad_save_user_regs
23841623c91SAlbert ARIBAUD	bl	do_software_interrupt
23941623c91SAlbert ARIBAUD
24041623c91SAlbert ARIBAUD	.align	5
24141623c91SAlbert ARIBAUDprefetch_abort:
24241623c91SAlbert ARIBAUD	get_bad_stack
24341623c91SAlbert ARIBAUD	bad_save_user_regs
24441623c91SAlbert ARIBAUD	bl	do_prefetch_abort
24541623c91SAlbert ARIBAUD
24641623c91SAlbert ARIBAUD	.align	5
24741623c91SAlbert ARIBAUDdata_abort:
24841623c91SAlbert ARIBAUD	get_bad_stack
24941623c91SAlbert ARIBAUD	bad_save_user_regs
25041623c91SAlbert ARIBAUD	bl	do_data_abort
25141623c91SAlbert ARIBAUD
25241623c91SAlbert ARIBAUD	.align	5
25341623c91SAlbert ARIBAUDnot_used:
25441623c91SAlbert ARIBAUD	get_bad_stack
25541623c91SAlbert ARIBAUD	bad_save_user_regs
25641623c91SAlbert ARIBAUD	bl	do_not_used
25741623c91SAlbert ARIBAUD
25841623c91SAlbert ARIBAUD#ifdef CONFIG_USE_IRQ
25941623c91SAlbert ARIBAUD
26041623c91SAlbert ARIBAUD	.align	5
26141623c91SAlbert ARIBAUDirq:
26241623c91SAlbert ARIBAUD	get_irq_stack
26341623c91SAlbert ARIBAUD	irq_save_user_regs
26441623c91SAlbert ARIBAUD	bl	do_irq
26541623c91SAlbert ARIBAUD	irq_restore_user_regs
26641623c91SAlbert ARIBAUD
26741623c91SAlbert ARIBAUD	.align	5
26841623c91SAlbert ARIBAUDfiq:
26941623c91SAlbert ARIBAUD	get_fiq_stack
27041623c91SAlbert ARIBAUD	/* someone ought to write a more effiction fiq_save_user_regs */
27141623c91SAlbert ARIBAUD	irq_save_user_regs
27241623c91SAlbert ARIBAUD	bl	do_fiq
27341623c91SAlbert ARIBAUD	irq_restore_user_regs
27441623c91SAlbert ARIBAUD
27541623c91SAlbert ARIBAUD#else
27641623c91SAlbert ARIBAUD
27741623c91SAlbert ARIBAUD	.align	5
27841623c91SAlbert ARIBAUDirq:
27941623c91SAlbert ARIBAUD	get_bad_stack
28041623c91SAlbert ARIBAUD	bad_save_user_regs
28141623c91SAlbert ARIBAUD	bl	do_irq
28241623c91SAlbert ARIBAUD
28341623c91SAlbert ARIBAUD	.align	5
28441623c91SAlbert ARIBAUDfiq:
28541623c91SAlbert ARIBAUD	get_bad_stack
28641623c91SAlbert ARIBAUD	bad_save_user_regs
28741623c91SAlbert ARIBAUD	bl	do_fiq
28841623c91SAlbert ARIBAUD
28941623c91SAlbert ARIBAUD#endif /* CONFIG_USE_IRQ */
29041623c91SAlbert ARIBAUD
29141623c91SAlbert ARIBAUD#endif	/* CONFIG_SPL_BUILD */
292