summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Deacon <will@kernel.org>2026-06-14 14:18:06 +0300
committerWill Deacon <will@kernel.org>2026-06-14 14:18:06 +0300
commit3594da9b7a7cf690d896310d46bf15cebcf540df (patch)
tree5e614581fae2b7ba7edc67c06e41d307be297ecf
parentdf3daf49a8a05751b34ec40c46ac6d9c47e9ec22 (diff)
parent50a42e03cdbd77d93366d301db3d367dce78eda6 (diff)
downloadlinux-3594da9b7a7cf690d896310d46bf15cebcf540df.tar.xz
Merge branch 'for-next/mpam' into for-next/core
* for-next/mpam: arm_mpam: Update architecture version check for MPAM MSC arm64: cpufeature: Add support for the MPAM v0.1 architecture version
-rw-r--r--arch/arm64/include/asm/cpufeature.h7
-rw-r--r--arch/arm64/include/asm/el2_setup.h4
-rw-r--r--arch/arm64/kernel/cpufeature.c15
-rw-r--r--drivers/resctrl/mpam_devices.c23
4 files changed, 41 insertions, 8 deletions
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 4de51f8d92cb..a57870fa96db 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -620,6 +620,13 @@ static inline bool id_aa64pfr0_mpam(u64 pfr0)
return val > 0;
}
+static inline bool id_aa64pfr1_mpamfrac(u64 pfr1)
+{
+ u32 val = cpuid_feature_extract_unsigned_field(pfr1, ID_AA64PFR1_EL1_MPAM_frac_SHIFT);
+
+ return val > 0;
+}
+
static inline bool id_aa64pfr1_mte(u64 pfr1)
{
u32 val = cpuid_feature_extract_unsigned_field(pfr1, ID_AA64PFR1_EL1_MTE_SHIFT);
diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h
index 587507a9980e..aa8ec9df8024 100644
--- a/arch/arm64/include/asm/el2_setup.h
+++ b/arch/arm64/include/asm/el2_setup.h
@@ -510,7 +510,9 @@
#endif
.macro finalise_el2_state
- check_override id_aa64pfr0, ID_AA64PFR0_EL1_MPAM_SHIFT, .Linit_mpam_\@, .Lskip_mpam_\@, x1, x2
+ check_override id_aa64pfr0, ID_AA64PFR0_EL1_MPAM_SHIFT, .Linit_mpam_\@, .Lmpam_minor_\@, x1, x2
+.Lmpam_minor_\@:
+ check_override id_aa64pfr1, ID_AA64PFR1_EL1_MPAM_frac_SHIFT, .Linit_mpam_\@, .Lskip_mpam_\@, x1, x2
.Linit_mpam_\@:
mov x0, #MPAM2_EL2_EnMPAMSM_MASK
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index b3160f2058d7..6d94fda321de 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1167,6 +1167,14 @@ static __init void detect_system_supports_pseudo_nmi(void)
static inline void detect_system_supports_pseudo_nmi(void) { }
#endif
+static bool detect_ftr_has_mpam(void)
+{
+ u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
+ u64 pfr1 = read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1);
+
+ return id_aa64pfr0_mpam(pfr0) || id_aa64pfr1_mpamfrac(pfr1);
+}
+
void __init init_cpu_features(struct cpuinfo_arm64 *info)
{
/* Before we start using the tables, make sure it is sorted */
@@ -1214,7 +1222,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
cpacr_restore(cpacr);
}
- if (id_aa64pfr0_mpam(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
+ if (detect_ftr_has_mpam()) {
info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
init_cpu_ftr_reg(SYS_MPAMIDR_EL1, info->reg_mpamidr);
}
@@ -1470,7 +1478,7 @@ void update_cpu_features(int cpu,
cpacr_restore(cpacr);
}
- if (id_aa64pfr0_mpam(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
+ if (detect_ftr_has_mpam()) {
info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
taint |= check_update_ftr_reg(SYS_MPAMIDR_EL1, cpu,
info->reg_mpamidr, boot->reg_mpamidr);
@@ -2489,7 +2497,7 @@ cpucap_panic_on_conflict(const struct arm64_cpu_capabilities *cap)
static bool
test_has_mpam(const struct arm64_cpu_capabilities *entry, int scope)
{
- if (!has_cpuid_feature(entry, scope))
+ if (!detect_ftr_has_mpam())
return false;
/* Check firmware actually enabled MPAM on this cpu. */
@@ -3096,7 +3104,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.capability = ARM64_MPAM,
.matches = test_has_mpam,
.cpu_enable = cpu_enable_mpam,
- ARM64_CPUID_FIELDS(ID_AA64PFR0_EL1, MPAM, 1)
},
{
.desc = "Memory Partitioning And Monitoring Virtualisation",
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 41b14344b16f..83ddbddb2782 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -218,6 +218,24 @@ static inline void _mpam_write_monsel_reg(struct mpam_msc *msc, u16 reg, u32 val
#define mpam_write_monsel_reg(msc, reg, val) _mpam_write_monsel_reg(msc, MSMON_##reg, val)
+static bool mpam_msc_check_aidr(struct mpam_msc *msc)
+{
+ u32 aidr = __mpam_read_reg(msc, MPAMF_AIDR);
+ u32 major = FIELD_GET(MPAMF_AIDR_ARCH_MAJOR_REV, aidr);
+ u32 minor = FIELD_GET(MPAMF_AIDR_ARCH_MINOR_REV, aidr);
+
+ /*
+ * v0.0 and >v2.x aren't supported, but anything else should be backward
+ * compatible to v0.1 or v1.0.
+ */
+ if (!major && !minor)
+ return false;
+ if (major > 1)
+ return false;
+
+ return true;
+}
+
static u64 mpam_msc_read_idr(struct mpam_msc *msc)
{
u64 idr_high = 0, idr_low;
@@ -945,9 +963,8 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc)
lockdep_assert_held(&msc->probe_lock);
- idr = __mpam_read_reg(msc, MPAMF_AIDR);
- if ((idr & MPAMF_AIDR_ARCH_MAJOR_REV) != MPAM_ARCHITECTURE_V1) {
- dev_err_once(dev, "MSC does not match MPAM architecture v1.x\n");
+ if (!mpam_msc_check_aidr(msc)) {
+ dev_err_once(dev, "MSC does not match architecture v1.x\n");
return -EIO;
}