Commit 8cd16e6b authored by Soby Mathew's avatar Soby Mathew
Browse files

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
parent e141aa03
......@@ -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))
......
......@@ -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);
......
......@@ -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();
......
......@@ -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
......
......@@ -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.
......
......@@ -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'
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment