1*c73686a1SBoyan Karatotev /* 2*c73686a1SBoyan Karatotev * Copyright (c) 2023, Arm Limited. All rights reserved. 3*c73686a1SBoyan Karatotev * 4*c73686a1SBoyan Karatotev * SPDX-License-Identifier: BSD-3-Clause 5*c73686a1SBoyan Karatotev */ 6*c73686a1SBoyan Karatotev 7*c73686a1SBoyan Karatotev #include <arch.h> 8*c73686a1SBoyan Karatotev #include <arch_features.h> 9*c73686a1SBoyan Karatotev #include <arch_helpers.h> 10*c73686a1SBoyan Karatotev #include <lib/extensions/pmuv3.h> 11*c73686a1SBoyan Karatotev 12*c73686a1SBoyan Karatotev static u_register_t init_mdcr_el2_hpmn(u_register_t mdcr_el2) 13*c73686a1SBoyan Karatotev { 14*c73686a1SBoyan Karatotev /* 15*c73686a1SBoyan Karatotev * Initialize MDCR_EL2.HPMN to its hardware reset value so we don't 16*c73686a1SBoyan Karatotev * throw anyone off who expects this to be sensible. 17*c73686a1SBoyan Karatotev */ 18*c73686a1SBoyan Karatotev mdcr_el2 &= ~MDCR_EL2_HPMN_MASK; 19*c73686a1SBoyan Karatotev mdcr_el2 |= ((read_pmcr_el0() >> PMCR_EL0_N_SHIFT) & PMCR_EL0_N_MASK); 20*c73686a1SBoyan Karatotev 21*c73686a1SBoyan Karatotev return mdcr_el2; 22*c73686a1SBoyan Karatotev } 23*c73686a1SBoyan Karatotev 24*c73686a1SBoyan Karatotev void pmuv3_enable(cpu_context_t *ctx) 25*c73686a1SBoyan Karatotev { 26*c73686a1SBoyan Karatotev #if CTX_INCLUDE_EL2_REGS 27*c73686a1SBoyan Karatotev u_register_t mdcr_el2; 28*c73686a1SBoyan Karatotev 29*c73686a1SBoyan Karatotev mdcr_el2 = read_ctx_reg(get_el2_sysregs_ctx(ctx), CTX_MDCR_EL2); 30*c73686a1SBoyan Karatotev mdcr_el2 = init_mdcr_el2_hpmn(mdcr_el2); 31*c73686a1SBoyan Karatotev write_ctx_reg(get_el2_sysregs_ctx(ctx), CTX_MDCR_EL2, mdcr_el2); 32*c73686a1SBoyan Karatotev #endif /* CTX_INCLUDE_EL2_REGS */ 33*c73686a1SBoyan Karatotev } 34*c73686a1SBoyan Karatotev 35*c73686a1SBoyan Karatotev void pmuv3_disable_el3(void) 36*c73686a1SBoyan Karatotev { 37*c73686a1SBoyan Karatotev u_register_t mdcr_el3 = read_mdcr_el3(); 38*c73686a1SBoyan Karatotev 39*c73686a1SBoyan Karatotev /* --------------------------------------------------------------------- 40*c73686a1SBoyan Karatotev * Initialise MDCR_EL3, setting all fields rather than relying on hw. 41*c73686a1SBoyan Karatotev * Some fields are architecturally UNKNOWN on reset. 42*c73686a1SBoyan Karatotev * 43*c73686a1SBoyan Karatotev * MDCR_EL3.MPMX: Set to zero to not affect event counters (when 44*c73686a1SBoyan Karatotev * SPME = 0). 45*c73686a1SBoyan Karatotev * 46*c73686a1SBoyan Karatotev * MDCR_EL3.MCCD: Set to one so that cycle counting by PMCCNTR_EL0 is 47*c73686a1SBoyan Karatotev * prohibited in EL3. This bit is RES0 in versions of the 48*c73686a1SBoyan Karatotev * architecture with FEAT_PMUv3p7 not implemented. 49*c73686a1SBoyan Karatotev * 50*c73686a1SBoyan Karatotev * MDCR_EL3.SCCD: Set to one so that cycle counting by PMCCNTR_EL0 is 51*c73686a1SBoyan Karatotev * prohibited in Secure state. This bit is RES0 in versions of the 52*c73686a1SBoyan Karatotev * architecture with FEAT_PMUv3p5 not implemented. 53*c73686a1SBoyan Karatotev * 54*c73686a1SBoyan Karatotev * MDCR_EL3.SPME: Set to zero so that event counting is prohibited in 55*c73686a1SBoyan Karatotev * Secure state (and explicitly EL3 with later revisions). If ARMv8.2 56*c73686a1SBoyan Karatotev * Debug is not implemented this bit does not have any effect on the 57*c73686a1SBoyan Karatotev * counters unless there is support for the implementation defined 58*c73686a1SBoyan Karatotev * authentication interface ExternalSecureNoninvasiveDebugEnabled(). 59*c73686a1SBoyan Karatotev * 60*c73686a1SBoyan Karatotev * The SPME/MPMX combination is a little tricky. Below is a small 61*c73686a1SBoyan Karatotev * summary if another combination is ever needed: 62*c73686a1SBoyan Karatotev * SPME | MPMX | secure world | EL3 63*c73686a1SBoyan Karatotev * ------------------------------------- 64*c73686a1SBoyan Karatotev * 0 | 0 | disabled | disabled 65*c73686a1SBoyan Karatotev * 1 | 0 | enabled | enabled 66*c73686a1SBoyan Karatotev * 0 | 1 | enabled | disabled 67*c73686a1SBoyan Karatotev * 1 | 1 | enabled | disabled only for counters 0 to 68*c73686a1SBoyan Karatotev * MDCR_EL2.HPMN - 1. Enabled for the rest 69*c73686a1SBoyan Karatotev */ 70*c73686a1SBoyan Karatotev mdcr_el3 = (mdcr_el3 | MDCR_SCCD_BIT | MDCR_MCCD_BIT) & 71*c73686a1SBoyan Karatotev ~(MDCR_MPMX_BIT | MDCR_SPME_BIT); 72*c73686a1SBoyan Karatotev write_mdcr_el3(mdcr_el3); 73*c73686a1SBoyan Karatotev 74*c73686a1SBoyan Karatotev /* --------------------------------------------------------------------- 75*c73686a1SBoyan Karatotev * Initialise PMCR_EL0 setting all fields rather than relying 76*c73686a1SBoyan Karatotev * on hw. Some fields are architecturally UNKNOWN on reset. 77*c73686a1SBoyan Karatotev * 78*c73686a1SBoyan Karatotev * PMCR_EL0.DP: Set to one so that the cycle counter, 79*c73686a1SBoyan Karatotev * PMCCNTR_EL0 does not count when event counting is prohibited. 80*c73686a1SBoyan Karatotev * Necessary on PMUv3 <= p7 where MDCR_EL3.{SCCD,MCCD} are not 81*c73686a1SBoyan Karatotev * available 82*c73686a1SBoyan Karatotev * 83*c73686a1SBoyan Karatotev * PMCR_EL0.X: Set to zero to disable export of events. 84*c73686a1SBoyan Karatotev * 85*c73686a1SBoyan Karatotev * PMCR_EL0.C: Set to one to reset PMCCNTR_EL0 to zero. 86*c73686a1SBoyan Karatotev * 87*c73686a1SBoyan Karatotev * PMCR_EL0.P: Set to one to reset each event counter PMEVCNTR<n>_EL0 to 88*c73686a1SBoyan Karatotev * zero. 89*c73686a1SBoyan Karatotev * 90*c73686a1SBoyan Karatotev * PMCR_EL0.E: Set to zero to disable cycle and event counters. 91*c73686a1SBoyan Karatotev * --------------------------------------------------------------------- 92*c73686a1SBoyan Karatotev */ 93*c73686a1SBoyan Karatotev write_pmcr_el0((read_pmcr_el0() | PMCR_EL0_DP_BIT | PMCR_EL0_C_BIT | 94*c73686a1SBoyan Karatotev PMCR_EL0_P_BIT) & ~(PMCR_EL0_X_BIT | PMCR_EL0_E_BIT)); 95*c73686a1SBoyan Karatotev } 96*c73686a1SBoyan Karatotev 97*c73686a1SBoyan Karatotev void pmuv3_init_el2_unused(void) 98*c73686a1SBoyan Karatotev { 99*c73686a1SBoyan Karatotev u_register_t mdcr_el2 = read_mdcr_el2(); 100*c73686a1SBoyan Karatotev 101*c73686a1SBoyan Karatotev /* 102*c73686a1SBoyan Karatotev * Initialise MDCR_EL2, setting all fields rather than 103*c73686a1SBoyan Karatotev * relying on hw. Some fields are architecturally 104*c73686a1SBoyan Karatotev * UNKNOWN on reset. 105*c73686a1SBoyan Karatotev * 106*c73686a1SBoyan Karatotev * MDCR_EL2.HLP: Set to one so that event counter overflow, that is 107*c73686a1SBoyan Karatotev * recorded in PMOVSCLR_EL0[0-30], occurs on the increment that changes 108*c73686a1SBoyan Karatotev * PMEVCNTR<n>_EL0[63] from 1 to 0, when ARMv8.5-PMU is implemented. 109*c73686a1SBoyan Karatotev * This bit is RES0 in versions of the architecture earlier than 110*c73686a1SBoyan Karatotev * ARMv8.5, setting it to 1 doesn't have any effect on them. 111*c73686a1SBoyan Karatotev * 112*c73686a1SBoyan Karatotev * MDCR_EL2.HCCD: Set to one to prohibit cycle counting at EL2. This bit 113*c73686a1SBoyan Karatotev * is RES0 in versions of the architecture with FEAT_PMUv3p5 not 114*c73686a1SBoyan Karatotev * implemented. 115*c73686a1SBoyan Karatotev * 116*c73686a1SBoyan Karatotev * MDCR_EL2.HPMD: Set to one so that event counting is 117*c73686a1SBoyan Karatotev * prohibited at EL2 for counter n < MDCR_EL2.HPMN. This bit is RES0 118*c73686a1SBoyan Karatotev * in versions of the architecture with FEAT_PMUv3p1 not implemented. 119*c73686a1SBoyan Karatotev * 120*c73686a1SBoyan Karatotev * MDCR_EL2.HPME: Set to zero to disable event counters for counters 121*c73686a1SBoyan Karatotev * n >= MDCR_EL2.HPMN. 122*c73686a1SBoyan Karatotev * 123*c73686a1SBoyan Karatotev * MDCR_EL2.TPM: Set to zero so that Non-secure EL0 and 124*c73686a1SBoyan Karatotev * EL1 accesses to all Performance Monitors registers 125*c73686a1SBoyan Karatotev * are not trapped to EL2. 126*c73686a1SBoyan Karatotev * 127*c73686a1SBoyan Karatotev * MDCR_EL2.TPMCR: Set to zero so that Non-secure EL0 128*c73686a1SBoyan Karatotev * and EL1 accesses to the PMCR_EL0 or PMCR are not 129*c73686a1SBoyan Karatotev * trapped to EL2. 130*c73686a1SBoyan Karatotev */ 131*c73686a1SBoyan Karatotev mdcr_el2 = (mdcr_el2 | MDCR_EL2_HLP_BIT | MDCR_EL2_HPMD_BIT | 132*c73686a1SBoyan Karatotev MDCR_EL2_HCCD_BIT) & 133*c73686a1SBoyan Karatotev ~(MDCR_EL2_HPME_BIT | MDCR_EL2_TPM_BIT | MDCR_EL2_TPMCR_BIT); 134*c73686a1SBoyan Karatotev mdcr_el2 = init_mdcr_el2_hpmn(mdcr_el2); 135*c73686a1SBoyan Karatotev write_mdcr_el2(mdcr_el2); 136*c73686a1SBoyan Karatotev } 137