diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index 7769770b..47ed7cd5 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -684,7 +684,7 @@ typedef struct CPUARMState { * should first be updated to something sparse instead of the current * supported_event_map[] array. */ -#define MAX_EVENT_ID 0x24 +#define MAX_EVENT_ID 0x3c uint16_t supported_event_map[MAX_EVENT_ID + 1]; // Unicorn engine @@ -3392,6 +3392,13 @@ static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id) FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; } +static inline bool isar_feature_aa32_pmu_8_4(const ARMISARegisters *id) +{ + /* 0xf means "non-standard IMPDEF PMU" */ + return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 && + FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; +} + /* * 64-bit feature tests via id registers. */ @@ -3577,6 +3584,12 @@ static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id) FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; } +static inline bool isar_feature_aa64_pmu_8_4(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 && + FIELD_EX32(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; +} + /* * Feature tests for "does this exist in either 32-bit or 64-bit?" */ @@ -3595,6 +3608,11 @@ static inline bool isar_feature_any_pmu_8_1(const ARMISARegisters *id) return isar_feature_aa64_pmu_8_1(id) || isar_feature_aa32_pmu_8_1(id); } +static inline bool isar_feature_any_pmu_8_4(const ARMISARegisters *id) +{ + return isar_feature_aa64_pmu_8_4(id) || isar_feature_aa32_pmu_8_4(id); +} + /* * Forward to the above feature tests given an ARMCPU pointer. */ diff --git a/qemu/target/arm/helper.c b/qemu/target/arm/helper.c index 8c80a68f..78f1f7d2 100644 --- a/qemu/target/arm/helper.c +++ b/qemu/target/arm/helper.c @@ -979,6 +979,12 @@ static bool pmu_8_1_events_supported(CPUARMState *env) return cpu_isar_feature(any_pmu_8_1, env_archcpu(env)); } +static bool pmu_8_4_events_supported(CPUARMState *env) +{ + /* For events which are supported in any v8.1 PMU */ + return cpu_isar_feature(any_pmu_8_4, env_archcpu(env)); +} + static uint64_t zero_event_get_count(CPUARMState *env) { /* For events which on QEMU never fire, so their count is always zero */ @@ -1019,6 +1025,11 @@ static const pm_event pm_events[] = { .get_count = zero_event_get_count, .ns_per_count = zero_event_ns_per, }, + { .number = 0x03c, /* STALL */ + .supported = pmu_8_4_events_supported, + .get_count = zero_event_get_count, + .ns_per_count = zero_event_ns_per, + }, }; #define UNSUPPORTED_EVENT UINT16_MAX @@ -6209,6 +6220,15 @@ static void define_pmu_regs(ARMCPU *cpu) }; define_arm_cp_regs(cpu, v81_pmu_regs); } + if (cpu_isar_feature(any_pmu_8_4, cpu)) { + static const ARMCPRegInfo v84_pmmir = { + .name = "PMMIR_EL1", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 6, + .access = PL1_R, .accessfn = pmreg_access, .type = ARM_CP_CONST, + .resetvalue = 0 + }; + define_one_arm_cp_reg(cpu, &v84_pmmir); + } } /* We don't know until after realize whether there's a GICv3