Commit e9e668cd authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents aef74575 10f885d6
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -458,6 +458,9 @@
	arm64.nomops	[ARM64] Unconditionally disable Memory Copy and Memory
			Set instructions support

	arm64.nompam	[ARM64] Unconditionally disable Memory Partitioning And
			Monitoring support

	arm64.nomte	[ARM64] Unconditionally disable Memory Tagging Extension
			support

+10 −14
Original line number Diff line number Diff line
@@ -298,19 +298,6 @@
.Lskip_gcs_\@:
.endm

.macro __init_el2_mpam
	/* Memory Partitioning And Monitoring: disable EL2 traps */
	mrs	x1, id_aa64pfr0_el1
	ubfx	x0, x1, #ID_AA64PFR0_EL1_MPAM_SHIFT, #4
	cbz	x0, .Lskip_mpam_\@		// skip if no MPAM
	msr_s	SYS_MPAM2_EL2, xzr		// use the default partition
						// and disable lower traps
	mrs_s	x0, SYS_MPAMIDR_EL1
	tbz	x0, #MPAMIDR_EL1_HAS_HCR_SHIFT, .Lskip_mpam_\@	// skip if no MPAMHCR reg
	msr_s	SYS_MPAMHCR_EL2, xzr		// clear TRAP_MPAMIDR_EL1 -> EL2
.Lskip_mpam_\@:
.endm

/**
 * Initialize EL2 registers to sane values. This should be called early on all
 * cores that were booted in EL2. Note that everything gets initialised as
@@ -328,7 +315,6 @@
	__init_el2_stage2
	__init_el2_gicv3
	__init_el2_hstr
	__init_el2_mpam
	__init_el2_nvhe_idregs
	__init_el2_cptr
	__init_el2_fgt
@@ -375,6 +361,16 @@
#endif

.macro finalise_el2_state
	check_override id_aa64pfr0, ID_AA64PFR0_EL1_MPAM_SHIFT, .Linit_mpam_\@, .Lskip_mpam_\@, x1, x2

.Linit_mpam_\@:
	msr_s	SYS_MPAM2_EL2, xzr		// use the default partition
						// and disable lower traps
	mrs_s	x0, SYS_MPAMIDR_EL1
	tbz	x0, #MPAMIDR_EL1_HAS_HCR_SHIFT, .Lskip_mpam_\@  // skip if no MPAMHCR reg
	msr_s   SYS_MPAMHCR_EL2, xzr		// clear TRAP_MPAMIDR_EL1 -> EL2

.Lskip_mpam_\@:
	check_override id_aa64pfr0, ID_AA64PFR0_EL1_SVE_SHIFT, .Linit_sve_\@, .Lskip_sve_\@, x1, x2

.Linit_sve_\@:	/* SVE register access */
+1 −1
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@
#define INIT_DIR_SIZE (PAGE_SIZE * (EARLY_PAGES(SWAPPER_PGTABLE_LEVELS, KIMAGE_VADDR, _end, EXTRA_PAGE) \
				    + EARLY_SEGMENT_EXTRA_PAGES))

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

#define INIT_IDMAP_FDT_PAGES	(EARLY_PAGES(INIT_IDMAP_PGTABLE_LEVELS, 0UL, UL(MAX_FDT_SIZE), 1) - 1)
+5 −4
Original line number Diff line number Diff line
@@ -323,13 +323,14 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
}

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

/*
+5 −2
Original line number Diff line number Diff line
@@ -1199,8 +1199,10 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
		cpacr_restore(cpacr);
	}

	if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0))
	if (id_aa64pfr0_mpam(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
		info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
		init_cpu_ftr_reg(SYS_MPAMIDR_EL1, info->reg_mpamidr);
	}

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

	if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0)) {
	if (id_aa64pfr0_mpam(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
		info->reg_mpamidr = read_cpuid(MPAMIDR_EL1);
		taint |= check_update_ftr_reg(SYS_MPAMIDR_EL1, cpu,
					info->reg_mpamidr, boot->reg_mpamidr);
	}
Loading