diff --git a/Makefile b/Makefile index b1560a2..ccb0abc 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,9 @@ 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,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,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 bd40608..972c7f6 100644 --- a/bl1/bl1_context_mgmt.c +++ b/bl1/bl1_context_mgmt.c @@ -32,6 +32,7 @@ #include #include #include +#include #include /* @@ -66,6 +67,19 @@ 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 835d41e..7f04d21 100644 --- a/bl31/bl31_main.c +++ b/bl31/bl31_main.c @@ -145,6 +145,19 @@ 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 0baa9b2..d51daa7 100644 --- a/common/aarch64/context.S +++ b/common/aarch64/context.S @@ -57,14 +57,6 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 ce0390d..0bdedf9 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -380,6 +380,12 @@ 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 0dfebe0..ec47f2a 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'