Commit 3e61b2b5 authored by David Cunado's avatar David Cunado
Browse files

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: default avatarDavid Cunado <david.cunado@arm.com>
parent 9679297f
...@@ -162,6 +162,15 @@ func handle_smc ...@@ -162,6 +162,15 @@ func handle_smc
stcopr r0, SCR stcopr r0, SCR
isb isb
/*
* Set PMCR.DP to 1 to prohibit cycle counting whilst in Secure Mode.
* Also, the PMCR.LC field has an architecturally UNKNOWN value on reset
* and so set to 1 as ARM has deprecated use of PMCR.LC=0.
*/
ldcopr r0, PMCR
orr r0, r0, #(PMCR_LC_BIT | PMCR_DP_BIT)
stcopr r0, PMCR
ldr r0, [r2, #SMC_CTX_GPREG_R0] /* smc_fid */ ldr r0, [r2, #SMC_CTX_GPREG_R0] /* smc_fid */
/* Check whether an SMC64 is issued */ /* Check whether an SMC64 is issued */
tst r0, #(FUNCID_CC_MASK << FUNCID_CC_SHIFT) tst r0, #(FUNCID_CC_MASK << FUNCID_CC_SHIFT)
...@@ -210,6 +219,15 @@ func handle_fiq ...@@ -210,6 +219,15 @@ func handle_fiq
stcopr r0, SCR stcopr r0, SCR
isb isb
/*
* Set PMCR.DP to 1 to prohibit cycle counting whilst in Secure Mode.
* Also, the PMCR.LC field has an architecturally UNKNOWN value on reset
* and so set to 1 as ARM has deprecated use of PMCR.LC=0.
*/
ldcopr r0, PMCR
orr r0, r0, #(PMCR_LC_BIT | PMCR_DP_BIT)
stcopr r0, PMCR
push {r2, r3} push {r2, r3}
bl sp_min_fiq bl sp_min_fiq
pop {r0, r3} pop {r0, r3}
......
...@@ -350,6 +350,8 @@ ...@@ -350,6 +350,8 @@
#define PMCR_N_SHIFT 11 #define PMCR_N_SHIFT 11
#define PMCR_N_MASK 0x1f #define PMCR_N_MASK 0x1f
#define PMCR_N_BITS (PMCR_N_MASK << PMCR_N_SHIFT) #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 * Definitions of register offsets, fields and macros for CPU system
......
/* /*
* 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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
#define SMC_CTX_SP_MON 0x7C #define SMC_CTX_SP_MON 0x7C
#define SMC_CTX_LR_MON 0x80 #define SMC_CTX_LR_MON 0x80
#define SMC_CTX_SCR 0x84 #define SMC_CTX_SCR 0x84
#define SMC_CTX_SIZE 0x88 #define SMC_CTX_PMCR 0x88
#define SMC_CTX_SIZE 0x8C
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <cassert.h> #include <cassert.h>
...@@ -73,6 +74,7 @@ typedef struct smc_ctx { ...@@ -73,6 +74,7 @@ typedef struct smc_ctx {
u_register_t sp_mon; u_register_t sp_mon;
u_register_t lr_mon; u_register_t lr_mon;
u_register_t scr; u_register_t scr;
u_register_t pmcr;
} smc_ctx_t; } smc_ctx_t;
/* /*
......
/* /*
* 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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
* spsr, lr, sp registers and the `scr` register to the SMC context on entry * 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 * 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. * 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 .macro smcc_save_gp_mode_regs
/* Save r0 - r12 in the SMC context */ /* Save r0 - r12 in the SMC context */
...@@ -46,6 +48,8 @@ ...@@ -46,6 +48,8 @@
/* lr_mon is already saved by caller */ /* lr_mon is already saved by caller */
ldcopr r4, SCR ldcopr r4, SCR
str r4, [sp, #SMC_CTX_SCR] str r4, [sp, #SMC_CTX_SCR]
ldcopr r4, PMCR
str r4, [sp, #SMC_CTX_PMCR]
.endm .endm
/* /*
...@@ -70,6 +74,12 @@ ...@@ -70,6 +74,12 @@
stcopr r1, SCR stcopr r1, SCR
isb isb
/*
* Restore the PMCR register.
*/
ldr r1, [r0, #SMC_CTX_PMCR]
stcopr r1, PMCR
/* Restore the banked registers including the current SPSR */ /* Restore the banked registers including the current SPSR */
add r1, r0, #SMC_CTX_SP_USR add r1, r0, #SMC_CTX_SP_USR
ldm r1!, {r4-r12} ldm r1!, {r4-r12}
......
...@@ -502,9 +502,14 @@ ...@@ -502,9 +502,14 @@
#define CNTACR_RWPT_SHIFT U(0x5) #define CNTACR_RWPT_SHIFT U(0x5)
/* PMCR_EL0 definitions */ /* PMCR_EL0 definitions */
#define PMCR_EL0_RESET_VAL U(0x0)
#define PMCR_EL0_N_SHIFT U(11) #define PMCR_EL0_N_SHIFT U(11)
#define PMCR_EL0_N_MASK U(0x1f) #define PMCR_EL0_N_MASK U(0x1f)
#define PMCR_EL0_N_BITS (PMCR_EL0_N_MASK << PMCR_EL0_N_SHIFT) #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 * Definitions of MAIR encodings for device and normal memory
......
...@@ -307,7 +307,7 @@ DEFINE_SYSREG_READ_FUNC(ctr_el0) ...@@ -307,7 +307,7 @@ DEFINE_SYSREG_READ_FUNC(ctr_el0)
DEFINE_SYSREG_RW_FUNCS(mdcr_el2) DEFINE_SYSREG_RW_FUNCS(mdcr_el2)
DEFINE_SYSREG_RW_FUNCS(hstr_el2) DEFINE_SYSREG_RW_FUNCS(hstr_el2)
DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_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_el1, ICC_SRE_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2) DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2)
......
...@@ -87,22 +87,23 @@ ...@@ -87,22 +87,23 @@
#define CTX_AFSR1_EL1 U(0x98) #define CTX_AFSR1_EL1 U(0x98)
#define CTX_CONTEXTIDR_EL1 U(0xa0) #define CTX_CONTEXTIDR_EL1 U(0xa0)
#define CTX_VBAR_EL1 U(0xa8) #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 * If the platform is AArch64-only, there is no need to save and restore these
* AArch32 registers. * AArch32 registers.
*/ */
#if CTX_INCLUDE_AARCH32_REGS #if CTX_INCLUDE_AARCH32_REGS
#define CTX_SPSR_ABT U(0xb0) #define CTX_SPSR_ABT U(0xc0) /* Align to the next 16 byte boundary */
#define CTX_SPSR_UND U(0xb8) #define CTX_SPSR_UND U(0xc8)
#define CTX_SPSR_IRQ U(0xc0) #define CTX_SPSR_IRQ U(0xd0)
#define CTX_SPSR_FIQ U(0xc8) #define CTX_SPSR_FIQ U(0xd8)
#define CTX_DACR32_EL2 U(0xd0) #define CTX_DACR32_EL2 U(0xe0)
#define CTX_IFSR32_EL2 U(0xd8) #define CTX_IFSR32_EL2 U(0xe8)
#define CTX_FP_FPEXC32_EL2 U(0xe0) #define CTX_FP_FPEXC32_EL2 U(0xf0)
#define CTX_TIMER_SYSREGS_OFF U(0xf0) /* Align to the next 16 byte boundary */ #define CTX_TIMER_SYSREGS_OFF U(0x100) /* Align to the next 16 byte boundary */
#else #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__ */ #endif /* __CTX_INCLUDE_AARCH32_REGS__ */
/* /*
......
...@@ -74,6 +74,9 @@ func el1_sysregs_context_save ...@@ -74,6 +74,9 @@ func el1_sysregs_context_save
mrs x9, vbar_el1 mrs x9, vbar_el1
stp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] stp x17, x9, [x0, #CTX_CONTEXTIDR_EL1]
mrs x10, pmcr_el0
str x10, [x0, #CTX_PMCR_EL0]
/* Save AArch32 system registers if the build has instructed so */ /* Save AArch32 system registers if the build has instructed so */
#if CTX_INCLUDE_AARCH32_REGS #if CTX_INCLUDE_AARCH32_REGS
mrs x11, spsr_abt mrs x11, spsr_abt
...@@ -193,6 +196,9 @@ func el1_sysregs_context_restore ...@@ -193,6 +196,9 @@ func el1_sysregs_context_restore
msr contextidr_el1, x17 msr contextidr_el1, x17
msr vbar_el1, x9 msr vbar_el1, x9
ldr x10, [x0, #CTX_PMCR_EL0]
msr pmcr_el0, x10
/* Restore AArch32 system registers if the build has instructed so */ /* Restore AArch32 system registers if the build has instructed so */
#if CTX_INCLUDE_AARCH32_REGS #if CTX_INCLUDE_AARCH32_REGS
ldp x11, x12, [x0, #CTX_SPSR_ABT] ldp x11, x12, [x0, #CTX_SPSR_ABT]
......
...@@ -58,7 +58,7 @@ void cm_init(void) ...@@ -58,7 +58,7 @@ void cm_init(void)
static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t *ep) static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t *ep)
{ {
unsigned int security_state; unsigned int security_state;
uint32_t scr_el3; uint32_t scr_el3, pmcr_el0;
el3_state_t *state; el3_state_t *state;
gp_regs_t *gp_regs; gp_regs_t *gp_regs;
unsigned long sctlr_elx; unsigned long sctlr_elx;
...@@ -164,11 +164,35 @@ static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t ...@@ -164,11 +164,35 @@ static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t
/* /*
* Store the initialised SCTLR_EL1 value in the cpu_context - SCTLR_EL2 * Store the initialised SCTLR_EL1 value in the cpu_context - SCTLR_EL2
* and other EL2 resgisters are set up by cm_preapre_ns_entry() as they * and other EL2 registers are set up by cm_preapre_ns_entry() as they
* are not part of the stored cpu_context. * are not part of the stored cpu_context.
*/ */
write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx); write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx);
if (security_state == SECURE) {
/*
* Initialise PMCR_EL0 for secure context only, setting all
* fields rather than relying on hw. Some fields are
* architecturally UNKNOWN on reset.
*
* PMCR_EL0.LC: Set to one so that cycle counter overflow, that
* is recorded in PMOVSCLR_EL0[31], occurs on the increment
* that changes PMCCNTR_EL0[63] from 1 to 0.
*
* PMCR_EL0.DP: Set to one so that the cycle counter,
* PMCCNTR_EL0 does not count when event counting is prohibited.
*
* PMCR_EL0.X: Set to zero to disable export of events.
*
* PMCR_EL0.D: Set to zero so that, when enabled, PMCCNTR_EL0
* counts on every clock cycle.
*/
pmcr_el0 = ((PMCR_EL0_RESET_VAL | PMCR_EL0_LC_BIT
| PMCR_EL0_DP_BIT)
& ~(PMCR_EL0_X_BIT | PMCR_EL0_D_BIT));
write_ctx_reg(get_sysregs_ctx(ctx), CTX_PMCR_EL0, pmcr_el0);
}
/* Populate EL3 state so that we've the right context before doing ERET */ /* Populate EL3 state so that we've the right context before doing ERET */
state = get_el3state_ctx(ctx); state = get_el3state_ctx(ctx);
write_ctx_reg(state, CTX_SCR_EL3, scr_el3); write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment