From 2da8d8bfc0877b9c723514133554dfee4c0638f1 Mon Sep 17 00:00:00 2001 From: Jeenu Viswambharan Date: Mon, 12 May 2014 15:28:47 +0100 Subject: [PATCH] Add build configuration for timer save/restore At present, non-secure timer register contents are saved and restored as part of world switch by BL3-1. This effectively means that the non-secure timer stops, and non-secure timer interrupts are prevented from asserting until BL3-1 switches back, introducing latency for non-secure services. Often, secure world might depend on alternate sources for secure interrupts (secure timer or platform timer) instead of non-secure timers, in which case this save and restore is unnecessary. This patch introduces a boolean build-time configuration NS_TIMER_SWITCH to choose whether or not to save and restore non-secure timer registers upon world switch. The default choice is made not to save and restore them. Fixes ARM-software/tf-issues#148 Change-Id: I1b9d623606acb9797c3e0b02fb5ec7c0a414f37e --- Makefile | 6 ++++++ bl31/aarch64/context.S | 14 ++++++++++++-- docs/user-guide.md | 5 +++++ include/bl31/context.h | 9 +++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fc6c46914..94dde7f7e 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,8 @@ PLAT := ${DEFAULT_PLAT} 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 @@ CFLAGS += -g 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 45d4a2255..d0bca64fc 100644 --- a/bl31/aarch64/context.S +++ b/bl31/aarch64/context.S @@ -172,6 +172,8 @@ func el1_sysregs_context_save 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 @@ func el1_sysregs_context_save 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 @@ func el1_sysregs_context_restore 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 @@ func el1_sysregs_context_restore 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 edf03f0a4..e7f0df54c 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -141,6 +141,11 @@ performed. * `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 549fa2127..b0dfec15d 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'