diff options
-rw-r--r-- | arch/powerpc/include/asm/pgtable-ppc32.h | 7 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pgtable-ppc64.h | 3 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pte-40x.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pte-44x.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pte-8xx.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pte-book3e.h | 13 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pte-common.h | 22 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pte-fsl-booke.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pte-hash32.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_44x.S | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_fsl_booke.S | 4 | ||||
-rw-r--r-- | arch/powerpc/mm/40x_mmu.c | 4 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable.c | 167 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable_32.c | 2 | ||||
-rw-r--r-- | arch/powerpc/mm/tlb_low_64e.S | 4 |
15 files changed, 149 insertions, 87 deletions
diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h index c9ff9d75990e..f2c52e253956 100644 --- a/arch/powerpc/include/asm/pgtable-ppc32.h +++ b/arch/powerpc/include/asm/pgtable-ppc32.h | |||
@@ -186,7 +186,7 @@ static inline unsigned long pte_update(pte_t *p, | |||
186 | #endif /* !PTE_ATOMIC_UPDATES */ | 186 | #endif /* !PTE_ATOMIC_UPDATES */ |
187 | 187 | ||
188 | #ifdef CONFIG_44x | 188 | #ifdef CONFIG_44x |
189 | if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC)) | 189 | if ((old & _PAGE_USER) && (old & _PAGE_EXEC)) |
190 | icache_44x_need_flush = 1; | 190 | icache_44x_need_flush = 1; |
191 | #endif | 191 | #endif |
192 | return old; | 192 | return old; |
@@ -217,7 +217,7 @@ static inline unsigned long long pte_update(pte_t *p, | |||
217 | #endif /* !PTE_ATOMIC_UPDATES */ | 217 | #endif /* !PTE_ATOMIC_UPDATES */ |
218 | 218 | ||
219 | #ifdef CONFIG_44x | 219 | #ifdef CONFIG_44x |
220 | if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC)) | 220 | if ((old & _PAGE_USER) && (old & _PAGE_EXEC)) |
221 | icache_44x_need_flush = 1; | 221 | icache_44x_need_flush = 1; |
222 | #endif | 222 | #endif |
223 | return old; | 223 | return old; |
@@ -267,8 +267,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, | |||
267 | static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry) | 267 | static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry) |
268 | { | 268 | { |
269 | unsigned long bits = pte_val(entry) & | 269 | unsigned long bits = pte_val(entry) & |
270 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | | 270 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); |
271 | _PAGE_HWEXEC | _PAGE_EXEC); | ||
272 | pte_update(ptep, 0, bits); | 271 | pte_update(ptep, 0, bits); |
273 | } | 272 | } |
274 | 273 | ||
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index 200ec2dfa034..806abe7a3fa5 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h | |||
@@ -313,8 +313,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, | |||
313 | static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry) | 313 | static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry) |
314 | { | 314 | { |
315 | unsigned long bits = pte_val(entry) & | 315 | unsigned long bits = pte_val(entry) & |
316 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | | 316 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); |
317 | _PAGE_EXEC | _PAGE_HWEXEC); | ||
318 | 317 | ||
319 | #ifdef PTE_ATOMIC_UPDATES | 318 | #ifdef PTE_ATOMIC_UPDATES |
320 | unsigned long old, tmp; | 319 | unsigned long old, tmp; |
diff --git a/arch/powerpc/include/asm/pte-40x.h b/arch/powerpc/include/asm/pte-40x.h index 07630faae029..6c3e1f4378d4 100644 --- a/arch/powerpc/include/asm/pte-40x.h +++ b/arch/powerpc/include/asm/pte-40x.h | |||
@@ -46,7 +46,7 @@ | |||
46 | #define _PAGE_RW 0x040 /* software: Writes permitted */ | 46 | #define _PAGE_RW 0x040 /* software: Writes permitted */ |
47 | #define _PAGE_DIRTY 0x080 /* software: dirty page */ | 47 | #define _PAGE_DIRTY 0x080 /* software: dirty page */ |
48 | #define _PAGE_HWWRITE 0x100 /* hardware: Dirty & RW, set in exception */ | 48 | #define _PAGE_HWWRITE 0x100 /* hardware: Dirty & RW, set in exception */ |
49 | #define _PAGE_HWEXEC 0x200 /* hardware: EX permission */ | 49 | #define _PAGE_EXEC 0x200 /* hardware: EX permission */ |
50 | #define _PAGE_ACCESSED 0x400 /* software: R: page referenced */ | 50 | #define _PAGE_ACCESSED 0x400 /* software: R: page referenced */ |
51 | 51 | ||
52 | #define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */ | 52 | #define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */ |
diff --git a/arch/powerpc/include/asm/pte-44x.h b/arch/powerpc/include/asm/pte-44x.h index 37e98bcf83e0..4192b9bad901 100644 --- a/arch/powerpc/include/asm/pte-44x.h +++ b/arch/powerpc/include/asm/pte-44x.h | |||
@@ -78,7 +78,7 @@ | |||
78 | #define _PAGE_PRESENT 0x00000001 /* S: PTE valid */ | 78 | #define _PAGE_PRESENT 0x00000001 /* S: PTE valid */ |
79 | #define _PAGE_RW 0x00000002 /* S: Write permission */ | 79 | #define _PAGE_RW 0x00000002 /* S: Write permission */ |
80 | #define _PAGE_FILE 0x00000004 /* S: nonlinear file mapping */ | 80 | #define _PAGE_FILE 0x00000004 /* S: nonlinear file mapping */ |
81 | #define _PAGE_HWEXEC 0x00000004 /* H: Execute permission */ | 81 | #define _PAGE_EXEC 0x00000004 /* H: Execute permission */ |
82 | #define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */ | 82 | #define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */ |
83 | #define _PAGE_DIRTY 0x00000010 /* S: Page dirty */ | 83 | #define _PAGE_DIRTY 0x00000010 /* S: Page dirty */ |
84 | #define _PAGE_SPECIAL 0x00000020 /* S: Special page */ | 84 | #define _PAGE_SPECIAL 0x00000020 /* S: Special page */ |
diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h index 8c6e31251034..94e979718dcf 100644 --- a/arch/powerpc/include/asm/pte-8xx.h +++ b/arch/powerpc/include/asm/pte-8xx.h | |||
@@ -36,7 +36,6 @@ | |||
36 | /* These five software bits must be masked out when the entry is loaded | 36 | /* These five software bits must be masked out when the entry is loaded |
37 | * into the TLB. | 37 | * into the TLB. |
38 | */ | 38 | */ |
39 | #define _PAGE_EXEC 0x0008 /* software: i-cache coherency required */ | ||
40 | #define _PAGE_GUARDED 0x0010 /* software: guarded access */ | 39 | #define _PAGE_GUARDED 0x0010 /* software: guarded access */ |
41 | #define _PAGE_DIRTY 0x0020 /* software: page changed */ | 40 | #define _PAGE_DIRTY 0x0020 /* software: page changed */ |
42 | #define _PAGE_RW 0x0040 /* software: user write access allowed */ | 41 | #define _PAGE_RW 0x0040 /* software: user write access allowed */ |
diff --git a/arch/powerpc/include/asm/pte-book3e.h b/arch/powerpc/include/asm/pte-book3e.h index 1d27c77d7704..9800565aebb8 100644 --- a/arch/powerpc/include/asm/pte-book3e.h +++ b/arch/powerpc/include/asm/pte-book3e.h | |||
@@ -37,12 +37,13 @@ | |||
37 | #define _PAGE_WRITETHRU 0x800000 /* W: cache write-through */ | 37 | #define _PAGE_WRITETHRU 0x800000 /* W: cache write-through */ |
38 | 38 | ||
39 | /* "Higher level" linux bit combinations */ | 39 | /* "Higher level" linux bit combinations */ |
40 | #define _PAGE_EXEC _PAGE_BAP_SX /* Can be executed from potentially */ | 40 | #define _PAGE_EXEC _PAGE_BAP_UX /* .. and was cache cleaned */ |
41 | #define _PAGE_HWEXEC _PAGE_BAP_UX /* .. and was cache cleaned */ | 41 | #define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */ |
42 | #define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */ | 42 | #define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY) |
43 | #define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY) | 43 | #define _PAGE_KERNEL_RO (_PAGE_BAP_SR) |
44 | #define _PAGE_KERNEL_RO (_PAGE_BAP_SR) | 44 | #define _PAGE_KERNEL_RWX (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY | _PAGE_BAP_SX) |
45 | #define _PAGE_USER (_PAGE_BAP_UR | _PAGE_BAP_SR) /* Can be read */ | 45 | #define _PAGE_KERNEL_ROX (_PAGE_BAP_SR | _PAGE_BAP_SX) |
46 | #define _PAGE_USER (_PAGE_BAP_UR | _PAGE_BAP_SR) /* Can be read */ | ||
46 | 47 | ||
47 | #define _PAGE_HASHPTE 0 | 48 | #define _PAGE_HASHPTE 0 |
48 | #define _PAGE_BUSY 0 | 49 | #define _PAGE_BUSY 0 |
diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h index 8bb6464ba619..c3b65076a263 100644 --- a/arch/powerpc/include/asm/pte-common.h +++ b/arch/powerpc/include/asm/pte-common.h | |||
@@ -13,9 +13,6 @@ | |||
13 | #ifndef _PAGE_HWWRITE | 13 | #ifndef _PAGE_HWWRITE |
14 | #define _PAGE_HWWRITE 0 | 14 | #define _PAGE_HWWRITE 0 |
15 | #endif | 15 | #endif |
16 | #ifndef _PAGE_HWEXEC | ||
17 | #define _PAGE_HWEXEC 0 | ||
18 | #endif | ||
19 | #ifndef _PAGE_EXEC | 16 | #ifndef _PAGE_EXEC |
20 | #define _PAGE_EXEC 0 | 17 | #define _PAGE_EXEC 0 |
21 | #endif | 18 | #endif |
@@ -48,10 +45,16 @@ | |||
48 | #define PMD_PAGE_SIZE(pmd) bad_call_to_PMD_PAGE_SIZE() | 45 | #define PMD_PAGE_SIZE(pmd) bad_call_to_PMD_PAGE_SIZE() |
49 | #endif | 46 | #endif |
50 | #ifndef _PAGE_KERNEL_RO | 47 | #ifndef _PAGE_KERNEL_RO |
51 | #define _PAGE_KERNEL_RO 0 | 48 | #define _PAGE_KERNEL_RO 0 |
49 | #endif | ||
50 | #ifndef _PAGE_KERNEL_ROX | ||
51 | #define _PAGE_KERNEL_ROX (_PAGE_EXEC) | ||
52 | #endif | 52 | #endif |
53 | #ifndef _PAGE_KERNEL_RW | 53 | #ifndef _PAGE_KERNEL_RW |
54 | #define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE) | 54 | #define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE) |
55 | #endif | ||
56 | #ifndef _PAGE_KERNEL_RWX | ||
57 | #define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE | _PAGE_EXEC) | ||
55 | #endif | 58 | #endif |
56 | #ifndef _PAGE_HPTEFLAGS | 59 | #ifndef _PAGE_HPTEFLAGS |
57 | #define _PAGE_HPTEFLAGS _PAGE_HASHPTE | 60 | #define _PAGE_HPTEFLAGS _PAGE_HASHPTE |
@@ -96,8 +99,7 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); | |||
96 | #define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \ | 99 | #define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \ |
97 | _PAGE_WRITETHRU | _PAGE_ENDIAN | _PAGE_4K_PFN | \ | 100 | _PAGE_WRITETHRU | _PAGE_ENDIAN | _PAGE_4K_PFN | \ |
98 | _PAGE_USER | _PAGE_ACCESSED | \ | 101 | _PAGE_USER | _PAGE_ACCESSED | \ |
99 | _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \ | 102 | _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | _PAGE_EXEC) |
100 | _PAGE_EXEC | _PAGE_HWEXEC) | ||
101 | 103 | ||
102 | /* | 104 | /* |
103 | * We define 2 sets of base prot bits, one for basic pages (ie, | 105 | * We define 2 sets of base prot bits, one for basic pages (ie, |
@@ -154,11 +156,9 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); | |||
154 | _PAGE_NO_CACHE) | 156 | _PAGE_NO_CACHE) |
155 | #define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ | 157 | #define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ |
156 | _PAGE_NO_CACHE | _PAGE_GUARDED) | 158 | _PAGE_NO_CACHE | _PAGE_GUARDED) |
157 | #define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW | _PAGE_EXEC | \ | 159 | #define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX) |
158 | _PAGE_HWEXEC) | ||
159 | #define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) | 160 | #define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) |
160 | #define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO | _PAGE_EXEC | \ | 161 | #define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX) |
161 | _PAGE_HWEXEC) | ||
162 | 162 | ||
163 | /* Protection used for kernel text. We want the debuggers to be able to | 163 | /* Protection used for kernel text. We want the debuggers to be able to |
164 | * set breakpoints anywhere, so don't write protect the kernel text | 164 | * set breakpoints anywhere, so don't write protect the kernel text |
diff --git a/arch/powerpc/include/asm/pte-fsl-booke.h b/arch/powerpc/include/asm/pte-fsl-booke.h index 10820f58acf5..ce8a9e94ce7f 100644 --- a/arch/powerpc/include/asm/pte-fsl-booke.h +++ b/arch/powerpc/include/asm/pte-fsl-booke.h | |||
@@ -23,7 +23,7 @@ | |||
23 | #define _PAGE_FILE 0x00002 /* S: when !present: nonlinear file mapping */ | 23 | #define _PAGE_FILE 0x00002 /* S: when !present: nonlinear file mapping */ |
24 | #define _PAGE_RW 0x00004 /* S: Write permission (SW) */ | 24 | #define _PAGE_RW 0x00004 /* S: Write permission (SW) */ |
25 | #define _PAGE_DIRTY 0x00008 /* S: Page dirty */ | 25 | #define _PAGE_DIRTY 0x00008 /* S: Page dirty */ |
26 | #define _PAGE_HWEXEC 0x00010 /* H: SX permission */ | 26 | #define _PAGE_EXEC 0x00010 /* H: SX permission */ |
27 | #define _PAGE_ACCESSED 0x00020 /* S: Page referenced */ | 27 | #define _PAGE_ACCESSED 0x00020 /* S: Page referenced */ |
28 | 28 | ||
29 | #define _PAGE_ENDIAN 0x00040 /* H: E bit */ | 29 | #define _PAGE_ENDIAN 0x00040 /* H: E bit */ |
diff --git a/arch/powerpc/include/asm/pte-hash32.h b/arch/powerpc/include/asm/pte-hash32.h index 16e571c7f9ef..4aad4132d0a8 100644 --- a/arch/powerpc/include/asm/pte-hash32.h +++ b/arch/powerpc/include/asm/pte-hash32.h | |||
@@ -26,7 +26,6 @@ | |||
26 | #define _PAGE_WRITETHRU 0x040 /* W: cache write-through */ | 26 | #define _PAGE_WRITETHRU 0x040 /* W: cache write-through */ |
27 | #define _PAGE_DIRTY 0x080 /* C: page changed */ | 27 | #define _PAGE_DIRTY 0x080 /* C: page changed */ |
28 | #define _PAGE_ACCESSED 0x100 /* R: page referenced */ | 28 | #define _PAGE_ACCESSED 0x100 /* R: page referenced */ |
29 | #define _PAGE_EXEC 0x200 /* software: i-cache coherency required */ | ||
30 | #define _PAGE_RW 0x400 /* software: user write access allowed */ | 29 | #define _PAGE_RW 0x400 /* software: user write access allowed */ |
31 | #define _PAGE_SPECIAL 0x800 /* software: Special page */ | 30 | #define _PAGE_SPECIAL 0x800 /* software: Special page */ |
32 | 31 | ||
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 656cfb2d6666..711368b993f2 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S | |||
@@ -497,7 +497,7 @@ tlb_44x_patch_hwater_D: | |||
497 | mtspr SPRN_MMUCR,r12 | 497 | mtspr SPRN_MMUCR,r12 |
498 | 498 | ||
499 | /* Make up the required permissions */ | 499 | /* Make up the required permissions */ |
500 | li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_HWEXEC | 500 | li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC |
501 | 501 | ||
502 | /* Compute pgdir/pmd offset */ | 502 | /* Compute pgdir/pmd offset */ |
503 | rlwinm r12, r10, PPC44x_PGD_OFF_SHIFT, PPC44x_PGD_OFF_MASK_BIT, 29 | 503 | rlwinm r12, r10, PPC44x_PGD_OFF_SHIFT, PPC44x_PGD_OFF_MASK_BIT, 29 |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index eca80482ae72..2c5af5256479 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -643,7 +643,7 @@ interrupt_base: | |||
643 | 643 | ||
644 | 4: | 644 | 4: |
645 | /* Make up the required permissions */ | 645 | /* Make up the required permissions */ |
646 | li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_HWEXEC | 646 | li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC |
647 | 647 | ||
648 | FIND_PTE | 648 | FIND_PTE |
649 | andc. r13,r13,r11 /* Check permission */ | 649 | andc. r13,r13,r11 /* Check permission */ |
@@ -742,7 +742,7 @@ finish_tlb_load: | |||
742 | #endif | 742 | #endif |
743 | mtspr SPRN_MAS2, r12 | 743 | mtspr SPRN_MAS2, r12 |
744 | 744 | ||
745 | li r10, (_PAGE_HWEXEC | _PAGE_PRESENT) | 745 | li r10, (_PAGE_EXEC | _PAGE_PRESENT) |
746 | rlwimi r10, r11, 31, 29, 29 /* extract _PAGE_DIRTY into SW */ | 746 | rlwimi r10, r11, 31, 29, 29 /* extract _PAGE_DIRTY into SW */ |
747 | and r12, r11, r10 | 747 | and r12, r11, r10 |
748 | andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */ | 748 | andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */ |
diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c index 29954dc28942..f5e7b9ce63dd 100644 --- a/arch/powerpc/mm/40x_mmu.c +++ b/arch/powerpc/mm/40x_mmu.c | |||
@@ -105,7 +105,7 @@ unsigned long __init mmu_mapin_ram(void) | |||
105 | 105 | ||
106 | while (s >= LARGE_PAGE_SIZE_16M) { | 106 | while (s >= LARGE_PAGE_SIZE_16M) { |
107 | pmd_t *pmdp; | 107 | pmd_t *pmdp; |
108 | unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE; | 108 | unsigned long val = p | _PMD_SIZE_16M | _PAGE_EXEC | _PAGE_HWWRITE; |
109 | 109 | ||
110 | pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v); | 110 | pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v); |
111 | pmd_val(*pmdp++) = val; | 111 | pmd_val(*pmdp++) = val; |
@@ -120,7 +120,7 @@ unsigned long __init mmu_mapin_ram(void) | |||
120 | 120 | ||
121 | while (s >= LARGE_PAGE_SIZE_4M) { | 121 | while (s >= LARGE_PAGE_SIZE_4M) { |
122 | pmd_t *pmdp; | 122 | pmd_t *pmdp; |
123 | unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE; | 123 | unsigned long val = p | _PMD_SIZE_4M | _PAGE_EXEC | _PAGE_HWWRITE; |
124 | 124 | ||
125 | pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v); | 125 | pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v); |
126 | pmd_val(*pmdp) = val; | 126 | pmd_val(*pmdp) = val; |
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index b6b32487e740..83f1551ec2c9 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c | |||
@@ -128,28 +128,6 @@ void pte_free_finish(void) | |||
128 | 128 | ||
129 | #endif /* CONFIG_SMP */ | 129 | #endif /* CONFIG_SMP */ |
130 | 130 | ||
131 | /* | ||
132 | * Handle i/d cache flushing, called from set_pte_at() or ptep_set_access_flags() | ||
133 | */ | ||
134 | static pte_t do_dcache_icache_coherency(pte_t pte) | ||
135 | { | ||
136 | unsigned long pfn = pte_pfn(pte); | ||
137 | struct page *page; | ||
138 | |||
139 | if (unlikely(!pfn_valid(pfn))) | ||
140 | return pte; | ||
141 | page = pfn_to_page(pfn); | ||
142 | |||
143 | if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) { | ||
144 | pr_devel("do_dcache_icache_coherency... flushing\n"); | ||
145 | flush_dcache_icache_page(page); | ||
146 | set_bit(PG_arch_1, &page->flags); | ||
147 | } | ||
148 | else | ||
149 | pr_devel("do_dcache_icache_coherency... already clean\n"); | ||
150 | return __pte(pte_val(pte) | _PAGE_HWEXEC); | ||
151 | } | ||
152 | |||
153 | static inline int is_exec_fault(void) | 131 | static inline int is_exec_fault(void) |
154 | { | 132 | { |
155 | return current->thread.regs && TRAP(current->thread.regs) == 0x400; | 133 | return current->thread.regs && TRAP(current->thread.regs) == 0x400; |
@@ -157,49 +135,139 @@ static inline int is_exec_fault(void) | |||
157 | 135 | ||
158 | /* We only try to do i/d cache coherency on stuff that looks like | 136 | /* We only try to do i/d cache coherency on stuff that looks like |
159 | * reasonably "normal" PTEs. We currently require a PTE to be present | 137 | * reasonably "normal" PTEs. We currently require a PTE to be present |
160 | * and we avoid _PAGE_SPECIAL and _PAGE_NO_CACHE | 138 | * and we avoid _PAGE_SPECIAL and _PAGE_NO_CACHE. We also only do that |
139 | * on userspace PTEs | ||
161 | */ | 140 | */ |
162 | static inline int pte_looks_normal(pte_t pte) | 141 | static inline int pte_looks_normal(pte_t pte) |
163 | { | 142 | { |
164 | return (pte_val(pte) & | 143 | return (pte_val(pte) & |
165 | (_PAGE_PRESENT | _PAGE_SPECIAL | _PAGE_NO_CACHE)) == | 144 | (_PAGE_PRESENT | _PAGE_SPECIAL | _PAGE_NO_CACHE | _PAGE_USER)) == |
166 | (_PAGE_PRESENT); | 145 | (_PAGE_PRESENT | _PAGE_USER); |
167 | } | 146 | } |
168 | 147 | ||
169 | #if defined(CONFIG_PPC_STD_MMU) | 148 | struct page * maybe_pte_to_page(pte_t pte) |
149 | { | ||
150 | unsigned long pfn = pte_pfn(pte); | ||
151 | struct page *page; | ||
152 | |||
153 | if (unlikely(!pfn_valid(pfn))) | ||
154 | return NULL; | ||
155 | page = pfn_to_page(pfn); | ||
156 | if (PageReserved(page)) | ||
157 | return NULL; | ||
158 | return page; | ||
159 | } | ||
160 | |||
161 | #if defined(CONFIG_PPC_STD_MMU) || _PAGE_EXEC == 0 | ||
162 | |||
170 | /* Server-style MMU handles coherency when hashing if HW exec permission | 163 | /* Server-style MMU handles coherency when hashing if HW exec permission |
171 | * is supposed per page (currently 64-bit only). Else, we always flush | 164 | * is supposed per page (currently 64-bit only). If not, then, we always |
172 | * valid PTEs in set_pte. | 165 | * flush the cache for valid PTEs in set_pte. Embedded CPU without HW exec |
166 | * support falls into the same category. | ||
173 | */ | 167 | */ |
174 | static inline int pte_need_exec_flush(pte_t pte, int set_pte) | 168 | |
169 | static pte_t set_pte_filter(pte_t pte) | ||
175 | { | 170 | { |
176 | return set_pte && pte_looks_normal(pte) && | 171 | pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); |
177 | !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) || | 172 | if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) || |
178 | cpu_has_feature(CPU_FTR_NOEXECUTE)); | 173 | cpu_has_feature(CPU_FTR_NOEXECUTE))) { |
174 | struct page *pg = maybe_pte_to_page(pte); | ||
175 | if (!pg) | ||
176 | return pte; | ||
177 | if (!test_bit(PG_arch_1, &pg->flags)) { | ||
178 | flush_dcache_icache_page(pg); | ||
179 | set_bit(PG_arch_1, &pg->flags); | ||
180 | } | ||
181 | } | ||
182 | return pte; | ||
179 | } | 183 | } |
180 | #elif _PAGE_HWEXEC == 0 | 184 | |
181 | /* Embedded type MMU without HW exec support (8xx only so far), we flush | 185 | static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, |
182 | * the cache for any present PTE | 186 | int dirty) |
183 | */ | ||
184 | static inline int pte_need_exec_flush(pte_t pte, int set_pte) | ||
185 | { | 187 | { |
186 | return set_pte && pte_looks_normal(pte); | 188 | return pte; |
187 | } | 189 | } |
188 | #else | 190 | |
189 | /* Other embedded CPUs with HW exec support per-page, we flush on exec | 191 | #else /* defined(CONFIG_PPC_STD_MMU) || _PAGE_EXEC == 0 */ |
190 | * fault if HWEXEC is not set | 192 | |
193 | /* Embedded type MMU with HW exec support. This is a bit more complicated | ||
194 | * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so | ||
195 | * instead we "filter out" the exec permission for non clean pages. | ||
191 | */ | 196 | */ |
192 | static inline int pte_need_exec_flush(pte_t pte, int set_pte) | 197 | static pte_t set_pte_filter(pte_t pte) |
193 | { | 198 | { |
194 | return pte_looks_normal(pte) && is_exec_fault() && | 199 | struct page *pg; |
195 | !(pte_val(pte) & _PAGE_HWEXEC); | 200 | |
201 | /* No exec permission in the first place, move on */ | ||
202 | if (!(pte_val(pte) & _PAGE_EXEC) || !pte_looks_normal(pte)) | ||
203 | return pte; | ||
204 | |||
205 | /* If you set _PAGE_EXEC on weird pages you're on your own */ | ||
206 | pg = maybe_pte_to_page(pte); | ||
207 | if (unlikely(!pg)) | ||
208 | return pte; | ||
209 | |||
210 | /* If the page clean, we move on */ | ||
211 | if (test_bit(PG_arch_1, &pg->flags)) | ||
212 | return pte; | ||
213 | |||
214 | /* If it's an exec fault, we flush the cache and make it clean */ | ||
215 | if (is_exec_fault()) { | ||
216 | flush_dcache_icache_page(pg); | ||
217 | set_bit(PG_arch_1, &pg->flags); | ||
218 | return pte; | ||
219 | } | ||
220 | |||
221 | /* Else, we filter out _PAGE_EXEC */ | ||
222 | return __pte(pte_val(pte) & ~_PAGE_EXEC); | ||
196 | } | 223 | } |
197 | #endif | 224 | |
225 | static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, | ||
226 | int dirty) | ||
227 | { | ||
228 | struct page *pg; | ||
229 | |||
230 | /* So here, we only care about exec faults, as we use them | ||
231 | * to recover lost _PAGE_EXEC and perform I$/D$ coherency | ||
232 | * if necessary. Also if _PAGE_EXEC is already set, same deal, | ||
233 | * we just bail out | ||
234 | */ | ||
235 | if (dirty || (pte_val(pte) & _PAGE_EXEC) || !is_exec_fault()) | ||
236 | return pte; | ||
237 | |||
238 | #ifdef CONFIG_DEBUG_VM | ||
239 | /* So this is an exec fault, _PAGE_EXEC is not set. If it was | ||
240 | * an error we would have bailed out earlier in do_page_fault() | ||
241 | * but let's make sure of it | ||
242 | */ | ||
243 | if (WARN_ON(!(vma->vm_flags & VM_EXEC))) | ||
244 | return pte; | ||
245 | #endif /* CONFIG_DEBUG_VM */ | ||
246 | |||
247 | /* If you set _PAGE_EXEC on weird pages you're on your own */ | ||
248 | pg = maybe_pte_to_page(pte); | ||
249 | if (unlikely(!pg)) | ||
250 | goto bail; | ||
251 | |||
252 | /* If the page is already clean, we move on */ | ||
253 | if (test_bit(PG_arch_1, &pg->flags)) | ||
254 | goto bail; | ||
255 | |||
256 | /* Clean the page and set PG_arch_1 */ | ||
257 | flush_dcache_icache_page(pg); | ||
258 | set_bit(PG_arch_1, &pg->flags); | ||
259 | |||
260 | bail: | ||
261 | return __pte(pte_val(pte) | _PAGE_EXEC); | ||
262 | } | ||
263 | |||
264 | #endif /* !(defined(CONFIG_PPC_STD_MMU) || _PAGE_EXEC == 0) */ | ||
198 | 265 | ||
199 | /* | 266 | /* |
200 | * set_pte stores a linux PTE into the linux page table. | 267 | * set_pte stores a linux PTE into the linux page table. |
201 | */ | 268 | */ |
202 | void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) | 269 | void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, |
270 | pte_t pte) | ||
203 | { | 271 | { |
204 | #ifdef CONFIG_DEBUG_VM | 272 | #ifdef CONFIG_DEBUG_VM |
205 | WARN_ON(pte_present(*ptep)); | 273 | WARN_ON(pte_present(*ptep)); |
@@ -208,9 +276,7 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte | |||
208 | * this context might not have been activated yet when this | 276 | * this context might not have been activated yet when this |
209 | * is called. | 277 | * is called. |
210 | */ | 278 | */ |
211 | pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); | 279 | pte = set_pte_filter(pte); |
212 | if (pte_need_exec_flush(pte, 1)) | ||
213 | pte = do_dcache_icache_coherency(pte); | ||
214 | 280 | ||
215 | /* Perform the setting of the PTE */ | 281 | /* Perform the setting of the PTE */ |
216 | __set_pte_at(mm, addr, ptep, pte, 0); | 282 | __set_pte_at(mm, addr, ptep, pte, 0); |
@@ -227,8 +293,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, | |||
227 | pte_t *ptep, pte_t entry, int dirty) | 293 | pte_t *ptep, pte_t entry, int dirty) |
228 | { | 294 | { |
229 | int changed; | 295 | int changed; |
230 | if (!dirty && pte_need_exec_flush(entry, 0)) | 296 | entry = set_access_flags_filter(entry, vma, dirty); |
231 | entry = do_dcache_icache_coherency(entry); | ||
232 | changed = !pte_same(*(ptep), entry); | 297 | changed = !pte_same(*(ptep), entry); |
233 | if (changed) { | 298 | if (changed) { |
234 | if (!(vma->vm_flags & VM_HUGETLB)) | 299 | if (!(vma->vm_flags & VM_HUGETLB)) |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 5422169626ba..cb96cb2e17cc 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -142,7 +142,7 @@ ioremap_flags(phys_addr_t addr, unsigned long size, unsigned long flags) | |||
142 | flags |= _PAGE_DIRTY | _PAGE_HWWRITE; | 142 | flags |= _PAGE_DIRTY | _PAGE_HWWRITE; |
143 | 143 | ||
144 | /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */ | 144 | /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */ |
145 | flags &= ~(_PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC); | 145 | flags &= ~(_PAGE_USER | _PAGE_EXEC); |
146 | 146 | ||
147 | return __ioremap_caller(addr, size, flags, __builtin_return_address(0)); | 147 | return __ioremap_caller(addr, size, flags, __builtin_return_address(0)); |
148 | } | 148 | } |
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S index 10d524ded7b2..cd92f62f9cf5 100644 --- a/arch/powerpc/mm/tlb_low_64e.S +++ b/arch/powerpc/mm/tlb_low_64e.S | |||
@@ -133,7 +133,7 @@ | |||
133 | 133 | ||
134 | /* We do the user/kernel test for the PID here along with the RW test | 134 | /* We do the user/kernel test for the PID here along with the RW test |
135 | */ | 135 | */ |
136 | li r11,_PAGE_PRESENT|_PAGE_HWEXEC /* Base perm */ | 136 | li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */ |
137 | oris r11,r11,_PAGE_ACCESSED@h | 137 | oris r11,r11,_PAGE_ACCESSED@h |
138 | 138 | ||
139 | cmpldi cr0,r15,0 /* Check for user region */ | 139 | cmpldi cr0,r15,0 /* Check for user region */ |
@@ -256,7 +256,7 @@ normal_tlb_miss_done: | |||
256 | 256 | ||
257 | normal_tlb_miss_access_fault: | 257 | normal_tlb_miss_access_fault: |
258 | /* We need to check if it was an instruction miss */ | 258 | /* We need to check if it was an instruction miss */ |
259 | andi. r10,r11,_PAGE_HWEXEC | 259 | andi. r10,r11,_PAGE_EXEC |
260 | bne 1f | 260 | bne 1f |
261 | ld r14,EX_TLB_DEAR(r12) | 261 | ld r14,EX_TLB_DEAR(r12) |
262 | ld r15,EX_TLB_ESR(r12) | 262 | ld r15,EX_TLB_ESR(r12) |