Build option to include AArch32 registers in cpu context

The system registers that are saved and restored in CPU context include
AArch32 systems registers like SPSR_ABT, SPSR_UND, SPSR_IRQ, SPSR_FIQ,
DACR32_EL2, IFSR32_EL2 and FPEXC32_EL2. Accessing these registers on an
AArch64-only (i.e. on hardware that does not implement AArch32, or at
least not at EL1 and higher ELs) platform leads to an exception. This patch
introduces the build option `CTX_INCLUDE_AARCH32_REGS` to specify whether to
include these AArch32 systems registers in the cpu context or not. By default
this build option is set to 1 to ensure compatibility. AArch64-only platforms
must set it to 0. A runtime check is added in BL1 and BL31 cold boot path to
verify this.

Fixes ARM-software/tf-issues#386

Change-Id: I720cdbd7ed7f7d8516635a2ec80d025f478b95ee
This commit is contained in:
Soby Mathew 2016-05-17 14:01:32 +01:00
parent e141aa0357
commit 8cd16e6b5b
6 changed files with 119 additions and 67 deletions

View File

@ -62,6 +62,9 @@ NS_TIMER_SWITCH := 0
RESET_TO_BL31 := 0
# Include FP registers in cpu context
CTX_INCLUDE_FPREGS := 0
# Build flag to include AArch32 registers in cpu context save and restore
# during world switch. This flag must be set to 0 for AArch64-only platforms.
CTX_INCLUDE_AARCH32_REGS := 1
# Determine the version of ARM GIC architecture to use for interrupt management
# in EL3. The platform port can change this value if needed.
ARM_GIC_ARCH := 2
@ -392,6 +395,7 @@ $(eval $(call assert_boolean,DEBUG))
$(eval $(call assert_boolean,NS_TIMER_SWITCH))
$(eval $(call assert_boolean,RESET_TO_BL31))
$(eval $(call assert_boolean,CTX_INCLUDE_FPREGS))
$(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS))
$(eval $(call assert_boolean,ASM_ASSERTION))
$(eval $(call assert_boolean,USE_COHERENT_MEM))
$(eval $(call assert_boolean,DISABLE_PEDANTIC))
@ -419,6 +423,7 @@ $(eval $(call add_define,SPD_${SPD}))
$(eval $(call add_define,NS_TIMER_SWITCH))
$(eval $(call add_define,RESET_TO_BL31))
$(eval $(call add_define,CTX_INCLUDE_FPREGS))
$(eval $(call add_define,CTX_INCLUDE_AARCH32_REGS))
$(eval $(call add_define,ARM_GIC_ARCH))
$(eval $(call add_define,ARM_CCI_PRODUCT_ID))
$(eval $(call add_define,ASM_ASSERTION))

View File

@ -32,6 +32,7 @@
#include <assert.h>
#include <context.h>
#include <context_mgmt.h>
#include <debug.h>
#include <platform.h>
/*
@ -66,6 +67,19 @@ void bl1_prepare_next_image(unsigned int image_id)
image_desc_t *image_desc;
entry_point_info_t *next_bl_ep;
#if CTX_INCLUDE_AARCH32_REGS
/*
* Ensure that the build flag to save AArch32 system registers in CPU
* context is not set for AArch64-only platforms.
*/
if (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL1_SHIFT)
& ID_AA64PFR0_ELX_MASK) == 0x1) {
ERROR("EL1 supports AArch64-only. Please set build flag "
"CTX_INCLUDE_AARCH32_REGS = 0");
panic();
}
#endif
/* Get the image descriptor. */
image_desc = bl1_plat_get_image_desc(image_id);
assert(image_desc);

View File

@ -145,6 +145,19 @@ void bl31_prepare_next_image_entry(void)
entry_point_info_t *next_image_info;
uint32_t image_type;
#if CTX_INCLUDE_AARCH32_REGS
/*
* Ensure that the build flag to save AArch32 system registers in CPU
* context is not set for AArch64-only platforms.
*/
if (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL1_SHIFT)
& ID_AA64PFR0_ELX_MASK) == 0x1) {
ERROR("EL1 supports AArch64-only. Please set build flag "
"CTX_INCLUDE_AARCH32_REGS = 0");
panic();
}
#endif
/* Determine which image to execute next */
image_type = bl31_get_next_image_type();

View File

