Skip to content

Commit

Permalink
Merge tag 'powerpc-5.14-6' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/powerpc/linux

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
  • Loading branch information
torvalds committed Aug 22, 2021
2 parents 9ff50bf + 9f7853d commit 1bdc3d5
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 14 deletions.
20 changes: 20 additions & 0 deletions arch/powerpc/include/asm/book3s/32/kup.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__

Expand All @@ -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)
Expand All @@ -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
Expand Down
23 changes: 10 additions & 13 deletions arch/powerpc/mm/pageattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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) {
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/sysdev/xive/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 1bdc3d5

Please sign in to comment.