Skip to content

Commit c01df72

Browse files
author
Sebastian Ott
committed
arm64: Add override for MPAM
JIRA: https://issues.redhat.com/browse/RHEL-92805 As the message of the commit 09e6b30 ("arm64: cpufeature: discover CPU support for MPAM") already states, if a buggy firmware fails to either enable MPAM or emulate the trap as if it were disabled, the kernel will just fail to boot. While upgrading the firmware should be the best solution, we have some hardware of which the vendor have made no response 2 months after we requested a firmware update. Allow overriding it so our devices don't become some e-waste. Cc: James Morse <james.morse@arm.com> Cc: Marc Zyngier <maz@kernel.org> Cc: Will Deacon <will@kernel.org> Cc: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Cc: Mingcong Bai <jeffbai@aosc.io> Cc: Shaopeng Tan <tan.shaopeng@fujitsu.com> Cc: Ben Horgan <ben.horgan@arm.com> Signed-off-by: Xi Ruoyao <xry111@xry111.site> Reviewed-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20250602043723.216338-1-xry111@xry111.site Signed-off-by: Will Deacon <will@kernel.org> (cherry picked from commit 10f885d) Signed-off-by: Sebastian Ott <sebott@redhat.com>
1 parent b0200cd commit c01df72

File tree

5 files changed

+26
-18
lines changed

5 files changed

+26
-18
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,9 @@
452452
arm64.nomops [ARM64] Unconditionally disable Memory Copy and Memory
453453
Set instructions support
454454

455+
arm64.nompam [ARM64] Unconditionally disable Memory Partitioning And
456+
Monitoring support
457+
455458
arm64.nomte [ARM64] Unconditionally disable Memory Tagging Extension
456459
support
457460

arch/arm64/include/asm/el2_setup.h

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -294,19 +294,6 @@
294294
.Lskip_gcs_\@:
295295
.endm
296296

297-
.macro __init_el2_mpam
298-
/* Memory Partitioning And Monitoring: disable EL2 traps */
299-
mrs x1, id_aa64pfr0_el1
300-
ubfx x0, x1, #ID_AA64PFR0_EL1_MPAM_SHIFT, #4
301-
cbz x0, .Lskip_mpam_\@ // skip if no MPAM
302-
msr_s SYS_MPAM2_EL2, xzr // use the default partition
303-
// and disable lower traps
304-
mrs_s x0, SYS_MPAMIDR_EL1
305-
tbz x0, #MPAMIDR_EL1_HAS_HCR_SHIFT, .Lskip_mpam_\@ // skip if no MPAMHCR reg
306-
msr_s SYS_MPAMHCR_EL2, xzr // clear TRAP_MPAMIDR_EL1 -> EL2
307-
.Lskip_mpam_\@:
308-
.endm
309-
310297
/**
311298
* Initialize EL2 registers to sane values. This should be called early on all
312299
* cores that were booted in EL2. Note that everything gets initialised as
@@ -324,7 +311,6 @@
324311
__init_el2_stage2
325312
__init_el2_gicv3
326313
__init_el2_hstr
327-
__init_el2_mpam
328314
__init_el2_nvhe_idregs
329315
__init_el2_cptr
330316
__init_el2_fgt
@@ -371,6 +357,16 @@
371357
#endif
372358

373359
.macro finalise_el2_state
360+
check_override id_aa64pfr0, ID_AA64PFR0_EL1_MPAM_SHIFT, .Linit_mpam_\@, .Lskip_mpam_\@, x1, x2
361+
362+
.Linit_mpam_\@:
363+
msr_s SYS_MPAM2_EL2, xzr // use the default partition
364+
// and disable lower traps
365+
mrs_s x0, SYS_MPAMIDR_EL1
366+
tbz x0, #MPAMIDR_EL1_HAS_HCR_SHIFT, .Lskip_mpam_\@ // skip if no MPAMHCR reg
367+
msr_s SYS_MPAMHCR_EL2, xzr // clear TRAP_MPAMIDR_EL1 -> EL2
368+
369+
.Lskip_mpam_\@:
374370
check_override id_aa64pfr0, ID_AA64PFR0_EL1_SVE_SHIFT, .Linit_sve_\@, .Lskip_sve_\@, x1, x2
375371

376372
.Linit_sve_\@: /* SVE register access */

arch/arm64/kernel/cpufeature.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,8 +1192,10 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
11921192
cpacr_restore(cpacr);
11931193
}
11941194

1195-
if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0))
1195+
if (id_aa64pfr0_mpam(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
1196+
info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
11961197
init_cpu_ftr_reg(SYS_MPAMIDR_EL1, info->reg_mpamidr);
1198+
}
11971199

11981200
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
11991201
init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
@@ -1444,7 +1446,8 @@ void update_cpu_features(int cpu,
14441446
cpacr_restore(cpacr);
14451447
}
14461448

1447-
if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0)) {
1449+
if (id_aa64pfr0_mpam(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
1450+
info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
14481451
taint |= check_update_ftr_reg(SYS_MPAMIDR_EL1, cpu,
14491452
info->reg_mpamidr, boot->reg_mpamidr);
14501453
}

arch/arm64/kernel/cpuinfo.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,8 +494,11 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
494494
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
495495
__cpuinfo_store_cpu_32bit(&info->aarch32);
496496

497-
if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0))
498-
info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
497+
/*
498+
* info->reg_mpamidr deferred to {init,update}_cpu_features because we
499+
* don't want to read it (and trigger a trap on buggy firmware) if
500+
* using an aa64pfr0_el1 override to unconditionally disable MPAM.
501+
*/
499502

500503
if (IS_ENABLED(CONFIG_ARM64_SME) &&
501504
id_aa64pfr1_sme(info->reg_id_aa64pfr1)) {

arch/arm64/kernel/pi/idreg-override.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ static const struct ftr_set_desc pfr0 __prel64_initconst = {
127127
.fields = {
128128
FIELD("sve", ID_AA64PFR0_EL1_SVE_SHIFT, pfr0_sve_filter),
129129
FIELD("el0", ID_AA64PFR0_EL1_EL0_SHIFT, NULL),
130+
FIELD("mpam", ID_AA64PFR0_EL1_MPAM_SHIFT, NULL),
130131
{}
131132
},
132133
};
@@ -154,6 +155,7 @@ static const struct ftr_set_desc pfr1 __prel64_initconst = {
154155
FIELD("gcs", ID_AA64PFR1_EL1_GCS_SHIFT, NULL),
155156
FIELD("mte", ID_AA64PFR1_EL1_MTE_SHIFT, NULL),
156157
FIELD("sme", ID_AA64PFR1_EL1_SME_SHIFT, pfr1_sme_filter),
158+
FIELD("mpam_frac", ID_AA64PFR1_EL1_MPAM_frac_SHIFT, NULL),
157159
{}
158160
},
159161
};
@@ -246,6 +248,7 @@ static const struct {
246248
{ "rodata=off", "arm64_sw.rodataoff=1" },
247249
{ "arm64.nolva", "id_aa64mmfr2.varange=0" },
248250
{ "arm64.no32bit_el0", "id_aa64pfr0.el0=1" },
251+
{ "arm64.nompam", "id_aa64pfr0.mpam=0 id_aa64pfr1.mpam_frac=0" },
249252
};
250253

251254
static int __init parse_hexdigit(const char *p, u64 *v)

0 commit comments

Comments
 (0)