[U-Boot] [PATCH v2 5/5] arm: move exception handling out of start.S files

Andreas Bießmann andreas.devel at googlemail.com
Sun Mar 9 19:21:24 CET 2014


Dear Albert Aribaud,

On 09.03.2014 17:18, Albert ARIBAUD wrote:

<snip>

> diff --git a/arch/arm/lib/vectors.S b/arch/arm/lib/vectors.S
> new file mode 100644
> index 0000000..1655d49
> --- /dev/null
> +++ b/arch/arm/lib/vectors.S
> @@ -0,0 +1,304 @@
> +/*
> + *  vectors - Generic ARM exception table code
> + *
> + *  Copyright (c) 1998	Dan Malek <dmalek at jlc.net>
> + *  Copyright (c) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
> + *  Copyright (c) 2000	Wolfgang Denk <wd at denx.de>
> + *  Copyright (c) 2001	Alex Züpke <azu at sysgo.de>
> + *  Copyright (c) 2001	Marius Gröger <mag at sysgo.de>
> + *  Copyright (c) 2002	Alex Züpke <azu at sysgo.de>
> + *  Copyright (c) 2002	Gary Jennejohn <garyj at denx.de>
> + *  Copyright (c) 2002	Kyle Harris <kharris at nexus-tech.net>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +/*
> + *************************************************************************
> + *
> + * 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", "x"
> +
> +/*
> + *************************************************************************
> + *
> + * 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
> +
> +#ifdef CONFIG_SPL_BUILD
> +
> +_start:
> +	ldr	pc, _reset
> +	ldr	pc, _hang
> +	ldr	pc, _hang
> +	ldr	pc, _hang
> +	ldr	pc, _hang
> +	ldr	pc, _hang
> +	ldr	pc, _hang
> +	ldr	pc, _hang
> +
> +#else
> +
> +_start:
> +	ldr	pc, _reset
> +	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
> +
> +#endif
> +
> +/*
> + *************************************************************************
> + *
> + * Indirect vectors table
> + *
> + * Symbols referenced here must be defined somewhere else
> + *
> + *************************************************************************
> + */
> +
> +_reset:			.word reset
> +
> +#ifdef CONFIG_SPL_BUILD
> +
> +_hang:			.word do_hang
> +
> +#else
> +
> +	.globl	_undefined_instruction
> +	.globl	_software_interrupt
> +	.globl	_prefetch_abort
> +	.globl	_data_abort
> +	.globl	_not_used
> +	.globl	_irq
> +	.globl	_fiq
> +
> +_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
> +
> +#endif
> +
> +	.balignl 16,0xdeadbeef
> +
> +/*
> + *************************************************************************
> + *
> + * Interrupt handling
> + *
> + *************************************************************************
> + */
> +
> +/* IRQ stack memory (calculated at run-time) + 8 bytes */
> +.globl IRQ_STACK_START_IN
> +IRQ_STACK_START_IN:
> +	.word	0x0badc0de
> +
> +#ifndef CONFIG_SPL_BUILD
> +
> +#ifdef CONFIG_USE_IRQ
> +/* IRQ stack memory (calculated at run-time) */
> +.globl IRQ_STACK_START
> +IRQ_STACK_START:
> +	.word	0x0badc0de
> +
> +/* IRQ stack memory (calculated at run-time) */
> +.globl FIQ_STACK_START
> +FIQ_STACK_START:
> +	.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
> +#endif	/* CONFIG_SPL_BUILD */
> +
> +/*
> + * exception handlers
> + */
> +#ifdef CONFIG_SPL_BUILD
> +	.align	5
> +do_hang:
> +1:
> +	bl	1b				/* hang and never return */
> +#else	/* !CONFIG_SPL_BUILD */
> +	.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
> +
> +#ifdef CONFIG_USE_IRQ
> +
> +	.align	5
> +irq:
> +	get_irq_stack
> +	irq_save_user_regs
> +	bl	do_irq
> +	irq_restore_user_regs
> +
> +	.align	5
> +fiq:
> +	get_fiq_stack
> +	/* someone ought to write a more effiction fiq_save_user_regs */
> +	irq_save_user_regs
> +	bl	do_fiq
> +	irq_restore_user_regs
> +
> +#else
> +
> +	.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
> +#endif	/* CONFIG_SPL_BUILD */

this file is completely different for SPL and non-SPL builds. They both 
share just the header of the file. I wonder why we introduce a single 
vectors.S then. Wouldn't it be better to have a vectors.S for non-SPL 
builds and lets say a vectors_SPL.S for SPL builds?

Best regards

Andreas Bießmann


More information about the U-Boot mailing list