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