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
This commit is contained in:
Will Deacon 2026-06-14 12:18:06 +01:00
commit 3594da9b7a
4 changed files with 41 additions and 8 deletions

View File

@ -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);

View File

@ -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

View File

@ -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",

View File

@ -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;
}