In the PMUv3, a new AArch32 64-bit (MCRR/MRRC) accessor for the PMCCNTR was added. In QEMU we forgot to implement this, so only provide the 32-bit accessor. Since we have a 64-bit PMCCNTR sysreg for AArch64, adding the 64-bit AArch32 version is easy.
We add the PMCCNTR to the v8_cp_reginfo because PMUv3 was added in the ARMv8 architecture. This is consistent with how we handle the existing PMCCNTR support, where we always implement it for all v7 CPUs. This is arguably something we should clean up so it is gated on ARM_FEATURE_PMU and/or an ID register check for the relevant PMU version, but we should do that as its own tidyup rather than being inconsistent between this PMCCNTR accessor and the others. Since the register name is the same as the 32-bit PMCCNTR, we set ARM_CP_NO_GDB on the 32-bit one to avoid generating an invalid GDB XML. See https://developer.arm.com/documentation/ddi0601/2024-06/AArch32-Registers/PMCCNTR--Performance-Monitors-Cycle-Count-Register?lang=en Change v2->v3: - Moved ARM_CP_NO_GDB to the 32-bit register if Armv8 is supported Changes v1->v2: - Moved to new file - Updated commit message - Added ARM_CP_NO_GDB Signed-off-by: Alex Richardson <alexrichard...@google.com> --- target/arm/cpregs-pmu.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/target/arm/cpregs-pmu.c b/target/arm/cpregs-pmu.c index 0f295b1376..144e339c76 100644 --- a/target/arm/cpregs-pmu.c +++ b/target/arm/cpregs-pmu.c @@ -1067,11 +1067,6 @@ static const ARMCPRegInfo v7_pm_reginfo[] = { .fgt = FGT_PMSELR_EL0, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmselr), .writefn = pmselr_write, .raw_writefn = raw_write, }, - { .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0, - .access = PL0_RW, .resetvalue = 0, .type = ARM_CP_ALIAS | ARM_CP_IO, - .fgt = FGT_PMCCNTR_EL0, - .readfn = pmccntr_read, .writefn = pmccntr_write32, - .accessfn = pmreg_access_ccntr }, { .name = "PMCCNTR_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 0, .access = PL0_RW, .accessfn = pmreg_access_ccntr, @@ -1211,6 +1206,19 @@ void define_pm_cpregs(ARMCPU *cpu) define_one_arm_cp_reg(cpu, &pmcr); define_one_arm_cp_reg(cpu, &pmcr64); define_arm_cp_regs(cpu, v7_pm_reginfo); + /* When Armv8 is supported, PMCCNTR aliases the new 64-bit version */ + ARMCPRegInfo pmccntr = { + .name = "PMCCNTR", + .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0, + .access = PL0_RW, .accessfn = pmreg_access_ccntr, + .resetvalue = 0, .type = ARM_CP_ALIAS | ARM_CP_IO, + .fgt = FGT_PMCCNTR_EL0, + .readfn = pmccntr_read, .writefn = pmccntr_write32, + }; + if (arm_feature(env, ARM_FEATURE_V8)) { + pmccntr.type |= ARM_CP_NO_GDB; + } + define_one_arm_cp_reg(cpu, &pmccntr); for (unsigned i = 0, pmcrn = pmu_num_counters(env); i < pmcrn; i++) { g_autofree char *pmevcntr_name = g_strdup_printf("PMEVCNTR%d", i); @@ -1276,6 +1284,12 @@ void define_pm_cpregs(ARMCPU *cpu) .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST, .fgt = FGT_PMCEIDN_EL0, .resetvalue = cpu->pmceid1 }, + { .name = "PMCCNTR", .state = ARM_CP_STATE_AA32, + .cp = 15, .crm = 9, .opc1 = 0, + .access = PL0_RW, .accessfn = pmreg_access_ccntr, .resetvalue = 0, + .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_64BIT, + .fgt = FGT_PMCCNTR_EL0, .readfn = pmccntr_read, + .writefn = pmccntr_write, }, }; define_arm_cp_regs(cpu, v8_pm_reginfo); } -- 2.50.1.470.g6ba607880d-goog