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 { 26fecf325bSSaivardhan Thatikonda if (is_feat_mtpmu_supported()) { 2783a4dae1SBoyan Karatotev /* 2883a4dae1SBoyan Karatotev * MDCR_EL3.MTPME = 0 2983a4dae1SBoyan Karatotev * FEAT_MTPMU is disabled. The Effective value of PMEVTYPER<n>_EL0.MT is 3083a4dae1SBoyan Karatotev * zero. 3183a4dae1SBoyan Karatotev */ 3283a4dae1SBoyan Karatotev mdcr_el3 &= ~MDCR_MTPME_BIT; 33fecf325bSSaivardhan Thatikonda } 3483a4dae1SBoyan Karatotev 3583a4dae1SBoyan Karatotev return mdcr_el3; 3683a4dae1SBoyan Karatotev } 3783a4dae1SBoyan Karatotev 38c95aa2ebSMateusz Sulimowicz void pmuv3_enable(cpu_context_t *ctx) 39c73686a1SBoyan Karatotev { 40c95aa2ebSMateusz Sulimowicz #if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) 41c95aa2ebSMateusz Sulimowicz u_register_t mdcr_el2_val; 42c95aa2ebSMateusz Sulimowicz 43c95aa2ebSMateusz Sulimowicz mdcr_el2_val = read_el2_ctx_common(get_el2_sysregs_ctx(ctx), mdcr_el2); 44c95aa2ebSMateusz Sulimowicz mdcr_el2_val = init_mdcr_el2_hpmn(mdcr_el2_val); 45c95aa2ebSMateusz Sulimowicz write_el2_ctx_common(get_el2_sysregs_ctx(ctx), mdcr_el2, mdcr_el2_val); 46c95aa2ebSMateusz Sulimowicz #endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */ 47c95aa2ebSMateusz Sulimowicz 48c95aa2ebSMateusz Sulimowicz el3_state_t *state = get_el3state_ctx(ctx); 49c95aa2ebSMateusz Sulimowicz u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3); 50c73686a1SBoyan Karatotev 51c73686a1SBoyan Karatotev /* --------------------------------------------------------------------- 52c73686a1SBoyan Karatotev * MDCR_EL3.MPMX: Set to zero to not affect event counters (when 53c73686a1SBoyan Karatotev * SPME = 0). 54c73686a1SBoyan Karatotev * 55c73686a1SBoyan Karatotev * MDCR_EL3.MCCD: Set to one so that cycle counting by PMCCNTR_EL0 is 56c73686a1SBoyan Karatotev * prohibited in EL3. This bit is RES0 in versions of the 57c73686a1SBoyan Karatotev * architecture with FEAT_PMUv3p7 not implemented. 58c73686a1SBoyan Karatotev * 59c73686a1SBoyan Karatotev * MDCR_EL3.SCCD: Set to one so that cycle counting by PMCCNTR_EL0 is 60c73686a1SBoyan Karatotev * prohibited in Secure state. This bit is RES0 in versions of the 61c73686a1SBoyan Karatotev * architecture with FEAT_PMUv3p5 not implemented. 62c73686a1SBoyan Karatotev * 63c73686a1SBoyan Karatotev * MDCR_EL3.SPME: Set to zero so that event counting is prohibited in 64c73686a1SBoyan Karatotev * Secure state (and explicitly EL3 with later revisions). If ARMv8.2 65c73686a1SBoyan Karatotev * Debug is not implemented this bit does not have any effect on the 66c73686a1SBoyan Karatotev * counters unless there is support for the implementation defined 67c73686a1SBoyan Karatotev * authentication interface ExternalSecureNoninvasiveDebugEnabled(). 68c73686a1SBoyan Karatotev * 69c73686a1SBoyan Karatotev * The SPME/MPMX combination is a little tricky. Below is a small 70c73686a1SBoyan Karatotev * summary if another combination is ever needed: 71c73686a1SBoyan Karatotev * SPME | MPMX | secure world | EL3 72c73686a1SBoyan Karatotev * ------------------------------------- 73c73686a1SBoyan Karatotev * 0 | 0 | disabled | disabled 74c73686a1SBoyan Karatotev * 1 | 0 | enabled | enabled 75c73686a1SBoyan Karatotev * 0 | 1 | enabled | disabled 76c73686a1SBoyan Karatotev * 1 | 1 | enabled | disabled only for counters 0 to 77c73686a1SBoyan Karatotev * MDCR_EL2.HPMN - 1. Enabled for the rest 78ece8f7d7SBoyan Karatotev * 79ba9e6a34SAndre Przywara * MDCR_EL3.EnPM2: Set to one so that various PMUv3p9 related system 80ba9e6a34SAndre Przywara * register accesses do not trap to EL3. 81ba9e6a34SAndre Przywara * 82ece8f7d7SBoyan Karatotev * MDCR_EL3.TPM: Set to zero so that EL0, EL1, and EL2 System register 83ece8f7d7SBoyan Karatotev * accesses to all Performance Monitors registers do not trap to EL3. 84*714a1a93SManish Pandey * 85*714a1a93SManish Pandey * MDCR_EL3.PMEE set to 0b01 to delegate PMU IRQ and Profiling exception 86*714a1a93SManish Pandey * control to MDCR_EL2, to allow lower ELs own this policy. 87c73686a1SBoyan Karatotev */ 88ba9e6a34SAndre Przywara mdcr_el3_val |= MDCR_SCCD_BIT | MDCR_MCCD_BIT | MDCR_EnPM2_BIT; 89ba9e6a34SAndre Przywara mdcr_el3_val &= ~(MDCR_MPMX_BIT | MDCR_SPME_BIT | MDCR_TPM_BIT); 90c95aa2ebSMateusz Sulimowicz mdcr_el3_val = mtpmu_disable_el3(mdcr_el3_val); 91c73686a1SBoyan Karatotev 92*714a1a93SManish Pandey if (is_feat_ebep_supported()) { 93*714a1a93SManish Pandey mdcr_el3_val |= MDCR_PMEE(MDCR_PMEE_CTRL_EL2); 94*714a1a93SManish Pandey } 95*714a1a93SManish Pandey 96c95aa2ebSMateusz Sulimowicz write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val); 97c95aa2ebSMateusz Sulimowicz } 98c95aa2ebSMateusz Sulimowicz 99c95aa2ebSMateusz Sulimowicz void pmuv3_init_el3(void) 100c95aa2ebSMateusz Sulimowicz { 101c73686a1SBoyan Karatotev /* --------------------------------------------------------------------- 102c73686a1SBoyan Karatotev * Initialise PMCR_EL0 setting all fields rather than relying 103c73686a1SBoyan Karatotev * on hw. Some fields are architecturally UNKNOWN on reset. 104c73686a1SBoyan Karatotev * 105c73686a1SBoyan Karatotev * PMCR_EL0.DP: Set to one so that the cycle counter, 106c73686a1SBoyan Karatotev * PMCCNTR_EL0 does not count when event counting is prohibited. 107c73686a1SBoyan Karatotev * Necessary on PMUv3 <= p7 where MDCR_EL3.{SCCD,MCCD} are not 108c73686a1SBoyan Karatotev * available 109c73686a1SBoyan Karatotev * 110c73686a1SBoyan Karatotev * PMCR_EL0.X: Set to zero to disable export of events. 111c73686a1SBoyan Karatotev * 112c73686a1SBoyan Karatotev * PMCR_EL0.C: Set to one to reset PMCCNTR_EL0 to zero. 113c73686a1SBoyan Karatotev * 114c73686a1SBoyan Karatotev * PMCR_EL0.P: Set to one to reset each event counter PMEVCNTR<n>_EL0 to 115c73686a1SBoyan Karatotev * zero. 116c73686a1SBoyan Karatotev * 117c73686a1SBoyan Karatotev * PMCR_EL0.E: Set to zero to disable cycle and event counters. 118c73686a1SBoyan Karatotev * --------------------------------------------------------------------- 119c73686a1SBoyan Karatotev */ 120c73686a1SBoyan Karatotev write_pmcr_el0((read_pmcr_el0() | PMCR_EL0_DP_BIT | PMCR_EL0_C_BIT | 121c73686a1SBoyan Karatotev PMCR_EL0_P_BIT) & ~(PMCR_EL0_X_BIT | PMCR_EL0_E_BIT)); 122c73686a1SBoyan Karatotev } 123c73686a1SBoyan Karatotev 12483a4dae1SBoyan Karatotev static u_register_t mtpmu_disable_el2(u_register_t mdcr_el2) 12583a4dae1SBoyan Karatotev { 126fecf325bSSaivardhan Thatikonda if (is_feat_mtpmu_supported()) { 12783a4dae1SBoyan Karatotev /* 12883a4dae1SBoyan Karatotev * MDCR_EL2.MTPME = 0 12983a4dae1SBoyan Karatotev * FEAT_MTPMU is disabled. The Effective value of PMEVTYPER<n>_EL0.MT is 13083a4dae1SBoyan Karatotev * zero. 13183a4dae1SBoyan Karatotev */ 13283a4dae1SBoyan Karatotev mdcr_el2 &= ~MDCR_EL2_MTPME; 133fecf325bSSaivardhan Thatikonda } 13483a4dae1SBoyan Karatotev return mdcr_el2; 13583a4dae1SBoyan Karatotev } 13683a4dae1SBoyan Karatotev 137c73686a1SBoyan Karatotev void pmuv3_init_el2_unused(void) 138c73686a1SBoyan Karatotev { 139c73686a1SBoyan Karatotev u_register_t mdcr_el2 = read_mdcr_el2(); 140c73686a1SBoyan Karatotev 141c73686a1SBoyan Karatotev /* 142c73686a1SBoyan Karatotev * Initialise MDCR_EL2, setting all fields rather than 143c73686a1SBoyan Karatotev * relying on hw. Some fields are architecturally 144c73686a1SBoyan Karatotev * UNKNOWN on reset. 145c73686a1SBoyan Karatotev * 146c73686a1SBoyan Karatotev * MDCR_EL2.HLP: Set to one so that event counter overflow, that is 147c73686a1SBoyan Karatotev * recorded in PMOVSCLR_EL0[0-30], occurs on the increment that changes 148c73686a1SBoyan Karatotev * PMEVCNTR<n>_EL0[63] from 1 to 0, when ARMv8.5-PMU is implemented. 149c73686a1SBoyan Karatotev * This bit is RES0 in versions of the architecture earlier than 150c73686a1SBoyan Karatotev * ARMv8.5, setting it to 1 doesn't have any effect on them. 151c73686a1SBoyan Karatotev * 152c73686a1SBoyan Karatotev * MDCR_EL2.HCCD: Set to one to prohibit cycle counting at EL2. This bit 153c73686a1SBoyan Karatotev * is RES0 in versions of the architecture with FEAT_PMUv3p5 not 154c73686a1SBoyan Karatotev * implemented. 155c73686a1SBoyan Karatotev * 156c73686a1SBoyan Karatotev * MDCR_EL2.HPMD: Set to one so that event counting is 157c73686a1SBoyan Karatotev * prohibited at EL2 for counter n < MDCR_EL2.HPMN. This bit is RES0 158c73686a1SBoyan Karatotev * in versions of the architecture with FEAT_PMUv3p1 not implemented. 159c73686a1SBoyan Karatotev * 160c73686a1SBoyan Karatotev * MDCR_EL2.HPME: Set to zero to disable event counters for counters 161c73686a1SBoyan Karatotev * n >= MDCR_EL2.HPMN. 162c73686a1SBoyan Karatotev * 163c73686a1SBoyan Karatotev * MDCR_EL2.TPM: Set to zero so that Non-secure EL0 and 164c73686a1SBoyan Karatotev * EL1 accesses to all Performance Monitors registers 165c73686a1SBoyan Karatotev * are not trapped to EL2. 166c73686a1SBoyan Karatotev * 167c73686a1SBoyan Karatotev * MDCR_EL2.TPMCR: Set to zero so that Non-secure EL0 168c73686a1SBoyan Karatotev * and EL1 accesses to the PMCR_EL0 or PMCR are not 169c73686a1SBoyan Karatotev * trapped to EL2. 170c73686a1SBoyan Karatotev */ 171c73686a1SBoyan Karatotev mdcr_el2 = (mdcr_el2 | MDCR_EL2_HLP_BIT | MDCR_EL2_HPMD_BIT | 172c73686a1SBoyan Karatotev MDCR_EL2_HCCD_BIT) & 173c73686a1SBoyan Karatotev ~(MDCR_EL2_HPME_BIT | MDCR_EL2_TPM_BIT | MDCR_EL2_TPMCR_BIT); 174c73686a1SBoyan Karatotev mdcr_el2 = init_mdcr_el2_hpmn(mdcr_el2); 17583a4dae1SBoyan Karatotev mdcr_el2 = mtpmu_disable_el2(mdcr_el2); 176c73686a1SBoyan Karatotev write_mdcr_el2(mdcr_el2); 177c73686a1SBoyan Karatotev } 178