mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-15 00:54:22 +00:00
Merge pull request #1127 from davidcunado-arm/dc/pmrc_init
Init and save / restore of PMCR_EL0 / PMCR
This commit is contained in:
commit
ccd0c24cf8
9 changed files with 83 additions and 15 deletions
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
/*
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue