aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-11-16 03:40:36 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-12-22 06:05:35 -0500
commit36bb94ba36f332de767cfaa3af6a5136435a3a9c (patch)
tree45d1bd890b58658f4db58a033e619e511e3368f4
parent9522d7e4cb5e0858122fc55d33a2c07728f0b10d (diff)
ARM: pgtable: provide RDONLY page table bit rather than WRITE bit
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/include/asm/pgtable.h38
-rw-r--r--arch/arm/mm/mmu.c19
-rw-r--r--arch/arm/mm/proc-macros.S16
-rw-r--r--arch/arm/mm/proc-v7.S6
-rw-r--r--arch/arm/mm/proc-xscale.S4
5 files changed, 41 insertions, 42 deletions
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index f9b3f4bd7410..ebcb6432f45f 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -169,7 +169,7 @@ extern void __pgd_error(const char *file, int line, pgd_t);
169#define L_PTE_YOUNG (_AT(pteval_t, 1) << 1) 169#define L_PTE_YOUNG (_AT(pteval_t, 1) << 1)
170#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ 170#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */
171#define L_PTE_DIRTY (_AT(pteval_t, 1) << 6) 171#define L_PTE_DIRTY (_AT(pteval_t, 1) << 6)
172#define L_PTE_WRITE (_AT(pteval_t, 1) << 7) 172#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7)
173#define L_PTE_USER (_AT(pteval_t, 1) << 8) 173#define L_PTE_USER (_AT(pteval_t, 1) << 8)
174#define L_PTE_XN (_AT(pteval_t, 1) << 9) 174#define L_PTE_XN (_AT(pteval_t, 1) << 9)
175#define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */ 175#define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */
@@ -205,23 +205,23 @@ extern pgprot_t pgprot_kernel;
205 205
206#define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) 206#define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b))
207 207
208#define PAGE_NONE _MOD_PROT(pgprot_user, L_PTE_XN) 208#define PAGE_NONE _MOD_PROT(pgprot_user, L_PTE_XN | L_PTE_RDONLY)
209#define PAGE_SHARED _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_WRITE | L_PTE_XN) 209#define PAGE_SHARED _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_XN)
210#define PAGE_SHARED_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_WRITE) 210#define PAGE_SHARED_EXEC _MOD_PROT(pgprot_user, L_PTE_USER)
211#define PAGE_COPY _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_XN) 211#define PAGE_COPY _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
212#define PAGE_COPY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER) 212#define PAGE_COPY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY)
213#define PAGE_READONLY _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_XN) 213#define PAGE_READONLY _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
214#define PAGE_READONLY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER) 214#define PAGE_READONLY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY)
215#define PAGE_KERNEL _MOD_PROT(pgprot_kernel, L_PTE_XN) 215#define PAGE_KERNEL _MOD_PROT(pgprot_kernel, L_PTE_XN)
216#define PAGE_KERNEL_EXEC pgprot_kernel 216#define PAGE_KERNEL_EXEC pgprot_kernel
217 217
218#define __PAGE_NONE __pgprot(_L_PTE_DEFAULT | L_PTE_XN) 218#define __PAGE_NONE __pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN)
219#define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_WRITE | L_PTE_XN) 219#define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN)
220#define __PAGE_SHARED_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_WRITE) 220#define __PAGE_SHARED_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER)
221#define __PAGE_COPY __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN) 221#define __PAGE_COPY __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
222#define __PAGE_COPY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER) 222#define __PAGE_COPY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY)
223#define __PAGE_READONLY __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN) 223#define __PAGE_READONLY __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
224#define __PAGE_READONLY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER) 224#define __PAGE_READONLY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY)
225 225
226#define __pgprot_modify(prot,mask,bits) \ 226#define __pgprot_modify(prot,mask,bits) \
227 __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) 227 __pgprot((pgprot_val(prot) & ~(mask)) | (bits))
@@ -380,7 +380,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
380 380
381#define pte_none(pte) (!pte_val(pte)) 381#define pte_none(pte) (!pte_val(pte))
382#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) 382#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
383#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE) 383#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY))
384#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) 384#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
385#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) 385#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
386#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) 386#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN))
@@ -393,8 +393,8 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
393#define PTE_BIT_FUNC(fn,op) \ 393#define PTE_BIT_FUNC(fn,op) \
394static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } 394static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
395 395
396PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE); 396PTE_BIT_FUNC(wrprotect, |= L_PTE_RDONLY);
397PTE_BIT_FUNC(mkwrite, |= L_PTE_WRITE); 397PTE_BIT_FUNC(mkwrite, &= ~L_PTE_RDONLY);
398PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); 398PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY);
399PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); 399PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY);
400PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); 400PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG);
@@ -404,7 +404,7 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
404 404
405static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 405static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
406{ 406{
407 const pteval_t mask = L_PTE_XN | L_PTE_WRITE | L_PTE_USER; 407 const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER;
408 pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); 408 pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
409 return pte; 409 return pte;
410} 410}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index bd5a94b2d610..546e44734db0 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -190,7 +190,7 @@ void adjust_cr(unsigned long mask, unsigned long set)
190} 190}
191#endif 191#endif
192 192
193#define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_WRITE|L_PTE_XN 193#define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
194#define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE 194#define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE
195 195
196static struct mem_type mem_types[] = { 196static struct mem_type mem_types[] = {
@@ -234,19 +234,19 @@ static struct mem_type mem_types[] = {
234 .domain = DOMAIN_KERNEL, 234 .domain = DOMAIN_KERNEL,
235 }, 235 },
236 [MT_LOW_VECTORS] = { 236 [MT_LOW_VECTORS] = {
237 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY, 237 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
238 L_PTE_RDONLY,
238 .prot_l1 = PMD_TYPE_TABLE, 239 .prot_l1 = PMD_TYPE_TABLE,
239 .domain = DOMAIN_USER, 240 .domain = DOMAIN_USER,
240 }, 241 },
241 [MT_HIGH_VECTORS] = { 242 [MT_HIGH_VECTORS] = {
242 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 243 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
243 L_PTE_USER, 244 L_PTE_USER | L_PTE_RDONLY,
244 .prot_l1 = PMD_TYPE_TABLE, 245 .prot_l1 = PMD_TYPE_TABLE,
245 .domain = DOMAIN_USER, 246 .domain = DOMAIN_USER,
246 }, 247 },
247 [MT_MEMORY] = { 248 [MT_MEMORY] = {
248 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 249 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
249 L_PTE_WRITE,
250 .prot_l1 = PMD_TYPE_TABLE, 250 .prot_l1 = PMD_TYPE_TABLE,
251 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, 251 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
252 .domain = DOMAIN_KERNEL, 252 .domain = DOMAIN_KERNEL,
@@ -257,21 +257,20 @@ static struct mem_type mem_types[] = {
257 }, 257 },
258 [MT_MEMORY_NONCACHED] = { 258 [MT_MEMORY_NONCACHED] = {
259 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 259 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
260 L_PTE_WRITE| L_PTE_MT_BUFFERABLE, 260 L_PTE_MT_BUFFERABLE,
261 .prot_l1 = PMD_TYPE_TABLE, 261 .prot_l1 = PMD_TYPE_TABLE,
262 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, 262 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
263 .domain = DOMAIN_KERNEL, 263 .domain = DOMAIN_KERNEL,
264 }, 264 },
265 [MT_MEMORY_DTCM] = { 265 [MT_MEMORY_DTCM] = {
266 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 266 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
267 L_PTE_WRITE | L_PTE_XN, 267 L_PTE_XN,
268 .prot_l1 = PMD_TYPE_TABLE, 268 .prot_l1 = PMD_TYPE_TABLE,
269 .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, 269 .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
270 .domain = DOMAIN_KERNEL, 270 .domain = DOMAIN_KERNEL,
271 }, 271 },
272 [MT_MEMORY_ITCM] = { 272 [MT_MEMORY_ITCM] = {
273 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 273 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
274 L_PTE_WRITE,
275 .prot_l1 = PMD_TYPE_TABLE, 274 .prot_l1 = PMD_TYPE_TABLE,
276 .domain = DOMAIN_KERNEL, 275 .domain = DOMAIN_KERNEL,
277 }, 276 },
@@ -478,7 +477,7 @@ static void __init build_mem_type_table(void)
478 477
479 pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot); 478 pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
480 pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | 479 pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
481 L_PTE_DIRTY | L_PTE_WRITE | kern_pgprot); 480 L_PTE_DIRTY | kern_pgprot);
482 481
483 mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; 482 mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
484 mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; 483 mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index 4a7a9e142e85..f5ca6aaecdbd 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -81,7 +81,7 @@
81#if L_PTE_SHARED != PTE_EXT_SHARED 81#if L_PTE_SHARED != PTE_EXT_SHARED
82#error PTE shared bit mismatch 82#error PTE shared bit mismatch
83#endif 83#endif
84#if (L_PTE_XN+L_PTE_USER+L_PTE_WRITE+L_PTE_DIRTY+L_PTE_YOUNG+\ 84#if (L_PTE_XN+L_PTE_USER+L_PTE_RDONLY+L_PTE_DIRTY+L_PTE_YOUNG+\
85 L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED 85 L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED
86#error Invalid Linux PTE bit settings 86#error Invalid Linux PTE bit settings
87#endif 87#endif
@@ -132,9 +132,9 @@
132 and r2, r1, #L_PTE_MT_MASK 132 and r2, r1, #L_PTE_MT_MASK
133 ldr r2, [ip, r2] 133 ldr r2, [ip, r2]
134 134
135 tst r1, #L_PTE_WRITE 135 eor r1, r1, #L_PTE_DIRTY
136 tstne r1, #L_PTE_DIRTY 136 tst r1, #L_PTE_DIRTY|L_PTE_RDONLY
137 orreq r3, r3, #PTE_EXT_APX 137 orrne r3, r3, #PTE_EXT_APX
138 138
139 tst r1, #L_PTE_USER 139 tst r1, #L_PTE_USER
140 orrne r3, r3, #PTE_EXT_AP1 140 orrne r3, r3, #PTE_EXT_AP1
@@ -172,7 +172,7 @@
172 .macro armv3_set_pte_ext wc_disable=1 172 .macro armv3_set_pte_ext wc_disable=1
173 str r1, [r0], #2048 @ linux version 173 str r1, [r0], #2048 @ linux version
174 174
175 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY 175 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY
176 176
177 bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits 177 bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits
178 bic r2, r2, #PTE_TYPE_MASK 178 bic r2, r2, #PTE_TYPE_MASK
@@ -181,7 +181,7 @@
181 tst r3, #L_PTE_USER @ user? 181 tst r3, #L_PTE_USER @ user?
182 orrne r2, r2, #PTE_SMALL_AP_URO_SRW 182 orrne r2, r2, #PTE_SMALL_AP_URO_SRW
183 183
184 tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty? 184 tst r3, #L_PTE_RDONLY | L_PTE_DIRTY @ write and dirty?
185 orreq r2, r2, #PTE_SMALL_AP_UNO_SRW 185 orreq r2, r2, #PTE_SMALL_AP_UNO_SRW
186 186
187 tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? 187 tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young?
@@ -215,7 +215,7 @@
215 .macro xscale_set_pte_ext_prologue 215 .macro xscale_set_pte_ext_prologue
216 str r1, [r0] @ linux version 216 str r1, [r0] @ linux version
217 217
218 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY 218 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY
219 219
220 bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits 220 bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits
221 orr r2, r2, #PTE_TYPE_EXT @ extended page 221 orr r2, r2, #PTE_TYPE_EXT @ extended page
@@ -223,7 +223,7 @@
223 tst r3, #L_PTE_USER @ user? 223 tst r3, #L_PTE_USER @ user?
224 orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w 224 orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w
225 225
226 tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty? 226 tst r3, #L_PTE_RDONLY | L_PTE_DIRTY @ write and dirty?
227 orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w 227 orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w
228 @ combined with user -> user r/w 228 @ combined with user -> user r/w
229 .endm 229 .endm
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 4f5a594aa5fd..210d051c54d7 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -140,9 +140,9 @@ ENTRY(cpu_v7_set_pte_ext)
140 tst r1, #1 << 4 140 tst r1, #1 << 4
141 orrne r3, r3, #PTE_EXT_TEX(1) 141 orrne r3, r3, #PTE_EXT_TEX(1)
142 142
143 tst r1, #L_PTE_WRITE 143 eor r1, r1, #L_PTE_DIRTY
144 tstne r1, #L_PTE_DIRTY 144 tst r1, #L_PTE_RDONLY | L_PTE_DIRTY
145 orreq r3, r3, #PTE_EXT_APX 145 orrne r3, r3, #PTE_EXT_APX
146 146
147 tst r1, #L_PTE_USER 147 tst r1, #L_PTE_USER
148 orrne r3, r3, #PTE_EXT_AP1 148 orrne r3, r3, #PTE_EXT_AP1
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 523408c0bb38..5a37c5e45c41 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -500,8 +500,8 @@ ENTRY(cpu_xscale_set_pte_ext)
500 @ 500 @
501 @ Erratum 40: must set memory to write-through for user read-only pages 501 @ Erratum 40: must set memory to write-through for user read-only pages
502 @ 502 @
503 and ip, r1, #(L_PTE_MT_MASK | L_PTE_USER | L_PTE_WRITE) & ~(4 << 2) 503 and ip, r1, #(L_PTE_MT_MASK | L_PTE_USER | L_PTE_RDONLY) & ~(4 << 2)
504 teq ip, #L_PTE_MT_WRITEBACK | L_PTE_USER 504 teq ip, #L_PTE_MT_WRITEBACK | L_PTE_USER | L_PTE_RDONLY
505 505
506 moveq r1, #L_PTE_MT_WRITETHROUGH 506 moveq r1, #L_PTE_MT_WRITETHROUGH
507 and r1, r1, #L_PTE_MT_MASK 507 and r1, r1, #L_PTE_MT_MASK