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