summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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'