]> www.infradead.org Git - users/hch/misc.git/commitdiff
KVM: arm64: Move PMUVer filtering into KVM code
authorOliver Upton <oliver.upton@linux.dev>
Wed, 5 Mar 2025 20:26:35 +0000 (12:26 -0800)
committerOliver Upton <oliver.upton@linux.dev>
Tue, 11 Mar 2025 19:54:29 +0000 (12:54 -0700)
The supported guest PMU version on a particular platform is ultimately a
KVM decision. Move PMUVer filtering into KVM code.

Tested-by: Janne Grunau <j@jannau.net>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250305202641.428114-9-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/include/asm/cpufeature.h
arch/arm64/kvm/pmu-emul.c

index 0eff048848b84ce62aa391c7dc8cc0b0a73ac35a..c4326f1cb917639ef0810676fbded49f37242472 100644 (file)
@@ -525,29 +525,6 @@ cpuid_feature_extract_unsigned_field(u64 features, int field)
        return cpuid_feature_extract_unsigned_field_width(features, field, 4);
 }
 
-/*
- * Fields that identify the version of the Performance Monitors Extension do
- * not follow the standard ID scheme. See ARM DDI 0487E.a page D13-2825,
- * "Alternative ID scheme used for the Performance Monitors Extension version".
- */
-static inline u64 __attribute_const__
-cpuid_feature_cap_perfmon_field(u64 features, int field, u64 cap)
-{
-       u64 val = cpuid_feature_extract_unsigned_field(features, field);
-       u64 mask = GENMASK_ULL(field + 3, field);
-
-       /* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
-       if (val == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
-               val = 0;
-
-       if (val > cap) {
-               features &= ~mask;
-               features |= (cap << field) & mask;
-       }
-
-       return features;
-}
-
 static inline u64 arm64_ftr_mask(const struct arm64_ftr_bits *ftrp)
 {
        return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
index fee3d0003d54480ec1c1e83f0dcc5f99caf1510d..0a2023aabe184bc53a2f1d05d29f4b496b8e3c82 100644 (file)
@@ -1226,13 +1226,16 @@ int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 
 u8 kvm_arm_pmu_get_pmuver_limit(void)
 {
-       u64 tmp;
+       unsigned int pmuver;
 
-       tmp = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
-       tmp = cpuid_feature_cap_perfmon_field(tmp,
-                                             ID_AA64DFR0_EL1_PMUVer_SHIFT,
-                                             ID_AA64DFR0_EL1_PMUVer_V3P5);
-       return FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), tmp);
+       pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer,
+                              read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1));
+
+       /* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
+       if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
+               return 0;
+
+       return min(pmuver, ID_AA64DFR0_EL1_PMUVer_V3P5);
 }
 
 /**