Skip to content

Commit 10f885d

Browse files
xry111willdeacon
authored andcommitted
arm64: Add override for MPAM
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 <[email protected]> Cc: Marc Zyngier <[email protected]> Cc: Will Deacon <[email protected]> Cc: Shameer Kolothum <[email protected]> Cc: Mingcong Bai <[email protected]> Cc: Shaopeng Tan <[email protected]> Cc: Ben Horgan <[email protected]> Signed-off-by: Xi Ruoyao <[email protected]> Reviewed-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 4b63491 commit 10f885d

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
@@ -458,6 +458,9 @@
458458
arm64.nomops [ARM64] Unconditionally disable Memory Copy and Memory
459459
Set instructions support
460460

461+
arm64.nompam [ARM64] Unconditionally disable Memory Partitioning And
462+
Monitoring support
463+
461464
arm64.nomte [ARM64] Unconditionally disable Memory Tagging Extension
462465
support
463466

arch/arm64/include/asm/el2_setup.h

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -298,19 +298,6 @@
298298
.Lskip_gcs_\@:
299299
.endm
300300

301-
.macro __init_el2_mpam
302-
/* Memory Partitioning And Monitoring: disable EL2 traps */
303-
mrs x1, id_aa64pfr0_el1
304-
ubfx x0, x1, #ID_AA64PFR0_EL1_MPAM_SHIFT, #4
305-
cbz x0, .Lskip_mpam_\@ // skip if no MPAM
306-
msr_s SYS_MPAM2_EL2, xzr // use the default partition
307-
// and disable lower traps
308-
mrs_s x0, SYS_MPAMIDR_EL1
309-
tbz x0, #MPAMIDR_EL1_HAS_HCR_SHIFT, .Lskip_mpam_\@ // skip if no MPAMHCR reg
310-
msr_s SYS_MPAMHCR_EL2, xzr // clear TRAP_MPAMIDR_EL1 -> EL2
311-
.Lskip_mpam_\@:
312-
.endm
313-
314301
/**
315302
* Initialize EL2 registers to sane values. This should be called early on all
316303
* cores that were booted in EL2. Note that everything gets initialised as
@@ -328,7 +315,6 @@
328315
__init_el2_stage2
329316
__init_el2_gicv3
330317
__init_el2_hstr
331-
__init_el2_mpam
332318
__init_el2_nvhe_idregs
333319
__init_el2_cptr
334320
__init_el2_fgt
@@ -375,6 +361,16 @@
375361
#endif
376362

377363
.macro finalise_el2_state
364+
check_override id_aa64pfr0, ID_AA64PFR0_EL1_MPAM_SHIFT, .Linit_mpam_\@, .Lskip_mpam_\@, x1, x2
365+
366+
.Linit_mpam_\@:
367+
msr_s SYS_MPAM2_EL2, xzr // use the default partition
368+
// and disable lower traps
369+
mrs_s x0, SYS_MPAMIDR_EL1
370+
tbz x0, #MPAMIDR_EL1_HAS_HCR_SHIFT, .Lskip_mpam_\@ // skip if no MPAMHCR reg
371+
msr_s SYS_MPAMHCR_EL2, xzr // clear TRAP_MPAMIDR_EL1 -> EL2
372+
373+
.Lskip_mpam_\@:
378374
check_override id_aa64pfr0, ID_AA64PFR0_EL1_SVE_SHIFT, .Linit_sve_\@, .Lskip_sve_\@, x1, x2
379375

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

arch/arm64/kernel/cpufeature.c

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

1201-
if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0))
1201+
if (id_aa64pfr0_mpam(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
1202+
info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
12021203
init_cpu_ftr_reg(SYS_MPAMIDR_EL1, info->reg_mpamidr);
1204+
}
12031205

12041206
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
12051207
init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
@@ -1452,7 +1454,8 @@ void update_cpu_features(int cpu,
14521454
cpacr_restore(cpacr);
14531455
}
14541456

1455-
if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0)) {
1457+
if (id_aa64pfr0_mpam(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
1458+
info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
14561459
taint |= check_update_ftr_reg(SYS_MPAMIDR_EL1, cpu,
14571460
info->reg_mpamidr, boot->reg_mpamidr);
14581461
}

arch/arm64/kernel/cpuinfo.c

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

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

502505
if (IS_ENABLED(CONFIG_ARM64_SME) &&
503506
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)