aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Philippe Brucker <jean-philippe@linaro.org>2023-12-19 17:57:50 +0000
committerMichael Tokarev <mjt@tls.msk.ru>2023-12-20 19:07:05 +0300
commitc06aef082f21d897c1f929b10f6ab0800a54be26 (patch)
treeb6117050fc9fd3a2be52ea05d778c4b940533660
parent5b2fd6cf37352d671db09b54e4bc9d2ce707ca6d (diff)
target/arm/helper: Propagate MDCR_EL2.HPMN into PMCR_EL0.N
MDCR_EL2.HPMN allows an hypervisor to limit the number of PMU counters available to EL1 and EL0 (to keep the others to itself). QEMU already implements this split correctly, except for PMCR_EL0.N reads: the number of counters read by EL1 or EL0 should be the one configured in MDCR_EL2.HPMN. Cc: qemu-stable@nongnu.org Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Message-id: 20231215144652.4193815-2-jean-philippe@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> (cherry picked from commit 6980c31dec42b6daebf7fec13b2d39ed87bb4766) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
-rw-r--r--target/arm/helper.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 01822b9086..e4822f1672 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1474,6 +1474,22 @@ static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
pmu_op_finish(env);
}
+static uint64_t pmcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ uint64_t pmcr = env->cp15.c9_pmcr;
+
+ /*
+ * If EL2 is implemented and enabled for the current security state, reads
+ * of PMCR.N from EL1 or EL0 return the value of MDCR_EL2.HPMN or HDCR.HPMN.
+ */
+ if (arm_current_el(env) <= 1 && arm_is_el2_enabled(env)) {
+ pmcr &= ~PMCRN_MASK;
+ pmcr |= (env->cp15.mdcr_el2 & MDCR_HPMN) << PMCRN_SHIFT;
+ }
+
+ return pmcr;
+}
+
static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
@@ -7048,8 +7064,9 @@ static void define_pmu_regs(ARMCPU *cpu)
.fgt = FGT_PMCR_EL0,
.type = ARM_CP_IO | ARM_CP_ALIAS,
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
- .accessfn = pmreg_access, .writefn = pmcr_write,
- .raw_writefn = raw_write,
+ .accessfn = pmreg_access,
+ .readfn = pmcr_read, .raw_readfn = raw_read,
+ .writefn = pmcr_write, .raw_writefn = raw_write,
};
ARMCPRegInfo pmcr64 = {
.name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
@@ -7059,6 +7076,7 @@ static void define_pmu_regs(ARMCPU *cpu)
.type = ARM_CP_IO,
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
.resetvalue = cpu->isar.reset_pmcr_el0,
+ .readfn = pmcr_read, .raw_readfn = raw_read,
.writefn = pmcr_write, .raw_writefn = raw_write,
};