diff options
author | davidcunado-arm <david.cunado@arm.com> | 2017-10-17 13:53:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-17 13:53:17 +0100 |
commit | ccd0c24cf89cb2195cbb38b6bb0639769afef7c5 (patch) | |
tree | 691f0f5f9759f66b9c5e454aaa44ec1fd932f307 /lib | |
parent | 5d2f87e8502d2f1dcb0d937c9ad96498e562451d (diff) | |
parent | 3e61b2b54336510475fbab83b7d97538f3ac5460 (diff) |
Merge pull request #1127 from davidcunado-arm/dc/pmrc_init
Init and save / restore of PMCR_EL0 / PMCR
Diffstat (limited to 'lib')
-rw-r--r-- | lib/el3_runtime/aarch64/context.S | 6 | ||||
-rw-r--r-- | lib/el3_runtime/aarch64/context_mgmt.c | 28 |
2 files changed, 32 insertions, 2 deletions
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index 8a6c11b7..db16a9f0 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -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] diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 3d26056a..21e86de0 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -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); |