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