summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSoby Mathew <soby.mathew@arm.com>2016-05-17 14:01:32 +0100
committerSoby Mathew <soby.mathew@arm.com>2016-06-03 10:50:52 +0100
commit8cd16e6b5b4a83a2cf704362b9acb1c2eea1417e (patch)
treeb514a455aa4ab76bb08f0313c170b6c160448ac0
parente141aa0357fd4977ba874f4f86874e2cadc73498 (diff)
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
-rw-r--r--Makefile5
-rw-r--r--bl1/bl1_context_mgmt.c14
-rw-r--r--bl31/bl31_main.c13
-rw-r--r--common/aarch64/context.S66
-rw-r--r--docs/user-guide.md6
-rw-r--r--include/common/context.h82
6 files changed, 119 insertions, 67 deletions
diff --git a/Makefile b/Makefile
index b1560a2b..ccb0abc3 100644
--- a/Makefile
+++ b/Makefile
@@ -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))
diff --git a/bl1/bl1_context_mgmt.c b/bl1/bl1_context_mgmt.c
index bd40608b..972c7f68 100644
--- a/bl1/bl1_context_mgmt.c
+++ b/bl1/bl1_context_mgmt.c
@@ -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);
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index 835d41e8..7f04d218 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -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();
diff --git a/common/aarch64/context.S b/common/aarch64/context.S
index 0baa9b2f..d51daa78 100644
--- a/common/aarch64/context.S
+++ b/common/aarch64/context.S
@@ -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
diff --git a/docs/user-guide.md b/docs/user-guide.md
index cd9c8c33..0911eb8b 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -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.
diff --git a/include/common/context.h b/include/common/context.h
index 0dfebe0b..ec47f2ad 100644
--- a/include/common/context.h
+++ b/include/common/context.h
@@ -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'