* [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect()
@ 2021-10-23 11:47 Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 02/10] powerpc/book3e: Fix set_memory_x() and set_memory_nx() Christophe Leroy
` (8 more replies)
0 siblings, 9 replies; 12+ messages in thread
From: Christophe Leroy @ 2021-10-23 11:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
Commit 26973fa5ac0e ("powerpc/mm: use pte helpers in generic code")
changed those two functions to use pte helpers to determine which
bits to clear and which bits to set.
This change was based on the assumption that bits to be set/cleared
are always the same and can be determined by applying the pte
manipulation helpers on __pte(0).
But on platforms like book3e, the bits depend on whether the page
is a user page or not.
For the time being it more or less works because of _PAGE_EXEC being
used for user pages only and exec right being set at all time on
kernel page. But following patch will clean that and output of
pte_mkexec() will depend on the page being a user or kernel page.
Instead of trying to make an even more complicated helper where bits
would become dependent on the final pte value, come back to a more
static situation like before commit 26973fa5ac0e ("powerpc/mm: use
pte helpers in generic code"), by introducing an 8xx specific
version of __ptep_set_access_flags() and ptep_set_wrprotect().
Fixes: 26973fa5ac0e ("powerpc/mm: use pte helpers in generic code")
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: New
---
arch/powerpc/include/asm/nohash/32/pgtable.h | 17 +++++++--------
arch/powerpc/include/asm/nohash/32/pte-8xx.h | 22 ++++++++++++++++++++
2 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h
index f06ae00f2a65..ac0a5ff48c3a 100644
--- a/arch/powerpc/include/asm/nohash/32/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/32/pgtable.h
@@ -306,30 +306,29 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
}
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+#ifndef ptep_set_wrprotect
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
{
- unsigned long clr = ~pte_val(pte_wrprotect(__pte(~0)));
- unsigned long set = pte_val(pte_wrprotect(__pte(0)));
-
- pte_update(mm, addr, ptep, clr, set, 0);
+ pte_update(mm, addr, ptep, _PAGE_RW, 0, 0);
}
+#endif
+#ifndef __ptep_set_access_flags
static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
pte_t *ptep, pte_t entry,
unsigned long address,
int psize)
{
- pte_t pte_set = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(0)))));
- pte_t pte_clr = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(~0)))));
- unsigned long set = pte_val(entry) & pte_val(pte_set);
- unsigned long clr = ~pte_val(entry) & ~pte_val(pte_clr);
+ unsigned long set = pte_val(entry) &
+ (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
int huge = psize > mmu_virtual_psize ? 1 : 0;
- pte_update(vma->vm_mm, address, ptep, clr, set, huge);
+ pte_update(vma->vm_mm, address, ptep, 0, set, huge);
flush_tlb_page(vma, address);
}
+#endif
static inline int pte_young(pte_t pte)
{
diff --git a/arch/powerpc/include/asm/nohash/32/pte-8xx.h b/arch/powerpc/include/asm/nohash/32/pte-8xx.h
index fcc48d590d88..1a89ebdc3acc 100644
--- a/arch/powerpc/include/asm/nohash/32/pte-8xx.h
+++ b/arch/powerpc/include/asm/nohash/32/pte-8xx.h
@@ -136,6 +136,28 @@ static inline pte_t pte_mkhuge(pte_t pte)
#define pte_mkhuge pte_mkhuge
+static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p,
+ unsigned long clr, unsigned long set, int huge);
+
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ pte_update(mm, addr, ptep, 0, _PAGE_RO, 0);
+}
+#define ptep_set_wrprotect ptep_set_wrprotect
+
+static inline void __ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep,
+ pte_t entry, unsigned long address, int psize)
+{
+ unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_EXEC);
+ unsigned long clr = ~pte_val(entry) & _PAGE_RO;
+ int huge = psize > mmu_virtual_psize ? 1 : 0;
+
+ pte_update(vma->vm_mm, address, ptep, clr, set, huge);
+
+ flush_tlb_page(vma, address);
+}
+#define __ptep_set_access_flags __ptep_set_access_flags
+
static inline unsigned long pgd_leaf_size(pgd_t pgd)
{
if (pgd_val(pgd) & _PMD_PAGE_8M)
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 02/10] powerpc/book3e: Fix set_memory_x() and set_memory_nx()
2021-10-23 11:47 [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() Christophe Leroy
@ 2021-10-23 11:47 ` Christophe Leroy
2021-10-25 21:53 ` Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 03/10] powerpc/booke: Disable STRICT_KERNEL_RWX, DEBUG_PAGEALLOC and KFENCE Christophe Leroy
` (7 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Christophe Leroy @ 2021-10-23 11:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
set_memory_x() calls pte_mkexec() which sets _PAGE_EXEC.
set_memory_nx() calls pte_exprotec() which clears _PAGE_EXEC.
Book3e has 2 bits, UX and SX, which defines the exec rights
resp. for user (PR=1) and for kernel (PR=0).
_PAGE_EXEC is defined as UX only.
An executable kernel page is set with either _PAGE_KERNEL_RWX
or _PAGE_KERNEL_ROX, which both have SX set and UX cleared.
So set_memory_nx() call for an executable kernel page does
nothing because UX is already cleared.
And set_memory_x() on a non-executable kernel page makes it
executable for the user and keeps it non-executable for kernel.
Also, pte_exec() always returns 'false' on kernel pages, because
it checks _PAGE_EXEC which doesn't include SX, so for instance
the W+X check doesn't work.
To fix this:
- change tlb_low_64e.S to use _PAGE_BAP_UX instead of _PAGE_USER
- sets both UX and SX in _PAGE_EXEC so that pte_user() returns
true whenever one of the two bits is set and pte_exprotect()
clears both bits.
- Define a book3e specific version of pte_mkexec() which sets
either SX or UX based on UR.
Fixes: 1f9ad21c3b38 ("powerpc/mm: Implement set_memory() routines")
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: New
---
arch/powerpc/include/asm/nohash/32/pgtable.h | 2 ++
arch/powerpc/include/asm/nohash/pte-book3e.h | 18 ++++++++++++++----
arch/powerpc/mm/nohash/tlb_low_64e.S | 8 ++++----
3 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h
index ac0a5ff48c3a..d6ba821a56ce 100644
--- a/arch/powerpc/include/asm/nohash/32/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/32/pgtable.h
@@ -193,10 +193,12 @@ static inline pte_t pte_wrprotect(pte_t pte)
}
#endif
+#ifndef pte_mkexec
static inline pte_t pte_mkexec(pte_t pte)
{
return __pte(pte_val(pte) | _PAGE_EXEC);
}
+#endif
#define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD)
diff --git a/arch/powerpc/include/asm/nohash/pte-book3e.h b/arch/powerpc/include/asm/nohash/pte-book3e.h
index 813918f40765..f798640422c2 100644
--- a/arch/powerpc/include/asm/nohash/pte-book3e.h
+++ b/arch/powerpc/include/asm/nohash/pte-book3e.h
@@ -48,7 +48,7 @@
#define _PAGE_WRITETHRU 0x800000 /* W: cache write-through */
/* "Higher level" linux bit combinations */
-#define _PAGE_EXEC _PAGE_BAP_UX /* .. and was cache cleaned */
+#define _PAGE_EXEC (_PAGE_BAP_SX | _PAGE_BAP_UX) /* .. and was cache cleaned */
#define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */
#define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY)
#define _PAGE_KERNEL_RO (_PAGE_BAP_SR)
@@ -93,11 +93,11 @@
/* Permission masks used to generate the __P and __S table */
#define PAGE_NONE __pgprot(_PAGE_BASE)
#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
+#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_BAP_UX)
#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX)
#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX)
#ifndef __ASSEMBLY__
static inline pte_t pte_mkprivileged(pte_t pte)
@@ -113,6 +113,16 @@ static inline pte_t pte_mkuser(pte_t pte)
}
#define pte_mkuser pte_mkuser
+
+static inline pte_t pte_mkexec(pte_t pte)
+{
+ if (pte_val(pte) & _PAGE_BAP_UR)
+ return __pte((pte_val(pte) & ~_PAGE_BAP_SX) | _PAGE_BAP_UX);
+ else
+ return __pte((pte_val(pte) & ~_PAGE_BAP_UX) | _PAGE_BAP_SX);
+}
+#define pte_mkexec pte_mkexec
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/mm/nohash/tlb_low_64e.S b/arch/powerpc/mm/nohash/tlb_low_64e.S
index bf24451f3e71..9235e720e357 100644
--- a/arch/powerpc/mm/nohash/tlb_low_64e.S
+++ b/arch/powerpc/mm/nohash/tlb_low_64e.S
@@ -222,7 +222,7 @@ tlb_miss_kernel_bolted:
tlb_miss_fault_bolted:
/* We need to check if it was an instruction miss */
- andi. r10,r11,_PAGE_EXEC|_PAGE_BAP_SX
+ andi. r10,r11,_PAGE_BAP_UX|_PAGE_BAP_SX
bne itlb_miss_fault_bolted
dtlb_miss_fault_bolted:
tlb_epilog_bolted
@@ -239,7 +239,7 @@ itlb_miss_fault_bolted:
srdi r15,r16,60 /* get region */
bne- itlb_miss_fault_bolted
- li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */
+ li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */
/* We do the user/kernel test for the PID here along with the RW test
*/
@@ -614,7 +614,7 @@ itlb_miss_fault_e6500:
/* We do the user/kernel test for the PID here along with the RW test
*/
- li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */
+ li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */
oris r11,r11,_PAGE_ACCESSED@h
cmpldi cr0,r15,0 /* Check for user region */
@@ -734,7 +734,7 @@ normal_tlb_miss_done:
normal_tlb_miss_access_fault:
/* We need to check if it was an instruction miss */
- andi. r10,r11,_PAGE_EXEC
+ andi. r10,r11,_PAGE_BAP_UX
bne 1f
ld r14,EX_TLB_DEAR(r12)
ld r15,EX_TLB_ESR(r12)
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 03/10] powerpc/booke: Disable STRICT_KERNEL_RWX, DEBUG_PAGEALLOC and KFENCE
2021-10-23 11:47 [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 02/10] powerpc/book3e: Fix set_memory_x() and set_memory_nx() Christophe Leroy
@ 2021-10-23 11:47 ` Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 04/10] powerpc/fsl_booke: Rename fsl_booke.c to fsl_book3e.c Christophe Leroy
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Christophe Leroy @ 2021-10-23 11:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
fsl_booke and 44x are not able to map kernel linear memory with
pages, so they can't support DEBUG_PAGEALLOC and KFENCE, and
STRICT_KERNEL_RWX is also a problem for now.
Enable those only on book3s (both 32 and 64 except KFENCE), 8xx and 40x.
Fixes: 88df6e90fa97 ("[POWERPC] DEBUG_PAGEALLOC for 32-bit")
Fixes: 95902e6c8864 ("powerpc/mm: Implement STRICT_KERNEL_RWX on PPC32")
Fixes: 90cbac0e995d ("powerpc: Enable KFENCE for PPC32")
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: No change
---
arch/powerpc/Kconfig | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ba5b66189358..6b9f523882c5 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -138,7 +138,7 @@ config PPC
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64
select ARCH_HAS_SET_MEMORY
- select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !HIBERNATION)
+ select ARCH_HAS_STRICT_KERNEL_RWX if (PPC_BOOK3S || PPC_8xx || 40x) && !HIBERNATION
select ARCH_HAS_STRICT_MODULE_RWX if ARCH_HAS_STRICT_KERNEL_RWX && !PPC_BOOK3S_32
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UACCESS_FLUSHCACHE
@@ -150,7 +150,7 @@ config PPC
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_STACKWALK
select ARCH_SUPPORTS_ATOMIC_RMW
- select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC32 || PPC_BOOK3S_64
+ select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC_BOOK3S || PPC_8xx || 40x
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF if PPC64
select ARCH_USE_MEMTEST
@@ -190,7 +190,7 @@ config PPC
select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if PPC32 && PPC_PAGE_SHIFT <= 14
select HAVE_ARCH_KASAN_VMALLOC if PPC32 && PPC_PAGE_SHIFT <= 14
- select HAVE_ARCH_KFENCE if PPC32
+ select HAVE_ARCH_KFENCE if PPC_BOOK3S_32 || PPC_8xx || 40x
select HAVE_ARCH_KGDB
select HAVE_ARCH_MMAP_RND_BITS
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 04/10] powerpc/fsl_booke: Rename fsl_booke.c to fsl_book3e.c
2021-10-23 11:47 [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 02/10] powerpc/book3e: Fix set_memory_x() and set_memory_nx() Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 03/10] powerpc/booke: Disable STRICT_KERNEL_RWX, DEBUG_PAGEALLOC and KFENCE Christophe Leroy
@ 2021-10-23 11:47 ` Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 05/10] powerpc/fsl_booke: Take exec flag into account when setting TLBCAMs Christophe Leroy
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Christophe Leroy @ 2021-10-23 11:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
We have a myriad of CONFIG symbols around different variants
of BOOKEs, which would be worth tidying up one day.
But at least, make file names and CONFIG option match:
We have CONFIG_FSL_BOOKE and CONFIG_PPC_FSL_BOOK3E.
fsl_booke.c is selected by and only by CONFIG_PPC_FSL_BOOK3E.
So rename it fsl_book3e to reduce confusion.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: No change
---
arch/powerpc/mm/nohash/Makefile | 4 ++--
arch/powerpc/mm/nohash/{fsl_booke.c => fsl_book3e.c} | 0
2 files changed, 2 insertions(+), 2 deletions(-)
rename arch/powerpc/mm/nohash/{fsl_booke.c => fsl_book3e.c} (100%)
diff --git a/arch/powerpc/mm/nohash/Makefile b/arch/powerpc/mm/nohash/Makefile
index 0424f6ce5bd8..b1f630d423d8 100644
--- a/arch/powerpc/mm/nohash/Makefile
+++ b/arch/powerpc/mm/nohash/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_PPC_BOOK3E_64) += tlb_low_64e.o book3e_pgtable.o
obj-$(CONFIG_40x) += 40x.o
obj-$(CONFIG_44x) += 44x.o
obj-$(CONFIG_PPC_8xx) += 8xx.o
-obj-$(CONFIG_PPC_FSL_BOOK3E) += fsl_booke.o
+obj-$(CONFIG_PPC_FSL_BOOK3E) += fsl_book3e.o
obj-$(CONFIG_RANDOMIZE_BASE) += kaslr_booke.o
ifdef CONFIG_HUGETLB_PAGE
obj-$(CONFIG_PPC_FSL_BOOK3E) += book3e_hugetlbpage.o
@@ -16,4 +16,4 @@ endif
# Disable kcov instrumentation on sensitive code
# This is necessary for booting with kcov enabled on book3e machines
KCOV_INSTRUMENT_tlb.o := n
-KCOV_INSTRUMENT_fsl_booke.o := n
+KCOV_INSTRUMENT_fsl_book3e.o := n
diff --git a/arch/powerpc/mm/nohash/fsl_booke.c b/arch/powerpc/mm/nohash/fsl_book3e.c
similarity index 100%
rename from arch/powerpc/mm/nohash/fsl_booke.c
rename to arch/powerpc/mm/nohash/fsl_book3e.c
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 05/10] powerpc/fsl_booke: Take exec flag into account when setting TLBCAMs
2021-10-23 11:47 [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() Christophe Leroy
` (2 preceding siblings ...)
2021-10-23 11:47 ` [PATCH v2 04/10] powerpc/fsl_booke: Rename fsl_booke.c to fsl_book3e.c Christophe Leroy
@ 2021-10-23 11:47 ` Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 06/10] powerpc/fsl_booke: Enable reloading of TLBCAM without switching to AS1 Christophe Leroy
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Christophe Leroy @ 2021-10-23 11:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
Don't force MAS3_SX and MAS3_UX at all time. Take into account the
exec flag.
While at it, fix a couple of closeby style problems (indent with space
and unnecessary parenthesis), it keeps more readability.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: Use the new _PAGE_EXEC to check executability of flags instead of _PAGE_BAP_SX (Error reported by robot with tqm8541_defconfig)
---
arch/powerpc/mm/nohash/fsl_book3e.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/mm/nohash/fsl_book3e.c b/arch/powerpc/mm/nohash/fsl_book3e.c
index 03dacbe940e5..2668bb06e4fa 100644
--- a/arch/powerpc/mm/nohash/fsl_book3e.c
+++ b/arch/powerpc/mm/nohash/fsl_book3e.c
@@ -122,15 +122,18 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
TLBCAM[index].MAS2 |= (flags & _PAGE_GUARDED) ? MAS2_G : 0;
TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0;
- TLBCAM[index].MAS3 = (phys & MAS3_RPN) | MAS3_SX | MAS3_SR;
- TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0);
+ TLBCAM[index].MAS3 = (phys & MAS3_RPN) | MAS3_SR;
+ TLBCAM[index].MAS3 |= (flags & _PAGE_RW) ? MAS3_SW : 0;
if (mmu_has_feature(MMU_FTR_BIG_PHYS))
TLBCAM[index].MAS7 = (u64)phys >> 32;
/* Below is unlikely -- only for large user pages or similar */
if (pte_user(__pte(flags))) {
- TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
- TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
+ TLBCAM[index].MAS3 |= MAS3_UR;
+ TLBCAM[index].MAS3 |= (flags & _PAGE_EXEC) ? MAS3_UX : 0;
+ TLBCAM[index].MAS3 |= (flags & _PAGE_RW) ? MAS3_UW : 0;
+ } else {
+ TLBCAM[index].MAS3 |= (flags & _PAGE_EXEC) ? MAS3_SX : 0;
}
tlbcam_addrs[index].start = virt;
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 06/10] powerpc/fsl_booke: Enable reloading of TLBCAM without switching to AS1
2021-10-23 11:47 [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() Christophe Leroy
` (3 preceding siblings ...)
2021-10-23 11:47 ` [PATCH v2 05/10] powerpc/fsl_booke: Take exec flag into account when setting TLBCAMs Christophe Leroy
@ 2021-10-23 11:47 ` Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 07/10] powerpc/fsl_booke: Tell map_mem_in_cams() if init is done Christophe Leroy
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Christophe Leroy @ 2021-10-23 11:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
Avoid switching to AS1 when reloading TLBCAM after init for
STRICT_KERNEL_RWX.
When we setup AS1 we expect the entire accessible memory to be mapped
through one entry, this is not the case anymore at the end of init.
We are not changing the size of TLBCAMs, only flags, so no need to
switch to AS1.
So change loadcam_multi() to not switch to AS1 when the given
temporary tlb entry in 0.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: No change
---
arch/powerpc/mm/nohash/tlb_low.S | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/mm/nohash/tlb_low.S b/arch/powerpc/mm/nohash/tlb_low.S
index 5add4a51e51f..dd39074de9af 100644
--- a/arch/powerpc/mm/nohash/tlb_low.S
+++ b/arch/powerpc/mm/nohash/tlb_low.S
@@ -369,7 +369,7 @@ _GLOBAL(_tlbivax_bcast)
* extern void loadcam_entry(unsigned int index)
*
* Load TLBCAM[index] entry in to the L2 CAM MMU
- * Must preserve r7, r8, r9, r10 and r11
+ * Must preserve r7, r8, r9, r10, r11, r12
*/
_GLOBAL(loadcam_entry)
mflr r5
@@ -401,7 +401,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
*
* r3 = first entry to write
* r4 = number of entries to write
- * r5 = temporary tlb entry
+ * r5 = temporary tlb entry (0 means no switch to AS1)
*/
_GLOBAL(loadcam_multi)
mflr r8
@@ -409,6 +409,8 @@ _GLOBAL(loadcam_multi)
mfmsr r11
andi. r11,r11,MSR_IS
bne 10f
+ mr. r12, r5
+ beq 10f
/*
* Set up temporary TLB entry that is the same as what we're
@@ -446,6 +448,8 @@ _GLOBAL(loadcam_multi)
/* Don't return to AS=0 if we were in AS=1 at function start */
andi. r11,r11,MSR_IS
bne 3f
+ cmpwi r12, 0
+ beq 3f
/* Return to AS=0 and clear the temporary entry */
mfmsr r6
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 07/10] powerpc/fsl_booke: Tell map_mem_in_cams() if init is done
2021-10-23 11:47 [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() Christophe Leroy
` (4 preceding siblings ...)
2021-10-23 11:47 ` [PATCH v2 06/10] powerpc/fsl_booke: Enable reloading of TLBCAM without switching to AS1 Christophe Leroy
@ 2021-10-23 11:47 ` Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 08/10] powerpc/fsl_booke: Allocate separate TLBCAMs for readonly memory Christophe Leroy
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Christophe Leroy @ 2021-10-23 11:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
In order to be able to call map_mem_in_cams() once more
after init for STRICT_KERNEL_RWX, add an argument.
For now, map_mem_in_cams() is always called only during init.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: No change
---
arch/powerpc/mm/mmu_decl.h | 2 +-
arch/powerpc/mm/nohash/fsl_book3e.c | 12 ++++++------
arch/powerpc/mm/nohash/kaslr_booke.c | 2 +-
arch/powerpc/mm/nohash/tlb.c | 4 ++--
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index dd1cabc2ea0f..e13a3c0caa02 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -126,7 +126,7 @@ unsigned long mmu_mapin_ram(unsigned long base, unsigned long top);
#ifdef CONFIG_PPC_FSL_BOOK3E
extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx,
- bool dryrun);
+ bool dryrun, bool init);
extern unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
phys_addr_t phys);
#ifdef CONFIG_PPC32
diff --git a/arch/powerpc/mm/nohash/fsl_book3e.c b/arch/powerpc/mm/nohash/fsl_book3e.c
index 2668bb06e4fa..8ae1ba7985df 100644
--- a/arch/powerpc/mm/nohash/fsl_book3e.c
+++ b/arch/powerpc/mm/nohash/fsl_book3e.c
@@ -168,7 +168,7 @@ unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,
unsigned long ram, int max_cam_idx,
- bool dryrun)
+ bool dryrun, bool init)
{
int i;
unsigned long amount_mapped = 0;
@@ -203,12 +203,12 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,
return amount_mapped;
}
-unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx, bool dryrun)
+unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx, bool dryrun, bool init)
{
unsigned long virt = PAGE_OFFSET;
phys_addr_t phys = memstart_addr;
- return map_mem_in_cams_addr(phys, virt, ram, max_cam_idx, dryrun);
+ return map_mem_in_cams_addr(phys, virt, ram, max_cam_idx, dryrun, init);
}
#ifdef CONFIG_PPC32
@@ -249,7 +249,7 @@ void __init adjust_total_lowmem(void)
ram = min((phys_addr_t)__max_low_memory, (phys_addr_t)total_lowmem);
i = switch_to_as1();
- __max_low_memory = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, false);
+ __max_low_memory = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, false, true);
restore_to_as0(i, 0, 0, 1);
pr_info("Memory CAM mapping: ");
@@ -320,11 +320,11 @@ notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)
/* map a 64M area for the second relocation */
if (memstart_addr > start)
map_mem_in_cams(0x4000000, CONFIG_LOWMEM_CAM_NUM,
- false);
+ false, true);
else
map_mem_in_cams_addr(start, PAGE_OFFSET + offset,
0x4000000, CONFIG_LOWMEM_CAM_NUM,
- false);
+ false, true);
restore_to_as0(n, offset, __va(dt_ptr), 1);
/* We should never reach here */
panic("Relocation error");
diff --git a/arch/powerpc/mm/nohash/kaslr_booke.c b/arch/powerpc/mm/nohash/kaslr_booke.c
index 4c74e8a5482b..8fc49b1b4a91 100644
--- a/arch/powerpc/mm/nohash/kaslr_booke.c
+++ b/arch/powerpc/mm/nohash/kaslr_booke.c
@@ -314,7 +314,7 @@ static unsigned long __init kaslr_choose_location(void *dt_ptr, phys_addr_t size
pr_warn("KASLR: No safe seed for randomizing the kernel base.\n");
ram = min_t(phys_addr_t, __max_low_memory, size);
- ram = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, true);
+ ram = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, true, false);
linear_sz = min_t(unsigned long, ram, SZ_512M);
/* If the linear size is smaller than 64M, do not randmize */
diff --git a/arch/powerpc/mm/nohash/tlb.c b/arch/powerpc/mm/nohash/tlb.c
index 5872f69141d5..fc195b9f524b 100644
--- a/arch/powerpc/mm/nohash/tlb.c
+++ b/arch/powerpc/mm/nohash/tlb.c
@@ -643,7 +643,7 @@ static void early_init_this_mmu(void)
if (map)
linear_map_top = map_mem_in_cams(linear_map_top,
- num_cams, false);
+ num_cams, true, true);
}
#endif
@@ -764,7 +764,7 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
linear_sz = map_mem_in_cams(first_memblock_size, num_cams,
- true);
+ false, true);
ppc64_rma_size = min_t(u64, linear_sz, 0x40000000);
} else
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 08/10] powerpc/fsl_booke: Allocate separate TLBCAMs for readonly memory
2021-10-23 11:47 [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() Christophe Leroy
` (5 preceding siblings ...)
2021-10-23 11:47 ` [PATCH v2 07/10] powerpc/fsl_booke: Tell map_mem_in_cams() if init is done Christophe Leroy
@ 2021-10-23 11:47 ` Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 09/10] powerpc/fsl_booke: Update of TLBCAMs after init Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 10/10] powerpc/fsl_booke: Enable STRICT_KERNEL_RWX Christophe Leroy
8 siblings, 0 replies; 12+ messages in thread
From: Christophe Leroy @ 2021-10-23 11:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
Reorganise TLBCAM allocation so that when STRICT_KERNEL_RWX is
enabled, TLBCAMs are allocated such that readonly memory uses
different TLBCAMs.
This results in an allocation looking like:
Memory CAM mapping: 4/4/4/1/1/1/1/16/16/16/64/64/64/256/256 Mb, residual: 256Mb
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: No change
---
arch/powerpc/mm/nohash/fsl_book3e.c | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/mm/nohash/fsl_book3e.c b/arch/powerpc/mm/nohash/fsl_book3e.c
index 8ae1ba7985df..88132cab3442 100644
--- a/arch/powerpc/mm/nohash/fsl_book3e.c
+++ b/arch/powerpc/mm/nohash/fsl_book3e.c
@@ -172,15 +172,34 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,
{
int i;
unsigned long amount_mapped = 0;
+ unsigned long boundary;
+
+ if (strict_kernel_rwx_enabled())
+ boundary = (unsigned long)(_sinittext - _stext);
+ else
+ boundary = ram;
/* Calculate CAM values */
- for (i = 0; ram && i < max_cam_idx; i++) {
+ for (i = 0; boundary && i < max_cam_idx; i++) {
+ unsigned long cam_sz;
+ pgprot_t prot = PAGE_KERNEL_X;
+
+ cam_sz = calc_cam_sz(boundary, virt, phys);
+ if (!dryrun)
+ settlbcam(i, virt, phys, cam_sz, pgprot_val(prot), 0);
+
+ boundary -= cam_sz;
+ amount_mapped += cam_sz;
+ virt += cam_sz;
+ phys += cam_sz;
+ }
+ for (ram -= amount_mapped; ram && i < max_cam_idx; i++) {
unsigned long cam_sz;
+ pgprot_t prot = PAGE_KERNEL_X;
cam_sz = calc_cam_sz(ram, virt, phys);
if (!dryrun)
- settlbcam(i, virt, phys, cam_sz,
- pgprot_val(PAGE_KERNEL_X), 0);
+ settlbcam(i, virt, phys, cam_sz, pgprot_val(prot), 0);
ram -= cam_sz;
amount_mapped += cam_sz;
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 09/10] powerpc/fsl_booke: Update of TLBCAMs after init
2021-10-23 11:47 [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() Christophe Leroy
` (6 preceding siblings ...)
2021-10-23 11:47 ` [PATCH v2 08/10] powerpc/fsl_booke: Allocate separate TLBCAMs for readonly memory Christophe Leroy
@ 2021-10-23 11:47 ` Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 10/10] powerpc/fsl_booke: Enable STRICT_KERNEL_RWX Christophe Leroy
8 siblings, 0 replies; 12+ messages in thread
From: Christophe Leroy @ 2021-10-23 11:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
After init, set readonly memory as ROX and set readwrite
memory as RWX, if STRICT_KERNEL_RWX is enabled.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: No change
---
arch/powerpc/mm/mmu_decl.h | 2 +-
arch/powerpc/mm/nohash/fsl_book3e.c | 32 +++++++++++++++++++++++++----
2 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index e13a3c0caa02..0dd4c18f8363 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -168,7 +168,7 @@ static inline phys_addr_t v_block_mapped(unsigned long va) { return 0; }
static inline unsigned long p_block_mapped(phys_addr_t pa) { return 0; }
#endif
-#if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_PPC_8xx)
+#if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_PPC_8xx) || defined(CONFIG_PPC_FSL_BOOK3E)
void mmu_mark_initmem_nx(void);
void mmu_mark_rodata_ro(void);
#else
diff --git a/arch/powerpc/mm/nohash/fsl_book3e.c b/arch/powerpc/mm/nohash/fsl_book3e.c
index 88132cab3442..b231a54f540c 100644
--- a/arch/powerpc/mm/nohash/fsl_book3e.c
+++ b/arch/powerpc/mm/nohash/fsl_book3e.c
@@ -182,7 +182,7 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,
/* Calculate CAM values */
for (i = 0; boundary && i < max_cam_idx; i++) {
unsigned long cam_sz;
- pgprot_t prot = PAGE_KERNEL_X;
+ pgprot_t prot = init ? PAGE_KERNEL_X : PAGE_KERNEL_ROX;
cam_sz = calc_cam_sz(boundary, virt, phys);
if (!dryrun)
@@ -195,7 +195,7 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,
}
for (ram -= amount_mapped; ram && i < max_cam_idx; i++) {
unsigned long cam_sz;
- pgprot_t prot = PAGE_KERNEL_X;
+ pgprot_t prot = init ? PAGE_KERNEL_X : PAGE_KERNEL;
cam_sz = calc_cam_sz(ram, virt, phys);
if (!dryrun)
@@ -210,8 +210,13 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,
if (dryrun)
return amount_mapped;
- loadcam_multi(0, i, max_cam_idx);
- tlbcam_index = i;
+ if (init) {
+ loadcam_multi(0, i, max_cam_idx);
+ tlbcam_index = i;
+ } else {
+ loadcam_multi(0, i, 0);
+ WARN_ON(i > tlbcam_index);
+ }
#ifdef CONFIG_PPC64
get_paca()->tcd.esel_next = i;
@@ -280,6 +285,25 @@ void __init adjust_total_lowmem(void)
memblock_set_current_limit(memstart_addr + __max_low_memory);
}
+#ifdef CONFIG_STRICT_KERNEL_RWX
+void mmu_mark_rodata_ro(void)
+{
+ /* Everything is done in mmu_mark_initmem_nx() */
+}
+#endif
+
+void mmu_mark_initmem_nx(void)
+{
+ unsigned long remapped;
+
+ if (!strict_kernel_rwx_enabled())
+ return;
+
+ remapped = map_mem_in_cams(__max_low_memory, CONFIG_LOWMEM_CAM_NUM, false, false);
+
+ WARN_ON(__max_low_memory != remapped);
+}
+
void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
{
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 10/10] powerpc/fsl_booke: Enable STRICT_KERNEL_RWX
2021-10-23 11:47 [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() Christophe Leroy
` (7 preceding siblings ...)
2021-10-23 11:47 ` [PATCH v2 09/10] powerpc/fsl_booke: Update of TLBCAMs after init Christophe Leroy
@ 2021-10-23 11:47 ` Christophe Leroy
8 siblings, 0 replies; 12+ messages in thread
From: Christophe Leroy @ 2021-10-23 11:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
Enable STRICT_KERNEL_RWX on fsl_booke.
For that, we need additional TLBCAMs dedicated to linear mapping,
based on the alignment of _sinittext.
By default, up to 768 Mbytes of memory are mapped.
It uses 3 TLBCAMs of size 256 Mbytes.
With a data alignment of 16, we need up to 9 TLBCAMs:
16/16/16/16/64/64/64/256/256
With a data alignment of 4, we need up to 12 TLBCAMs:
4/4/4/4/16/16/16/64/64/64/256/256
With a data alignment of 1, we need up to 15 TLBCAMs:
1/1/1/1/4/4/4/16/16/16/64/64/64/256/256
By default, set a 16 Mbytes alignment as a compromise between memory
usage and number of TLBCAMs. This can be adjusted manually when needed.
For the time being, it doens't work when the base is randomised.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: No change
---
arch/powerpc/Kconfig | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6b9f523882c5..939a47642a9c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -139,6 +139,7 @@ config PPC
select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64
select ARCH_HAS_SET_MEMORY
select ARCH_HAS_STRICT_KERNEL_RWX if (PPC_BOOK3S || PPC_8xx || 40x) && !HIBERNATION
+ select ARCH_HAS_STRICT_KERNEL_RWX if FSL_BOOKE && !HIBERNATION && !RANDOMIZE_BASE
select ARCH_HAS_STRICT_MODULE_RWX if ARCH_HAS_STRICT_KERNEL_RWX && !PPC_BOOK3S_32
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UACCESS_FLUSHCACHE
@@ -778,7 +779,8 @@ config DATA_SHIFT_BOOL
bool "Set custom data alignment"
depends on ADVANCED_OPTIONS
depends on STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE
- depends on PPC_BOOK3S_32 || (PPC_8xx && !PIN_TLB_DATA && !STRICT_KERNEL_RWX)
+ depends on PPC_BOOK3S_32 || (PPC_8xx && !PIN_TLB_DATA && !STRICT_KERNEL_RWX) || \
+ FSL_BOOKE
help
This option allows you to set the kernel data alignment. When
RAM is mapped by blocks, the alignment needs to fit the size and
@@ -791,11 +793,13 @@ config DATA_SHIFT
default 24 if STRICT_KERNEL_RWX && PPC64
range 17 28 if (STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE) && PPC_BOOK3S_32
range 19 23 if (STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE) && PPC_8xx
+ range 20 24 if (STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE) && PPC_FSL_BOOKE
default 22 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default 18 if (DEBUG_PAGEALLOC || KFENCE) && PPC_BOOK3S_32
default 23 if STRICT_KERNEL_RWX && PPC_8xx
default 23 if (DEBUG_PAGEALLOC || KFENCE) && PPC_8xx && PIN_TLB_DATA
default 19 if (DEBUG_PAGEALLOC || KFENCE) && PPC_8xx
+ default 24 if STRICT_KERNEL_RWX && FSL_BOOKE
default PPC_PAGE_SHIFT
help
On Book3S 32 (603+), DBATs are used to map kernel text and rodata RO.
@@ -1123,7 +1127,10 @@ config LOWMEM_CAM_NUM_BOOL
config LOWMEM_CAM_NUM
depends on FSL_BOOKE
int "Number of CAMs to use to map low memory" if LOWMEM_CAM_NUM_BOOL
- default 3
+ default 3 if !STRICT_KERNEL_RWX
+ default 9 if DATA_SHIFT >= 24
+ default 12 if DATA_SHIFT >= 22
+ default 15
config DYNAMIC_MEMSTART
bool "Enable page aligned dynamic load address for kernel"
--
2.31.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2 02/10] powerpc/book3e: Fix set_memory_x() and set_memory_nx()
2021-10-23 11:47 ` [PATCH v2 02/10] powerpc/book3e: Fix set_memory_x() and set_memory_nx() Christophe Leroy
@ 2021-10-25 21:53 ` Christophe Leroy
2021-10-26 7:03 ` Christophe Leroy
0 siblings, 1 reply; 12+ messages in thread
From: Christophe Leroy @ 2021-10-25 21:53 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
On 23/10/2021 13:47, Christophe Leroy wrote:
> set_memory_x() calls pte_mkexec() which sets _PAGE_EXEC.
> set_memory_nx() calls pte_exprotec() which clears _PAGE_EXEC.
>
> Book3e has 2 bits, UX and SX, which defines the exec rights
> resp. for user (PR=1) and for kernel (PR=0).
>
> _PAGE_EXEC is defined as UX only.
>
> An executable kernel page is set with either _PAGE_KERNEL_RWX
> or _PAGE_KERNEL_ROX, which both have SX set and UX cleared.
>
> So set_memory_nx() call for an executable kernel page does
> nothing because UX is already cleared.
>
> And set_memory_x() on a non-executable kernel page makes it
> executable for the user and keeps it non-executable for kernel.
>
> Also, pte_exec() always returns 'false' on kernel pages, because
> it checks _PAGE_EXEC which doesn't include SX, so for instance
> the W+X check doesn't work.
>
> To fix this:
> - change tlb_low_64e.S to use _PAGE_BAP_UX instead of _PAGE_USER
> - sets both UX and SX in _PAGE_EXEC so that pte_user() returns
> true whenever one of the two bits is set and pte_exprotect()
> clears both bits.
> - Define a book3e specific version of pte_mkexec() which sets
> either SX or UX based on UR.
>
> Fixes: 1f9ad21c3b38 ("powerpc/mm: Implement set_memory() routines")
> Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
> ---
> v2: New
pte_mkexec() in nohash/64/pgtable.h conflicts with the one in
nohash/pte_book3e.h
Should guard it with #ifndef pte_mkexec(), but as pte_book3e is the
only user in 64 bits, then just remove it from there.
Send v3 with only that change compared to v2.
Christophe
> ---
> arch/powerpc/include/asm/nohash/32/pgtable.h | 2 ++
> arch/powerpc/include/asm/nohash/pte-book3e.h | 18 ++++++++++++++----
> arch/powerpc/mm/nohash/tlb_low_64e.S | 8 ++++----
> 3 files changed, 20 insertions(+), 8 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h
> index ac0a5ff48c3a..d6ba821a56ce 100644
> --- a/arch/powerpc/include/asm/nohash/32/pgtable.h
> +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h
> @@ -193,10 +193,12 @@ static inline pte_t pte_wrprotect(pte_t pte)
> }
> #endif
>
> +#ifndef pte_mkexec
> static inline pte_t pte_mkexec(pte_t pte)
> {
> return __pte(pte_val(pte) | _PAGE_EXEC);
> }
> +#endif
>
> #define pmd_none(pmd) (!pmd_val(pmd))
> #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD)
> diff --git a/arch/powerpc/include/asm/nohash/pte-book3e.h b/arch/powerpc/include/asm/nohash/pte-book3e.h
> index 813918f40765..f798640422c2 100644
> --- a/arch/powerpc/include/asm/nohash/pte-book3e.h
> +++ b/arch/powerpc/include/asm/nohash/pte-book3e.h
> @@ -48,7 +48,7 @@
> #define _PAGE_WRITETHRU 0x800000 /* W: cache write-through */
>
> /* "Higher level" linux bit combinations */
> -#define _PAGE_EXEC _PAGE_BAP_UX /* .. and was cache cleaned */
> +#define _PAGE_EXEC (_PAGE_BAP_SX | _PAGE_BAP_UX) /* .. and was cache cleaned */
> #define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */
> #define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY)
> #define _PAGE_KERNEL_RO (_PAGE_BAP_SR)
> @@ -93,11 +93,11 @@
> /* Permission masks used to generate the __P and __S table */
> #define PAGE_NONE __pgprot(_PAGE_BASE)
> #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
> -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
> +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_BAP_UX)
> #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
> -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
> +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX)
> #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
> -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
> +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX)
>
> #ifndef __ASSEMBLY__
> static inline pte_t pte_mkprivileged(pte_t pte)
> @@ -113,6 +113,16 @@ static inline pte_t pte_mkuser(pte_t pte)
> }
>
> #define pte_mkuser pte_mkuser
> +
> +static inline pte_t pte_mkexec(pte_t pte)
> +{
> + if (pte_val(pte) & _PAGE_BAP_UR)
> + return __pte((pte_val(pte) & ~_PAGE_BAP_SX) | _PAGE_BAP_UX);
> + else
> + return __pte((pte_val(pte) & ~_PAGE_BAP_UX) | _PAGE_BAP_SX);
> +}
> +#define pte_mkexec pte_mkexec
> +
> #endif /* __ASSEMBLY__ */
>
> #endif /* __KERNEL__ */
> diff --git a/arch/powerpc/mm/nohash/tlb_low_64e.S b/arch/powerpc/mm/nohash/tlb_low_64e.S
> index bf24451f3e71..9235e720e357 100644
> --- a/arch/powerpc/mm/nohash/tlb_low_64e.S
> +++ b/arch/powerpc/mm/nohash/tlb_low_64e.S
> @@ -222,7 +222,7 @@ tlb_miss_kernel_bolted:
>
> tlb_miss_fault_bolted:
> /* We need to check if it was an instruction miss */
> - andi. r10,r11,_PAGE_EXEC|_PAGE_BAP_SX
> + andi. r10,r11,_PAGE_BAP_UX|_PAGE_BAP_SX
> bne itlb_miss_fault_bolted
> dtlb_miss_fault_bolted:
> tlb_epilog_bolted
> @@ -239,7 +239,7 @@ itlb_miss_fault_bolted:
> srdi r15,r16,60 /* get region */
> bne- itlb_miss_fault_bolted
>
> - li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */
> + li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */
>
> /* We do the user/kernel test for the PID here along with the RW test
> */
> @@ -614,7 +614,7 @@ itlb_miss_fault_e6500:
>
> /* We do the user/kernel test for the PID here along with the RW test
> */
> - li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */
> + li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */
> oris r11,r11,_PAGE_ACCESSED@h
>
> cmpldi cr0,r15,0 /* Check for user region */
> @@ -734,7 +734,7 @@ normal_tlb_miss_done:
>
> normal_tlb_miss_access_fault:
> /* We need to check if it was an instruction miss */
> - andi. r10,r11,_PAGE_EXEC
> + andi. r10,r11,_PAGE_BAP_UX
> bne 1f
> ld r14,EX_TLB_DEAR(r12)
> ld r15,EX_TLB_ESR(r12)
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 02/10] powerpc/book3e: Fix set_memory_x() and set_memory_nx()
2021-10-25 21:53 ` Christophe Leroy
@ 2021-10-26 7:03 ` Christophe Leroy
0 siblings, 0 replies; 12+ messages in thread
From: Christophe Leroy @ 2021-10-26 7:03 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev, linux-kernel
Le 25/10/2021 à 23:53, Christophe Leroy a écrit :
>
>
> On 23/10/2021 13:47, Christophe Leroy wrote:
>> set_memory_x() calls pte_mkexec() which sets _PAGE_EXEC.
>> set_memory_nx() calls pte_exprotec() which clears _PAGE_EXEC.
>>
>> Book3e has 2 bits, UX and SX, which defines the exec rights
>> resp. for user (PR=1) and for kernel (PR=0).
>>
>> _PAGE_EXEC is defined as UX only.
>>
>> An executable kernel page is set with either _PAGE_KERNEL_RWX
>> or _PAGE_KERNEL_ROX, which both have SX set and UX cleared.
>>
>> So set_memory_nx() call for an executable kernel page does
>> nothing because UX is already cleared.
>>
>> And set_memory_x() on a non-executable kernel page makes it
>> executable for the user and keeps it non-executable for kernel.
>>
>> Also, pte_exec() always returns 'false' on kernel pages, because
>> it checks _PAGE_EXEC which doesn't include SX, so for instance
>> the W+X check doesn't work.
>>
>> To fix this:
>> - change tlb_low_64e.S to use _PAGE_BAP_UX instead of _PAGE_USER
>> - sets both UX and SX in _PAGE_EXEC so that pte_user() returns
>> true whenever one of the two bits is set and pte_exprotect()
>> clears both bits.
>> - Define a book3e specific version of pte_mkexec() which sets
>> either SX or UX based on UR.
>>
>> Fixes: 1f9ad21c3b38 ("powerpc/mm: Implement set_memory() routines")
>> Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
>> ---
>> v2: New
>
> pte_mkexec() in nohash/64/pgtable.h conflicts with the one in
> nohash/pte_book3e.h
>
> Should guard it with #ifndef pte_mkexec(), but as pte_book3e is the
> only user in 64 bits, then just remove it from there.
>
> Send v3 with only that change compared to v2.
Series v1 was merged into next so I submitted followup series with the
three fixes.
Christophe
>
> Christophe
>
>> ---
>> arch/powerpc/include/asm/nohash/32/pgtable.h | 2 ++
>> arch/powerpc/include/asm/nohash/pte-book3e.h | 18 ++++++++++++++----
>> arch/powerpc/mm/nohash/tlb_low_64e.S | 8 ++++----
>> 3 files changed, 20 insertions(+), 8 deletions(-)
>>
>> diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h
>> b/arch/powerpc/include/asm/nohash/32/pgtable.h
>> index ac0a5ff48c3a..d6ba821a56ce 100644
>> --- a/arch/powerpc/include/asm/nohash/32/pgtable.h
>> +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h
>> @@ -193,10 +193,12 @@ static inline pte_t pte_wrprotect(pte_t pte)
>> }
>> #endif
>> +#ifndef pte_mkexec
>> static inline pte_t pte_mkexec(pte_t pte)
>> {
>> return __pte(pte_val(pte) | _PAGE_EXEC);
>> }
>> +#endif
>> #define pmd_none(pmd) (!pmd_val(pmd))
>> #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD)
>> diff --git a/arch/powerpc/include/asm/nohash/pte-book3e.h
>> b/arch/powerpc/include/asm/nohash/pte-book3e.h
>> index 813918f40765..f798640422c2 100644
>> --- a/arch/powerpc/include/asm/nohash/pte-book3e.h
>> +++ b/arch/powerpc/include/asm/nohash/pte-book3e.h
>> @@ -48,7 +48,7 @@
>> #define _PAGE_WRITETHRU 0x800000 /* W: cache write-through */
>> /* "Higher level" linux bit combinations */
>> -#define _PAGE_EXEC _PAGE_BAP_UX /* .. and was cache cleaned */
>> +#define _PAGE_EXEC (_PAGE_BAP_SX | _PAGE_BAP_UX) /* .. and was
>> cache cleaned */
>> #define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write
>> permission */
>> #define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR |
>> _PAGE_DIRTY)
>> #define _PAGE_KERNEL_RO (_PAGE_BAP_SR)
>> @@ -93,11 +93,11 @@
>> /* Permission masks used to generate the __P and __S table */
>> #define PAGE_NONE __pgprot(_PAGE_BASE)
>> #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
>> -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW
>> | _PAGE_EXEC)
>> +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW
>> | _PAGE_BAP_UX)
>> #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
>> -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
>> +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX)
>> #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
>> -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER |
>> _PAGE_EXEC)
>> +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER |
>> _PAGE_BAP_UX)
>> #ifndef __ASSEMBLY__
>> static inline pte_t pte_mkprivileged(pte_t pte)
>> @@ -113,6 +113,16 @@ static inline pte_t pte_mkuser(pte_t pte)
>> }
>> #define pte_mkuser pte_mkuser
>> +
>> +static inline pte_t pte_mkexec(pte_t pte)
>> +{
>> + if (pte_val(pte) & _PAGE_BAP_UR)
>> + return __pte((pte_val(pte) & ~_PAGE_BAP_SX) | _PAGE_BAP_UX);
>> + else
>> + return __pte((pte_val(pte) & ~_PAGE_BAP_UX) | _PAGE_BAP_SX);
>> +}
>> +#define pte_mkexec pte_mkexec
>> +
>> #endif /* __ASSEMBLY__ */
>> #endif /* __KERNEL__ */
>> diff --git a/arch/powerpc/mm/nohash/tlb_low_64e.S
>> b/arch/powerpc/mm/nohash/tlb_low_64e.S
>> index bf24451f3e71..9235e720e357 100644
>> --- a/arch/powerpc/mm/nohash/tlb_low_64e.S
>> +++ b/arch/powerpc/mm/nohash/tlb_low_64e.S
>> @@ -222,7 +222,7 @@ tlb_miss_kernel_bolted:
>> tlb_miss_fault_bolted:
>> /* We need to check if it was an instruction miss */
>> - andi. r10,r11,_PAGE_EXEC|_PAGE_BAP_SX
>> + andi. r10,r11,_PAGE_BAP_UX|_PAGE_BAP_SX
>> bne itlb_miss_fault_bolted
>> dtlb_miss_fault_bolted:
>> tlb_epilog_bolted
>> @@ -239,7 +239,7 @@ itlb_miss_fault_bolted:
>> srdi r15,r16,60 /* get region */
>> bne- itlb_miss_fault_bolted
>> - li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */
>> + li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */
>> /* We do the user/kernel test for the PID here along with the RW
>> test
>> */
>> @@ -614,7 +614,7 @@ itlb_miss_fault_e6500:
>> /* We do the user/kernel test for the PID here along with the RW
>> test
>> */
>> - li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */
>> + li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */
>> oris r11,r11,_PAGE_ACCESSED@h
>> cmpldi cr0,r15,0 /* Check for user region */
>> @@ -734,7 +734,7 @@ normal_tlb_miss_done:
>> normal_tlb_miss_access_fault:
>> /* We need to check if it was an instruction miss */
>> - andi. r10,r11,_PAGE_EXEC
>> + andi. r10,r11,_PAGE_BAP_UX
>> bne 1f
>> ld r14,EX_TLB_DEAR(r12)
>> ld r15,EX_TLB_ESR(r12)
>>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2021-10-26 7:04 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-23 11:47 [PATCH v2 01/10] powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 02/10] powerpc/book3e: Fix set_memory_x() and set_memory_nx() Christophe Leroy
2021-10-25 21:53 ` Christophe Leroy
2021-10-26 7:03 ` Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 03/10] powerpc/booke: Disable STRICT_KERNEL_RWX, DEBUG_PAGEALLOC and KFENCE Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 04/10] powerpc/fsl_booke: Rename fsl_booke.c to fsl_book3e.c Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 05/10] powerpc/fsl_booke: Take exec flag into account when setting TLBCAMs Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 06/10] powerpc/fsl_booke: Enable reloading of TLBCAM without switching to AS1 Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 07/10] powerpc/fsl_booke: Tell map_mem_in_cams() if init is done Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 08/10] powerpc/fsl_booke: Allocate separate TLBCAMs for readonly memory Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 09/10] powerpc/fsl_booke: Update of TLBCAMs after init Christophe Leroy
2021-10-23 11:47 ` [PATCH v2 10/10] powerpc/fsl_booke: Enable STRICT_KERNEL_RWX Christophe Leroy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).