]> www.infradead.org Git - users/hch/misc.git/commitdiff
arm64: Enable IMP DEF PMUv3 traps on Apple M*
authorOliver Upton <oliver.upton@linux.dev>
Wed, 5 Mar 2025 20:30:40 +0000 (12:30 -0800)
committerOliver Upton <oliver.upton@linux.dev>
Tue, 11 Mar 2025 19:54:30 +0000 (12:54 -0700)
Apple M1 and M2 CPUs support IMPDEF traps of the PMUv3 sysregs, allowing
a hypervisor to virtualize an architectural PMU for a VM. Flip the
appropriate bit in HACR_EL2 on supporting hardware.

Tested-by: Janne Grunau <j@jannau.net>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250305203040.428448-1-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kernel/cpu_errata.c

index 7ce5558628951860d196e58f5bd9e9b5629a1014..a1e16b156fab351278ce001d14e8e36dbe2623f9 100644 (file)
@@ -194,6 +194,43 @@ has_neoverse_n1_erratum_1542419(const struct arm64_cpu_capabilities *entry,
        return is_midr_in_range(midr, &range) && has_dic;
 }
 
+static const struct midr_range impdef_pmuv3_cpus[] = {
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_PRO),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_PRO),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_MAX),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_MAX),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_PRO),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_PRO),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_MAX),
+       MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_MAX),
+       {},
+};
+
+static bool has_impdef_pmuv3(const struct arm64_cpu_capabilities *entry, int scope)
+{
+       u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
+       unsigned int pmuver;
+
+       if (!is_kernel_in_hyp_mode())
+               return false;
+
+       pmuver = cpuid_feature_extract_unsigned_field(dfr0,
+                                                     ID_AA64DFR0_EL1_PMUVer_SHIFT);
+       if (pmuver != ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
+               return false;
+
+       return is_midr_in_range_list(read_cpuid_id(), impdef_pmuv3_cpus);
+}
+
+static void cpu_enable_impdef_pmuv3_traps(const struct arm64_cpu_capabilities *__unused)
+{
+       sysreg_clear_set_s(SYS_HACR_EL2, 0, BIT(56));
+}
+
 #ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
 static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
@@ -794,6 +831,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                                        {}
                                })),
        },
+       {
+               .desc = "Apple IMPDEF PMUv3 Traps",
+               .capability = ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS,
+               .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+               .matches = has_impdef_pmuv3,
+               .cpu_enable = cpu_enable_impdef_pmuv3_traps,
+       },
        {
        }
 };