Commit 1bdc3d5b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull powerpc fixes from Michael Ellerman:

 - Fix random crashes on some 32-bit CPUs by adding isync() after
   locking/unlocking KUEP

 - Fix intermittent crashes when loading modules with strict module RWX

 - Fix a section mismatch introduce by a previous fix.

Thanks to Christophe Leroy, Fabiano Rosas, Laurent Vivier, Murilo
Opsfelder Araújo, Nathan Chancellor, and Stan Johnson.

h# -----BEGIN PGP SIGNATURE-----

* tag 'powerpc-5.14-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/mm: Fix set_memory_*() against concurrent accesses
  powerpc/32s: Fix random crashes by adding isync() after locking/unlocking KUEP
  powerpc/xive: Do not mark xive_request_ipi() as __init
parents 9ff50bf2 9f7853d7
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@

#include <asm/bug.h>
#include <asm/book3s/32/mmu-hash.h>
#include <asm/mmu.h>
#include <asm/synch.h>

#ifndef __ASSEMBLY__

@@ -28,6 +30,15 @@ static inline void kuep_lock(void)
		return;

	update_user_segments(mfsr(0) | SR_NX);
	/*
	 * This isync() shouldn't be necessary as the kernel is not excepted to
	 * run any instruction in userspace soon after the update of segments,
	 * but hash based cores (at least G3) seem to exhibit a random
	 * behaviour when the 'isync' is not there. 603 cores don't have this
	 * behaviour so don't do the 'isync' as it saves several CPU cycles.
	 */
	if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
		isync();	/* Context sync required after mtsr() */
}

static inline void kuep_unlock(void)
@@ -36,6 +47,15 @@ static inline void kuep_unlock(void)
		return;

	update_user_segments(mfsr(0) & ~SR_NX);
	/*
	 * This isync() shouldn't be necessary as a 'rfi' will soon be executed
	 * to return to userspace, but hash based cores (at least G3) seem to
	 * exhibit a random behaviour when the 'isync' is not there. 603 cores
	 * don't have this behaviour so don't do the 'isync' as it saves several
	 * CPU cycles.
	 */
	if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
		isync();	/* Context sync required after mtsr() */
}

#ifdef CONFIG_PPC_KUAP
+10 −13
Original line number Diff line number Diff line
@@ -18,16 +18,12 @@
/*
 * Updates the attributes of a page in three steps:
 *
 * 1. invalidate the page table entry
 * 2. flush the TLB
 * 3. install the new entry with the updated attributes
 *
 * Invalidating the pte means there are situations where this will not work
 * when in theory it should.
 * For example:
 * - removing write from page whilst it is being executed
 * - setting a page read-only whilst it is being read by another CPU
 * 1. take the page_table_lock
 * 2. install the new entry with the updated attributes
 * 3. flush the TLB
 *
 * This sequence is safe against concurrent updates, and also allows updating the
 * attributes of a page currently being executed or accessed.
 */
static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
{
@@ -36,9 +32,7 @@ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)

	spin_lock(&init_mm.page_table_lock);

	/* invalidate the PTE so it's safe to modify */
	pte = ptep_get_and_clear(&init_mm, addr, ptep);
	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
	pte = ptep_get(ptep);

	/* modify the PTE bits as desired, then apply */
	switch (action) {
@@ -59,11 +53,14 @@ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
		break;
	}

	set_pte_at(&init_mm, addr, ptep, pte);
	pte_update(&init_mm, addr, ptep, ~0UL, pte_val(pte), 0);

	/* See ptesync comment in radix__set_pte_at() */
	if (radix_enabled())
		asm volatile("ptesync": : :"memory");

	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);

	spin_unlock(&init_mm.page_table_lock);

	return 0;
+1 −1
Original line number Diff line number Diff line
@@ -1170,7 +1170,7 @@ static int __init xive_init_ipis(void)
	return ret;
}

static int __init xive_request_ipi(unsigned int cpu)
static int xive_request_ipi(unsigned int cpu)
{
	struct xive_ipi_desc *xid = &xive_ipis[early_cpu_to_node(cpu)];
	int ret;