From 3e61b2b54336510475fbab83b7d97538f3ac5460 Mon Sep 17 00:00:00 2001 From: David Cunado Date: Mon, 2 Oct 2017 17:41:39 +0100 Subject: Init and save / restore of PMCR_EL0 / PMCR Currently TF does not initialise the PMCR_EL0 register in the secure context or save/restore the register. In particular, the DP field may not be set to one to prohibit cycle counting in the secure state, even though event counting generally is prohibited via the default setting of MDCR_EL3.SMPE to 0. This patch initialises PMCR_EL0.DP to one in the secure state to prohibit cycle counting and also initialises other fields that have an architectually UNKNOWN reset value. Additionally, PMCR_EL0 is added to the list of registers that are saved and restored during a world switch. Similar changes are made for PMCR for the AArch32 execution state. NOTE: secure world code at lower ELs that assume other values in PMCR_EL0 will be impacted. Change-Id: Iae40e8c0a196d74053accf97063ebc257b4d2f3a Signed-off-by: David Cunado --- include/lib/aarch32/arch.h | 2 ++ include/lib/aarch32/smcc_helpers.h | 6 ++++-- include/lib/aarch32/smcc_macros.S | 12 +++++++++++- include/lib/aarch64/arch.h | 5 +++++ include/lib/aarch64/arch_helpers.h | 2 +- include/lib/el3_runtime/aarch64/context.h | 19 ++++++++++--------- 6 files changed, 33 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h index 5fbb83a6..6c6d6a1d 100644 --- a/include/lib/aarch32/arch.h +++ b/include/lib/aarch32/arch.h @@ -350,6 +350,8 @@ #define PMCR_N_SHIFT 11 #define PMCR_N_MASK 0x1f #define PMCR_N_BITS (PMCR_N_MASK << PMCR_N_SHIFT) +#define PMCR_LC_BIT (1 << 6) +#define PMCR_DP_BIT (1 << 5) /******************************************************************************* * Definitions of register offsets, fields and macros for CPU system diff --git a/include/lib/aarch32/smcc_helpers.h b/include/lib/aarch32/smcc_helpers.h index 1bc84381..53f1aa4a 100644 --- a/include/lib/aarch32/smcc_helpers.h +++ b/include/lib/aarch32/smcc_helpers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,7 +21,8 @@ #define SMC_CTX_SP_MON 0x7C #define SMC_CTX_LR_MON 0x80 #define SMC_CTX_SCR 0x84 -#define SMC_CTX_SIZE 0x88 +#define SMC_CTX_PMCR 0x88 +#define SMC_CTX_SIZE 0x8C #ifndef __ASSEMBLY__ #include @@ -73,6 +74,7 @@ typedef struct smc_ctx { u_register_t sp_mon; u_register_t lr_mon; u_register_t scr; + u_register_t pmcr; } smc_ctx_t; /* diff --git a/include/lib/aarch32/smcc_macros.S b/include/lib/aarch32/smcc_macros.S index 7edf4106..cf26175d 100644 --- a/include/lib/aarch32/smcc_macros.S +++ b/include/lib/aarch32/smcc_macros.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -13,6 +13,8 @@ * spsr, lr, sp registers and the `scr` register to the SMC context on entry * due a SMC call. The `lr` of the current mode (monitor) is expected to be * already saved. The `sp` must point to the `smc_ctx_t` to save to. + * Additionally, also save the 'pmcr' register as this is updated whilst + * executing in the secure world. */ .macro smcc_save_gp_mode_regs /* Save r0 - r12 in the SMC context */ @@ -46,6 +48,8 @@ /* lr_mon is already saved by caller */ ldcopr r4, SCR str r4, [sp, #SMC_CTX_SCR] + ldcopr r4, PMCR + str r4, [sp, #SMC_CTX_PMCR] .endm /* @@ -70,6 +74,12 @@ stcopr r1, SCR isb + /* + * Restore the PMCR register. + */ + ldr r1, [r0, #SMC_CTX_PMCR] + stcopr r1, PMCR + /* Restore the banked registers including the current SPSR */ add r1, r0, #SMC_CTX_SP_USR ldm r1!, {r4-r12} diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index f85e7897..9cbe4058 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -502,9 +502,14 @@ #define CNTACR_RWPT_SHIFT U(0x5) /* PMCR_EL0 definitions */ +#define PMCR_EL0_RESET_VAL U(0x0) #define PMCR_EL0_N_SHIFT U(11) #define PMCR_EL0_N_MASK U(0x1f) #define PMCR_EL0_N_BITS (PMCR_EL0_N_MASK << PMCR_EL0_N_SHIFT) +#define PMCR_EL0_LC_BIT (U(1) << 6) +#define PMCR_EL0_DP_BIT (U(1) << 5) +#define PMCR_EL0_X_BIT (U(1) << 4) +#define PMCR_EL0_D_BIT (U(1) << 3) /******************************************************************************* * Definitions of MAIR encodings for device and normal memory diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h index 0d0d7d33..684a0deb 100644 --- a/include/lib/aarch64/arch_helpers.h +++ b/include/lib/aarch64/arch_helpers.h @@ -307,7 +307,7 @@ DEFINE_SYSREG_READ_FUNC(ctr_el0) DEFINE_SYSREG_RW_FUNCS(mdcr_el2) DEFINE_SYSREG_RW_FUNCS(hstr_el2) DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_el2) -DEFINE_SYSREG_READ_FUNC(pmcr_el0) +DEFINE_SYSREG_RW_FUNCS(pmcr_el0) DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2) diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index dcbf1c9d..a89468d4 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -87,22 +87,23 @@ #define CTX_AFSR1_EL1 U(0x98) #define CTX_CONTEXTIDR_EL1 U(0xa0) #define CTX_VBAR_EL1 U(0xa8) +#define CTX_PMCR_EL0 U(0xb0) /* * 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 U(0xb0) -#define CTX_SPSR_UND U(0xb8) -#define CTX_SPSR_IRQ U(0xc0) -#define CTX_SPSR_FIQ U(0xc8) -#define CTX_DACR32_EL2 U(0xd0) -#define CTX_IFSR32_EL2 U(0xd8) -#define CTX_FP_FPEXC32_EL2 U(0xe0) -#define CTX_TIMER_SYSREGS_OFF U(0xf0) /* Align to the next 16 byte boundary */ +#define CTX_SPSR_ABT U(0xc0) /* Align to the next 16 byte boundary */ +#define CTX_SPSR_UND U(0xc8) +#define CTX_SPSR_IRQ U(0xd0) +#define CTX_SPSR_FIQ U(0xd8) +#define CTX_DACR32_EL2 U(0xe0) +#define CTX_IFSR32_EL2 U(0xe8) +#define CTX_FP_FPEXC32_EL2 U(0xf0) +#define CTX_TIMER_SYSREGS_OFF U(0x100) /* Align to the next 16 byte boundary */ #else -#define CTX_TIMER_SYSREGS_OFF U(0xb0) +#define CTX_TIMER_SYSREGS_OFF U(0xc0) /* Align to the next 16 byte boundary */ #endif /* __CTX_INCLUDE_AARCH32_REGS__ */ /* -- cgit v1.2.3