refactor(pmu): convert FEAT_MTPMU to C and move to persistent register init
The FEAT_MTPMU feature disable runs very early after reset. This means,
it needs to be written in assembly, since the C runtime has not been
initialised yet.
However, there is no need for it to be initialised so soon. The PMU
state is only relevant after TF-A has relinquished control. The code
to do this is also very verbose and difficult to read. Delaying the
initialisation allows for it to happen with the rest of the PMU. Align
with FEAT_STATE in the process.
BREAKING CHANGE: This patch explicitly breaks the EL2 entry path. It is
currently unsupported.
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
Change-Id: I2aa659d026fbdb75152469f6d19812ece3488c6f
diff --git a/lib/extensions/pmuv3/aarch64/pmuv3.c b/lib/extensions/pmuv3/aarch64/pmuv3.c
index 107d12e..f83a5ee 100644
--- a/lib/extensions/pmuv3/aarch64/pmuv3.c
+++ b/lib/extensions/pmuv3/aarch64/pmuv3.c
@@ -32,6 +32,22 @@
#endif /* CTX_INCLUDE_EL2_REGS */
}
+static u_register_t mtpmu_disable_el3(u_register_t mdcr_el3)
+{
+ if (!is_feat_mtpmu_supported()) {
+ return mdcr_el3;
+ }
+
+ /*
+ * MDCR_EL3.MTPME = 0
+ * FEAT_MTPMU is disabled. The Effective value of PMEVTYPER<n>_EL0.MT is
+ * zero.
+ */
+ mdcr_el3 &= ~MDCR_MTPME_BIT;
+
+ return mdcr_el3;
+}
+
void pmuv3_disable_el3(void)
{
u_register_t mdcr_el3 = read_mdcr_el3();
@@ -69,6 +85,7 @@
*/
mdcr_el3 = (mdcr_el3 | MDCR_SCCD_BIT | MDCR_MCCD_BIT) &
~(MDCR_MPMX_BIT | MDCR_SPME_BIT);
+ mdcr_el3 = mtpmu_disable_el3(mdcr_el3);
write_mdcr_el3(mdcr_el3);
/* ---------------------------------------------------------------------
@@ -94,6 +111,22 @@
PMCR_EL0_P_BIT) & ~(PMCR_EL0_X_BIT | PMCR_EL0_E_BIT));
}
+static u_register_t mtpmu_disable_el2(u_register_t mdcr_el2)
+{
+ if (!is_feat_mtpmu_supported()) {
+ return mdcr_el2;
+ }
+
+ /*
+ * MDCR_EL2.MTPME = 0
+ * FEAT_MTPMU is disabled. The Effective value of PMEVTYPER<n>_EL0.MT is
+ * zero.
+ */
+ mdcr_el2 &= ~MDCR_EL2_MTPME;
+
+ return mdcr_el2;
+}
+
void pmuv3_init_el2_unused(void)
{
u_register_t mdcr_el2 = read_mdcr_el2();
@@ -132,5 +165,6 @@
MDCR_EL2_HCCD_BIT) &
~(MDCR_EL2_HPME_BIT | MDCR_EL2_TPM_BIT | MDCR_EL2_TPMCR_BIT);
mdcr_el2 = init_mdcr_el2_hpmn(mdcr_el2);
+ mdcr_el2 = mtpmu_disable_el2(mdcr_el2);
write_mdcr_el2(mdcr_el2);
}