From: Smail AIDER Date: Tue, 26 Aug 2025 10:21:28 +0000 (+0100) Subject: target/arm: Trap PMCR when MDCR_EL2.TPMCR is set X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=186db6a73bc5c01026bb9f4f4a59e442c0156841;p=thirdparty%2Fqemu.git target/arm: Trap PMCR when MDCR_EL2.TPMCR is set Trap PMCR_EL0 or PMCR accesses to EL2 when MDCR_EL2.TPMCR is set. Similar to MDCR_EL2.TPM, MDCR_EL2.TPMCR allows trapping EL0 and EL1 accesses to the PMCR register to EL2. Cc: qemu-stable@nongnu.org Signed-off-by: Smail AIDER Reviewed-by: Richard Henderson Message-id: 20250811112143.1577055-2-smail.aider@huawei.com Message-Id: <20250722131925.2119169-1-smail.aider@huawei.com> Signed-off-by: Peter Maydell --- diff --git a/target/arm/cpregs-pmu.c b/target/arm/cpregs-pmu.c index 9c4431c18ba..31c01eddc87 100644 --- a/target/arm/cpregs-pmu.c +++ b/target/arm/cpregs-pmu.c @@ -228,22 +228,27 @@ static bool event_supported(uint16_t number) return supported_event_map[number] != UNSUPPORTED_EVENT; } -static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) +static CPAccessResult do_pmreg_access(CPUARMState *env, bool is_pmcr) { /* * Performance monitor registers user accessibility is controlled - * by PMUSERENR. MDCR_EL2.TPM and MDCR_EL3.TPM allow configurable + * by PMUSERENR. MDCR_EL2.TPM/TPMCR and MDCR_EL3.TPM allow configurable * trapping to EL2 or EL3 for other accesses. */ int el = arm_current_el(env); - uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); if (el == 0 && !(env->cp15.c9_pmuserenr & 1)) { return CP_ACCESS_TRAP_EL1; } - if (el < 2 && (mdcr_el2 & MDCR_TPM)) { - return CP_ACCESS_TRAP_EL2; + if (el < 2) { + uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); + + if (mdcr_el2 & MDCR_TPM) { + return CP_ACCESS_TRAP_EL2; + } + if (is_pmcr && (mdcr_el2 & MDCR_TPMCR)) { + return CP_ACCESS_TRAP_EL2; + } } if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) { return CP_ACCESS_TRAP_EL3; @@ -252,6 +257,19 @@ static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri, return CP_ACCESS_OK; } +static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + return do_pmreg_access(env, false); +} + +static CPAccessResult pmreg_access_pmcr(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + return do_pmreg_access(env, true); +} + static CPAccessResult pmreg_access_xevcntr(CPUARMState *env, const ARMCPRegInfo *ri, bool isread) @@ -1187,14 +1205,14 @@ void define_pm_cpregs(ARMCPU *cpu) .fgt = FGT_PMCR_EL0, .type = ARM_CP_IO | ARM_CP_ALIAS, .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr), - .accessfn = pmreg_access, + .accessfn = pmreg_access_pmcr, .readfn = pmcr_read, .raw_readfn = raw_read, .writefn = pmcr_write, .raw_writefn = raw_write, }; const ARMCPRegInfo pmcr64 = { .name = "PMCR_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 0, - .access = PL0_RW, .accessfn = pmreg_access, + .access = PL0_RW, .accessfn = pmreg_access_pmcr, .fgt = FGT_PMCR_EL0, .type = ARM_CP_IO, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),