Skip to content

Commit 1bdc3d5

Browse files
committed
Merge tag 'powerpc-5.14-6' of git://git.kernel.org/pub/scm/linux/kernel/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
2 parents 9ff50bf + 9f7853d commit 1bdc3d5

File tree

3 files changed

+31
-14
lines changed

3 files changed

+31
-14
lines changed

arch/powerpc/include/asm/book3s/32/kup.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include <asm/bug.h>
66
#include <asm/book3s/32/mmu-hash.h>
7+
#include <asm/mmu.h>
8+
#include <asm/synch.h>
79

810
#ifndef __ASSEMBLY__
911

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

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

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

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

4161
#ifdef CONFIG_PPC_KUAP

arch/powerpc/mm/pageattr.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,12 @@
1818
/*
1919
* Updates the attributes of a page in three steps:
2020
*
21-
* 1. invalidate the page table entry
22-
* 2. flush the TLB
23-
* 3. install the new entry with the updated attributes
24-
*
25-
* Invalidating the pte means there are situations where this will not work
26-
* when in theory it should.
27-
* For example:
28-
* - removing write from page whilst it is being executed
29-
* - setting a page read-only whilst it is being read by another CPU
21+
* 1. take the page_table_lock
22+
* 2. install the new entry with the updated attributes
23+
* 3. flush the TLB
3024
*
25+
* This sequence is safe against concurrent updates, and also allows updating the
26+
* attributes of a page currently being executed or accessed.
3127
*/
3228
static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
3329
{
@@ -36,9 +32,7 @@ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
3632

3733
spin_lock(&init_mm.page_table_lock);
3834

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

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

62-
set_pte_at(&init_mm, addr, ptep, pte);
56+
pte_update(&init_mm, addr, ptep, ~0UL, pte_val(pte), 0);
6357

6458
/* See ptesync comment in radix__set_pte_at() */
6559
if (radix_enabled())
6660
asm volatile("ptesync": : :"memory");
61+
62+
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
63+
6764
spin_unlock(&init_mm.page_table_lock);
6865

6966
return 0;

arch/powerpc/sysdev/xive/common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1170,7 +1170,7 @@ static int __init xive_init_ipis(void)
11701170
return ret;
11711171
}
11721172

1173-
static int __init xive_request_ipi(unsigned int cpu)
1173+
static int xive_request_ipi(unsigned int cpu)
11741174
{
11751175
struct xive_ipi_desc *xid = &xive_ipis[early_cpu_to_node(cpu)];
11761176
int ret;

0 commit comments

Comments
 (0)