Skip to content

Commit e9e668c

Browse files
committed
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Will Deacon: "We've got a couple of build fixes when using LLD, a missing TLB invalidation and a workaround for broken firmware on SoCs with CPUs that implement MPAM: - Disable problematic linker assertions for broken versions of LLD - Work around sporadic link failure with LLD and various randconfig builds - Fix missing invalidation in the TLB batching code when reclaim races with mprotect() and friends - Add a command-line override for MPAM to allow booting on systems with broken firmware" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: Add override for MPAM arm64/mm: Close theoretical race where stale TLB entry remains valid arm64: Work around convergence issue with LLD linker arm64: Disable LLD linker ASSERT()s for the time being
2 parents aef7457 + 10f885d commit e9e668c

File tree

8 files changed

+49
-23
lines changed

8 files changed

+49
-23
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/include/asm/kernel-pgtable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
#define INIT_DIR_SIZE (PAGE_SIZE * (EARLY_PAGES(SWAPPER_PGTABLE_LEVELS, KIMAGE_VADDR, _end, EXTRA_PAGE) \
5959
+ EARLY_SEGMENT_EXTRA_PAGES))
6060

61-
#define INIT_IDMAP_DIR_PAGES (EARLY_PAGES(INIT_IDMAP_PGTABLE_LEVELS, KIMAGE_VADDR, _end, 1))
61+
#define INIT_IDMAP_DIR_PAGES (EARLY_PAGES(INIT_IDMAP_PGTABLE_LEVELS, KIMAGE_VADDR, kimage_limit, 1))
6262
#define INIT_IDMAP_DIR_SIZE ((INIT_IDMAP_DIR_PAGES + EARLY_IDMAP_EXTRA_PAGES) * PAGE_SIZE)
6363

6464
#define INIT_IDMAP_FDT_PAGES (EARLY_PAGES(INIT_IDMAP_PGTABLE_LEVELS, 0UL, UL(MAX_FDT_SIZE), 1) - 1)

arch/arm64/include/asm/tlbflush.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,13 +323,14 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
323323
}
324324

325325
/*
326-
* If mprotect/munmap/etc occurs during TLB batched flushing, we need to
327-
* synchronise all the TLBI issued with a DSB to avoid the race mentioned in
328-
* flush_tlb_batched_pending().
326+
* If mprotect/munmap/etc occurs during TLB batched flushing, we need to ensure
327+
* all the previously issued TLBIs targeting mm have completed. But since we
328+
* can be executing on a remote CPU, a DSB cannot guarantee this like it can
329+
* for arch_tlbbatch_flush(). Our only option is to flush the entire mm.
329330
*/
330331
static inline void arch_flush_tlb_batched_pending(struct mm_struct *mm)
331332
{
332-
dsb(ish);
333+
flush_tlb_mm(mm);
333334
}
334335

335336
/*

arch/arm64/kernel/cpufeature.c

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

1202-
if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0))
1202+
if (id_aa64pfr0_mpam(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
1203+
info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
12031204
init_cpu_ftr_reg(SYS_MPAMIDR_EL1, info->reg_mpamidr);
1205+
}
12041206

12051207
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
12061208
init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
@@ -1453,7 +1455,8 @@ void update_cpu_features(int cpu,
14531455
cpacr_restore(cpacr);
14541456
}
14551457

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

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/image-vars.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#error This file should only be included in vmlinux.lds.S
1111
#endif
1212

13+
#if defined(CONFIG_LD_IS_LLD) && CONFIG_LLD_VERSION < 210000
14+
#define ASSERT(...)
15+
#endif
16+
1317
#define PI_EXPORT_SYM(sym) \
1418
__PI_EXPORT_SYM(sym, __pi_ ## sym, Cannot export BSS symbol sym to startup code)
1519
#define __PI_EXPORT_SYM(sym, pisym, msg)\
@@ -140,4 +144,17 @@ KVM_NVHE_ALIAS(kvm_protected_mode_initialized);
140144
_kernel_codesize = ABSOLUTE(__inittext_end - _text);
141145
#endif
142146

147+
/*
148+
* LLD will occasionally error out with a '__init_end does not converge' error
149+
* if INIT_IDMAP_DIR_SIZE is defined in terms of _end, as this results in a
150+
* circular dependency. Counter this by dimensioning the initial IDMAP page
151+
* tables based on kimage_limit, which is defined such that its value should
152+
* not change as a result of the initdata segment being pushed over a 64k
153+
* segment boundary due to changes in INIT_IDMAP_DIR_SIZE, provided that its
154+
* value doesn't change by more than 2M between linker passes.
155+
*/
156+
kimage_limit = ALIGN(ABSOLUTE(_end + SZ_64K), SZ_2M);
157+
158+
#undef ASSERT
159+
143160
#endif /* __ARM64_KERNEL_IMAGE_VARS_H */

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)