Merge pull request #1127 from davidcunado-arm/dc/pmrc_init

Init and save / restore of PMCR_EL0 / PMCR
This commit is contained in:
davidcunado-arm 2017-10-17 13:53:17 +01:00 committed by GitHub
commit ccd0c24cf8
9 changed files with 83 additions and 15 deletions

View File

@ -162,6 +162,15 @@ func handle_smc
stcopr r0, SCR
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 */
/* Check whether an SMC64 is issued */
tst r0, #(FUNCID_CC_MASK << FUNCID_CC_SHIFT)
@ -210,6 +219,15 @@ func handle_fiq
stcopr r0, SCR
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}
bl sp_min_fiq
pop {r0, r3}

View File

@ -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

View File

@ -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 <cassert.h>
@ -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;
/*

View File

@ -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}

View File

@ -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

View File

@ -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)

View File

@ -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__ */
/*

View File

@ -74,6 +74,9 @@ func el1_sysregs_context_save
mrs x9, vbar_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 */
#if CTX_INCLUDE_AARCH32_REGS
mrs x11, spsr_abt
@ -193,6 +196,9 @@ func el1_sysregs_context_restore
msr contextidr_el1, x17
msr vbar_el1, x9
ldr x10, [x0, #CTX_PMCR_EL0]
msr pmcr_el0, x10
/* Restore AArch32 system registers if the build has instructed so */
#if CTX_INCLUDE_AARCH32_REGS
ldp x11, x12, [x0, #CTX_SPSR_ABT]

View File

@ -58,7 +58,7 @@ void cm_init(void)
static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t *ep)
{
unsigned int security_state;
uint32_t scr_el3;
uint32_t scr_el3, pmcr_el0;
el3_state_t *state;
gp_regs_t *gp_regs;
unsigned long sctlr_elx;
@ -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
* 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.
*/
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 */
state = get_el3state_ctx(ctx);
write_ctx_reg(state, CTX_SCR_EL3, scr_el3);