diff --git a/Makefile b/Makefile index fc6c469..94dde7f 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,8 @@ SPD := none # Base commit to perform code check on BASE_COMMIT := origin/master +# NS timer register save and restore +NS_TIMER_SWITCH := 0 # Checkpatch ignores @@ -171,6 +173,10 @@ ASFLAGS += -g -Wa,--gdwarf-2 endif +# Process NS_TIMER_SWITCH flag +$(eval $(call assert_boolean,NS_TIMER_SWITCH)) +$(eval $(call add_define,NS_TIMER_SWITCH)) + ASFLAGS += -nostdinc -ffreestanding -Wa,--fatal-warnings \ -mgeneral-regs-only -D__ASSEMBLY__ \ ${DEFINES} ${INCLUDES} diff --git a/bl31/aarch64/context.S b/bl31/aarch64/context.S index 45d4a22..d0bca64 100644 --- a/bl31/aarch64/context.S +++ b/bl31/aarch64/context.S @@ -172,6 +172,8 @@ mrs x9, vbar_el1 stp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] + /* Save NS timer registers if the build has instructed so */ +#if NS_TIMER_SWITCH mrs x10, cntp_ctl_el0 mrs x11, cntp_cval_el0 stp x10, x11, [x0, #CTX_CNTP_CTL_EL0] @@ -181,8 +183,11 @@ stp x12, x13, [x0, #CTX_CNTV_CTL_EL0] mrs x14, cntkctl_el1 + str x14, [x0, #CTX_CNTKCTL_EL1] +#endif + mrs x15, fpexc32_el2 - stp x14, x15, [x0, #CTX_CNTKCTL_EL1] + str x15, [x0, #CTX_FP_FPEXC32_EL2] ret @@ -253,6 +258,8 @@ msr contextidr_el1, x17 msr vbar_el1, x9 + /* Restore NS timer registers if the build has instructed so */ +#if NS_TIMER_SWITCH ldp x10, x11, [x0, #CTX_CNTP_CTL_EL0] msr cntp_ctl_el0, x10 msr cntp_cval_el0, x11 @@ -261,8 +268,11 @@ msr cntv_ctl_el0, x12 msr cntv_cval_el0, x13 - ldp x14, x15, [x0, #CTX_CNTKCTL_EL1] + ldr x14, [x0, #CTX_CNTKCTL_EL1] 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 */ diff --git a/docs/user-guide.md b/docs/user-guide.md index edf03f0..e7f0df5 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -141,6 +141,11 @@ * `DEBUG`: Chooses between a debug and release build. It can take either 0 (release) or 1 (debug) as values. 0 is the default +* `NS_TIMER_SWITCH`: Enable save and restore for non-secure timer register + contents upon world switch. It can take either 0 (don't save and restore) or + 1 (do save and restore). 0 is the default. An SPD could set this to 1 if it + wants the timer registers to be saved and restored + * `PLAT`: Choose a platform to build ARM Trusted Firmware for. The chosen platform name must be the name of one of the directories under the `plat/` directory other than `common` diff --git a/include/bl31/context.h b/include/bl31/context.h index 549fa21..b0dfec1 100644 --- a/include/bl31/context.h +++ b/include/bl31/context.h @@ -127,6 +127,11 @@ #define CTX_AFSR1_EL1 0xc8 #define CTX_CONTEXTIDR_EL1 0xd0 #define CTX_VBAR_EL1 0xd8 +/* + * 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 @@ -134,6 +139,10 @@ #define CTX_CNTKCTL_EL1 0x100 #define CTX_FP_FPEXC32_EL2 0x108 #define CTX_SYSREGS_END 0x110 +#else +#define CTX_FP_FPEXC32_EL2 0xe0 +#define CTX_SYSREGS_END 0xf0 +#endif /******************************************************************************* * Constants that allow assembler code to access members of and the 'fp_regs'