Skip to content

Commit

Permalink
powerpc/mm: Cleanup handling of execute permission
Browse files Browse the repository at this point in the history
This is an attempt at cleaning up a bit the way we handle execute
permission on powerpc. _PAGE_HWEXEC is gone, _PAGE_EXEC is now only
defined by CPUs that can do something with it, and the myriad of
#ifdef's in the I$/D$ coherency code is reduced to 2 cases that
hopefully should cover everything.

The logic on BookE is a little bit different than what it was though
not by much. Since now, _PAGE_EXEC will be set by the generic code
for executable pages, we need to filter out if they are unclean and
recover it. However, I don't expect the code to be more bloated than
it already was in that area due to that change.

I could boast that this brings proper enforcing of per-page execute
permissions to all BookE and 40x but in fact, we've had that now for
some time as a side effect of my previous rework in that area (and
I didn't even know it :-) We would only enable execute permission if
the page was cache clean and we would only cache clean it if we took
and exec fault. Since we now enforce that the later only work if
VM_EXEC is part of the VMA flags, we de-fact already enforce per-page
execute permissions... Unless I missed something

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Benjamin Herrenschmidt committed Aug 27, 2009
1 parent f480fe3 commit ea3cc33
Show file tree
Hide file tree
Showing 15 changed files with 149 additions and 87 deletions.
7 changes: 3 additions & 4 deletions arch/powerpc/include/asm/pgtable-ppc32.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ static inline unsigned long pte_update(pte_t *p,
#endif /* !PTE_ATOMIC_UPDATES */

#ifdef CONFIG_44x
if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
if ((old & _PAGE_USER) && (old & _PAGE_EXEC))
icache_44x_need_flush = 1;
#endif
return old;
Expand Down Expand Up @@ -217,7 +217,7 @@ static inline unsigned long long pte_update(pte_t *p,
#endif /* !PTE_ATOMIC_UPDATES */

#ifdef CONFIG_44x
if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
if ((old & _PAGE_USER) && (old & _PAGE_EXEC))
icache_44x_need_flush = 1;
#endif
return old;
Expand Down Expand Up @@ -267,8 +267,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
{
unsigned long bits = pte_val(entry) &
(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW |
_PAGE_HWEXEC | _PAGE_EXEC);
(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
pte_update(ptep, 0, bits);
}

Expand Down
3 changes: 1 addition & 2 deletions arch/powerpc/include/asm/pgtable-ppc64.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
{
unsigned long bits = pte_val(entry) &
(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW |
_PAGE_EXEC | _PAGE_HWEXEC);
(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);

#ifdef PTE_ATOMIC_UPDATES
unsigned long old, tmp;
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/include/asm/pte-40x.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
#define _PAGE_RW 0x040 /* software: Writes permitted */
#define _PAGE_DIRTY 0x080 /* software: dirty page */
#define _PAGE_HWWRITE 0x100 /* hardware: Dirty & RW, set in exception */
#define _PAGE_HWEXEC 0x200 /* hardware: EX permission */
#define _PAGE_EXEC 0x200 /* hardware: EX permission */
#define _PAGE_ACCESSED 0x400 /* software: R: page referenced */

#define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/include/asm/pte-44x.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
#define _PAGE_PRESENT 0x00000001 /* S: PTE valid */
#define _PAGE_RW 0x00000002 /* S: Write permission */
#define _PAGE_FILE 0x00000004 /* S: nonlinear file mapping */
#define _PAGE_HWEXEC 0x00000004 /* H: Execute permission */
#define _PAGE_EXEC 0x00000004 /* H: Execute permission */
#define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */
#define _PAGE_DIRTY 0x00000010 /* S: Page dirty */
#define _PAGE_SPECIAL 0x00000020 /* S: Special page */
Expand Down
1 change: 0 additions & 1 deletion arch/powerpc/include/asm/pte-8xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
/* These five software bits must be masked out when the entry is loaded
* into the TLB.
*/
#define _PAGE_EXEC 0x0008 /* software: i-cache coherency required */
#define _PAGE_GUARDED 0x0010 /* software: guarded access */
#define _PAGE_DIRTY 0x0020 /* software: page changed */
#define _PAGE_RW 0x0040 /* software: user write access allowed */
Expand Down
13 changes: 7 additions & 6 deletions arch/powerpc/include/asm/pte-book3e.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@
#define _PAGE_WRITETHRU 0x800000 /* W: cache write-through */

/* "Higher level" linux bit combinations */
#define _PAGE_EXEC _PAGE_BAP_SX /* Can be executed from potentially */
#define _PAGE_HWEXEC _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)
#define _PAGE_USER (_PAGE_BAP_UR | _PAGE_BAP_SR) /* Can be read */
#define _PAGE_EXEC _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)
#define _PAGE_KERNEL_RWX (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY | _PAGE_BAP_SX)
#define _PAGE_KERNEL_ROX (_PAGE_BAP_SR | _PAGE_BAP_SX)
#define _PAGE_USER (_PAGE_BAP_UR | _PAGE_BAP_SR) /* Can be read */

#define _PAGE_HASHPTE 0
#define _PAGE_BUSY 0
Expand Down
22 changes: 11 additions & 11 deletions arch/powerpc/include/asm/pte-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
#ifndef _PAGE_HWWRITE
#define _PAGE_HWWRITE 0
#endif
#ifndef _PAGE_HWEXEC
#define _PAGE_HWEXEC 0
#endif
#ifndef _PAGE_EXEC
#define _PAGE_EXEC 0
#endif
Expand Down Expand Up @@ -48,10 +45,16 @@
#define PMD_PAGE_SIZE(pmd) bad_call_to_PMD_PAGE_SIZE()
#endif
#ifndef _PAGE_KERNEL_RO
#define _PAGE_KERNEL_RO 0
#define _PAGE_KERNEL_RO 0
#endif
#ifndef _PAGE_KERNEL_ROX
#define _PAGE_KERNEL_ROX (_PAGE_EXEC)
#endif
#ifndef _PAGE_KERNEL_RW
#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)
#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)
#endif
#ifndef _PAGE_KERNEL_RWX
#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE | _PAGE_EXEC)
#endif
#ifndef _PAGE_HPTEFLAGS
#define _PAGE_HPTEFLAGS _PAGE_HASHPTE
Expand Down Expand Up @@ -96,8 +99,7 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
#define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
_PAGE_WRITETHRU | _PAGE_ENDIAN | _PAGE_4K_PFN | \
_PAGE_USER | _PAGE_ACCESSED | \
_PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \
_PAGE_EXEC | _PAGE_HWEXEC)
_PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | _PAGE_EXEC)

/*
* We define 2 sets of base prot bits, one for basic pages (ie,
Expand Down Expand Up @@ -154,11 +156,9 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
_PAGE_NO_CACHE)
#define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
_PAGE_NO_CACHE | _PAGE_GUARDED)
#define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW | _PAGE_EXEC | \
_PAGE_HWEXEC)
#define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX)
#define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO)
#define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO | _PAGE_EXEC | \
_PAGE_HWEXEC)
#define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX)

/* Protection used for kernel text. We want the debuggers to be able to
* set breakpoints anywhere, so don't write protect the kernel text
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/include/asm/pte-fsl-booke.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#define _PAGE_FILE 0x00002 /* S: when !present: nonlinear file mapping */
#define _PAGE_RW 0x00004 /* S: Write permission (SW) */
#define _PAGE_DIRTY 0x00008 /* S: Page dirty */
#define _PAGE_HWEXEC 0x00010 /* H: SX permission */
#define _PAGE_EXEC 0x00010 /* H: SX permission */
#define _PAGE_ACCESSED 0x00020 /* S: Page referenced */

#define _PAGE_ENDIAN 0x00040 /* H: E bit */
Expand Down
1 change: 0 additions & 1 deletion arch/powerpc/include/asm/pte-hash32.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#define _PAGE_WRITETHRU 0x040 /* W: cache write-through */
#define _PAGE_DIRTY 0x080 /* C: page changed */
#define _PAGE_ACCESSED 0x100 /* R: page referenced */
#define _PAGE_EXEC 0x200 /* software: i-cache coherency required */
#define _PAGE_RW 0x400 /* software: user write access allowed */
#define _PAGE_SPECIAL 0x800 /* software: Special page */

Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/head_44x.S
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ tlb_44x_patch_hwater_D:
mtspr SPRN_MMUCR,r12

/* Make up the required permissions */
li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_HWEXEC
li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC

/* Compute pgdir/pmd offset */
rlwinm r12, r10, PPC44x_PGD_OFF_SHIFT, PPC44x_PGD_OFF_MASK_BIT, 29
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/kernel/head_fsl_booke.S
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ interrupt_base:

4:
/* Make up the required permissions */
li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_HWEXEC
li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC

FIND_PTE
andc. r13,r13,r11 /* Check permission */
Expand Down Expand Up @@ -742,7 +742,7 @@ finish_tlb_load:
#endif
mtspr SPRN_MAS2, r12

li r10, (_PAGE_HWEXEC | _PAGE_PRESENT)
li r10, (_PAGE_EXEC | _PAGE_PRESENT)
rlwimi r10, r11, 31, 29, 29 /* extract _PAGE_DIRTY into SW */
and r12, r11, r10
andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/mm/40x_mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ unsigned long __init mmu_mapin_ram(void)

while (s >= LARGE_PAGE_SIZE_16M) {
pmd_t *pmdp;
unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE;
unsigned long val = p | _PMD_SIZE_16M | _PAGE_EXEC | _PAGE_HWWRITE;

pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v);
pmd_val(*pmdp++) = val;
Expand All @@ -120,7 +120,7 @@ unsigned long __init mmu_mapin_ram(void)

while (s >= LARGE_PAGE_SIZE_4M) {
pmd_t *pmdp;
unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE;
unsigned long val = p | _PMD_SIZE_4M | _PAGE_EXEC | _PAGE_HWWRITE;

pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v);
pmd_val(*pmdp) = val;
Expand Down
Loading

0 comments on commit ea3cc33

Please sign in to comment.