@ -57,14 +57,6 @@ func el1_sysregs_context_save
mrs x10, elr_el1
stp x9, x10, [x0, #CTX_SPSR_EL1]
mrs x11, spsr_abt
mrs x12, spsr_und
stp x11, x12, [x0, #CTX_SPSR_ABT]
mrs x13, spsr_irq
mrs x14, spsr_fiq
stp x13, x14, [x0, #CTX_SPSR_IRQ]
mrs x15, sctlr_el1
mrs x16, actlr_el1
stp x15, x16, [x0, #CTX_SCTLR_EL1]
@ -93,10 +85,6 @@ func el1_sysregs_context_save
mrs x10, tpidrro_el0
stp x9, x10, [x0, #CTX_TPIDR_EL0]
mrs x11, dacr32_el2
mrs x12, ifsr32_el2
stp x11, x12, [x0, #CTX_DACR32_EL2]
mrs x13, par_el1
mrs x14, far_el1
stp x13, x14, [x0, #CTX_PAR_EL1]
@ -109,6 +97,24 @@ func el1_sysregs_context_save
mrs x9, vbar_el1
stp x17, x9, [x0, #CTX_CONTEXTIDR_EL1]
/* Save AArch32 system registers if the build has instructed so */
#if CTX_INCLUDE_AARCH32_REGS
mrs x11, spsr_abt
mrs x12, spsr_und
stp x11, x12, [x0, #CTX_SPSR_ABT]
mrs x13, spsr_irq
mrs x14, spsr_fiq
stp x13, x14, [x0, #CTX_SPSR_IRQ]
mrs x15, dacr32_el2
mrs x16, ifsr32_el2
stp x15, x16, [x0, #CTX_DACR32_EL2]
mrs x17, fpexc32_el2
str x17, [x0, #CTX_FP_FPEXC32_EL2]
#endif
/* Save NS timer registers if the build has instructed so */
#if NS_TIMER_SWITCH
mrs x10, cntp_ctl_el0
@ -123,9 +129,6 @@ func el1_sysregs_context_save
str x14, [x0, #CTX_CNTKCTL_EL1]
#endif
mrs x15, fpexc32_el2
str x15, [x0, #CTX_FP_FPEXC32_EL2]
ret
endfunc el1_sysregs_context_save
@ -143,14 +146,6 @@ func el1_sysregs_context_restore
msr spsr_el1, x9
msr elr_el1, x10
ldp x11, x12, [x0, #CTX_SPSR_ABT]
msr spsr_abt, x11
msr spsr_und, x12
ldp x13, x14, [x0, #CTX_SPSR_IRQ]
msr spsr_irq, x13
msr spsr_fiq, x14
ldp x15, x16, [x0, #CTX_SCTLR_EL1]
msr sctlr_el1, x15
msr actlr_el1, x16
@ -179,10 +174,6 @@ func el1_sysregs_context_restore
msr tpidr_el0, x9
msr tpidrro_el0, x10
ldp x11, x12, [x0, #CTX_DACR32_EL2]
msr dacr32_el2, x11
msr ifsr32_el2, x12
ldp x13, x14, [x0, #CTX_PAR_EL1]
msr par_el1, x13
msr far_el1, x14
@ -195,6 +186,23 @@ func el1_sysregs_context_restore
msr contextidr_el1, x17
msr vbar_el1, x9
/* Restore AArch32 system registers if the build has instructed so */
#if CTX_INCLUDE_AARCH32_REGS
ldp x11, x12, [x0, #CTX_SPSR_ABT]
msr spsr_abt, x11
msr spsr_und, x12
ldp x13, x14, [x0, #CTX_SPSR_IRQ]
msr spsr_irq, x13
msr spsr_fiq, x14
ldp x15, x16, [x0, #CTX_DACR32_EL2]
msr dacr32_el2, x15
msr ifsr32_el2, x16
ldr x17, [x0, #CTX_FP_FPEXC32_EL2]
msr fpexc32_el2, x17
#endif
/* Restore NS timer registers if the build has instructed so */
#if NS_TIMER_SWITCH
ldp x10, x11, [x0, #CTX_CNTP_CTL_EL0]
@ -209,11 +217,7 @@ func el1_sysregs_context_restore
msr cntkctl_el1, x14
#endif
ldr x15, [x0, #CTX_FP_FPEXC32_EL2]
msr fpexc32_el2, x15
/* No explict ISB required here as ERET covers it */
ret
endfunc el1_sysregs_context_restore

View File

@ -380,6 +380,12 @@ performed.
any register that is not part of the SBSA generic UART specification.
Default value is 0 (a full PL011 compliant UART is present).
* `CTX_INCLUDE_AARCH32_REGS` : Boolean option that, when set to 1, will cause
the AArch32 system registers to be included when saving and restoring the
CPU context. The option must be set to 0 for AArch64-only platforms (that
is on hardware that does not implement AArch32, or at least not at EL1 and
higher ELs). Default value is 1.
* `CTX_INCLUDE_FPREGS`: Boolean option that, when set to 1, will cause the FP
registers to be included when saving and restoring the CPU context. Default
is 0.

View File

@ -91,48 +91,58 @@
#define CTX_SYSREGS_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
#define CTX_SPSR_EL1 0x0
#define CTX_ELR_EL1 0x8
#define CTX_SPSR_ABT 0x10
#define CTX_SPSR_UND 0x18
#define CTX_SPSR_IRQ 0x20
#define CTX_SPSR_FIQ 0x28
#define CTX_SCTLR_EL1 0x30
#define CTX_ACTLR_EL1 0x38
#define CTX_CPACR_EL1 0x40
#define CTX_CSSELR_EL1 0x48
#define CTX_SP_EL1 0x50
#define CTX_ESR_EL1 0x58
#define CTX_TTBR0_EL1 0x60
#define CTX_TTBR1_EL1 0x68
#define CTX_MAIR_EL1 0x70
#define CTX_AMAIR_EL1 0x78
#define CTX_TCR_EL1 0x80
#define CTX_TPIDR_EL1 0x88
#define CTX_TPIDR_EL0 0x90
#define CTX_TPIDRRO_EL0 0x98
#define CTX_DACR32_EL2 0xa0
#define CTX_IFSR32_EL2 0xa8
#define CTX_PAR_EL1 0xb0
#define CTX_FAR_EL1 0xb8
#define CTX_AFSR0_EL1 0xc0
#define CTX_AFSR1_EL1 0xc8
#define CTX_CONTEXTIDR_EL1 0xd0
#define CTX_VBAR_EL1 0xd8
#define CTX_SCTLR_EL1 0x10
#define CTX_ACTLR_EL1 0x18
#define CTX_CPACR_EL1 0x20
#define CTX_CSSELR_EL1 0x28
#define CTX_SP_EL1 0x30
#define CTX_ESR_EL1 0x38
#define CTX_TTBR0_EL1 0x40
#define CTX_TTBR1_EL1 0x48
#define CTX_MAIR_EL1 0x50
#define CTX_AMAIR_EL1 0x58
#define CTX_TCR_EL1 0x60
#define CTX_TPIDR_EL1 0x68
#define CTX_TPIDR_EL0 0x70
#define CTX_TPIDRRO_EL0 0x78
#define CTX_PAR_EL1 0x80
#define CTX_FAR_EL1 0x88
#define CTX_AFSR0_EL1 0x90
#define CTX_AFSR1_EL1 0x98
#define CTX_CONTEXTIDR_EL1 0xa0
#define CTX_VBAR_EL1 0xa8
/*
* If the platform is AArch64-only, there is no need to save and restore these
* AArch32 registers.
*/
#if CTX_INCLUDE_AARCH32_REGS
#define CTX_SPSR_ABT 0xb0
#define CTX_SPSR_UND 0xb8
#define CTX_SPSR_IRQ 0xc0
#define CTX_SPSR_FIQ 0xc8
#define CTX_DACR32_EL2 0xd0
#define CTX_IFSR32_EL2 0xd8
#define CTX_FP_FPEXC32_EL2 0xe0
#define CTX_TIMER_SYSREGS_OFF 0xf0 /* Align to the next 16 byte boundary */
#else
#define CTX_TIMER_SYSREGS_OFF 0xb0
#endif /* __CTX_INCLUDE_AARCH32_REGS__ */
/*
* If the timer registers aren't saved and restored, we don't have to reserve
* space for them in the context
*/
#if NS_TIMER_SWITCH
#define CTX_CNTP_CTL_EL0 0xe0
#define CTX_CNTP_CVAL_EL0 0xe8
#define CTX_CNTV_CTL_EL0 0xf0
#define CTX_CNTV_CVAL_EL0 0xf8
#define CTX_CNTKCTL_EL1 0x100
#define CTX_FP_FPEXC32_EL2 0x108
#define CTX_SYSREGS_END 0x110
#define CTX_CNTP_CTL_EL0 (CTX_TIMER_SYSREGS_OFF + 0x0)
#define CTX_CNTP_CVAL_EL0 (CTX_TIMER_SYSREGS_OFF + 0x8)
#define CTX_CNTV_CTL_EL0 (CTX_TIMER_SYSREGS_OFF + 0x10)
#define CTX_CNTV_CVAL_EL0 (CTX_TIMER_SYSREGS_OFF + 0x18)
#define CTX_CNTKCTL_EL1 (CTX_TIMER_SYSREGS_OFF + 0x20)
#define CTX_SYSREGS_END (CTX_TIMER_SYSREGS_OFF + 0x30) /* Align to the next 16 byte boundary */
#else
#define CTX_FP_FPEXC32_EL2 0xe0
#define CTX_SYSREGS_END 0xf0
#endif
#define CTX_SYSREGS_END CTX_TIMER_SYSREGS_OFF
#endif /* __NS_TIMER_SWITCH__ */
/*******************************************************************************
* Constants that allow assembler code to access members of and the 'fp_regs'