diff options
Diffstat (limited to 'include/asm-powerpc')
-rw-r--r-- | include/asm-powerpc/pgtable-ppc32.h | 61 |
1 files changed, 46 insertions, 15 deletions
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h index e1d2bb57f1d5..11eede4a2906 100644 --- a/include/asm-powerpc/pgtable-ppc32.h +++ b/include/asm-powerpc/pgtable-ppc32.h | |||
@@ -182,6 +182,9 @@ extern int icache_44x_need_flush; | |||
182 | #define _PMD_SIZE_16M 0x0e0 | 182 | #define _PMD_SIZE_16M 0x0e0 |
183 | #define PMD_PAGE_SIZE(pmdval) (1024 << (((pmdval) & _PMD_SIZE) >> 4)) | 183 | #define PMD_PAGE_SIZE(pmdval) (1024 << (((pmdval) & _PMD_SIZE) >> 4)) |
184 | 184 | ||
185 | /* Until my rework is finished, 40x still needs atomic PTE updates */ | ||
186 | #define PTE_ATOMIC_UPDATES 1 | ||
187 | |||
185 | #elif defined(CONFIG_44x) | 188 | #elif defined(CONFIG_44x) |
186 | /* | 189 | /* |
187 | * Definitions for PPC440 | 190 | * Definitions for PPC440 |
@@ -253,17 +256,17 @@ extern int icache_44x_need_flush; | |||
253 | */ | 256 | */ |
254 | 257 | ||
255 | #define _PAGE_PRESENT 0x00000001 /* S: PTE valid */ | 258 | #define _PAGE_PRESENT 0x00000001 /* S: PTE valid */ |
256 | #define _PAGE_RW 0x00000002 /* S: Write permission */ | 259 | #define _PAGE_RW 0x00000002 /* S: Write permission */ |
257 | #define _PAGE_FILE 0x00000004 /* S: nonlinear file mapping */ | 260 | #define _PAGE_FILE 0x00000004 /* S: nonlinear file mapping */ |
261 | #define _PAGE_HWEXEC 0x00000004 /* H: Execute permission */ | ||
258 | #define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */ | 262 | #define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */ |
259 | #define _PAGE_HWWRITE 0x00000010 /* H: Dirty & RW */ | 263 | #define _PAGE_DIRTY 0x00000010 /* S: Page dirty */ |
260 | #define _PAGE_HWEXEC 0x00000020 /* H: Execute permission */ | 264 | #define _PAGE_USER 0x00000040 /* S: User page */ |
261 | #define _PAGE_USER 0x00000040 /* S: User page */ | 265 | #define _PAGE_ENDIAN 0x00000080 /* H: E bit */ |
262 | #define _PAGE_ENDIAN 0x00000080 /* H: E bit */ | 266 | #define _PAGE_GUARDED 0x00000100 /* H: G bit */ |
263 | #define _PAGE_GUARDED 0x00000100 /* H: G bit */ | 267 | #define _PAGE_COHERENT 0x00000200 /* H: M bit */ |
264 | #define _PAGE_DIRTY 0x00000200 /* S: Page dirty */ | 268 | #define _PAGE_NO_CACHE 0x00000400 /* H: I bit */ |
265 | #define _PAGE_NO_CACHE 0x00000400 /* H: I bit */ | 269 | #define _PAGE_WRITETHRU 0x00000800 /* H: W bit */ |
266 | #define _PAGE_WRITETHRU 0x00000800 /* H: W bit */ | ||
267 | 270 | ||
268 | /* TODO: Add large page lowmem mapping support */ | 271 | /* TODO: Add large page lowmem mapping support */ |
269 | #define _PMD_PRESENT 0 | 272 | #define _PMD_PRESENT 0 |
@@ -273,6 +276,7 @@ extern int icache_44x_need_flush; | |||
273 | /* ERPN in a PTE never gets cleared, ignore it */ | 276 | /* ERPN in a PTE never gets cleared, ignore it */ |
274 | #define _PTE_NONE_MASK 0xffffffff00000000ULL | 277 | #define _PTE_NONE_MASK 0xffffffff00000000ULL |
275 | 278 | ||
279 | |||
276 | #elif defined(CONFIG_FSL_BOOKE) | 280 | #elif defined(CONFIG_FSL_BOOKE) |
277 | /* | 281 | /* |
278 | MMU Assist Register 3: | 282 | MMU Assist Register 3: |
@@ -315,6 +319,9 @@ extern int icache_44x_need_flush; | |||
315 | #define _PMD_PRESENT_MASK (PAGE_MASK) | 319 | #define _PMD_PRESENT_MASK (PAGE_MASK) |
316 | #define _PMD_BAD (~PAGE_MASK) | 320 | #define _PMD_BAD (~PAGE_MASK) |
317 | 321 | ||
322 | /* Until my rework is finished, FSL BookE still needs atomic PTE updates */ | ||
323 | #define PTE_ATOMIC_UPDATES 1 | ||
324 | |||
318 | #elif defined(CONFIG_8xx) | 325 | #elif defined(CONFIG_8xx) |
319 | /* Definitions for 8xx embedded chips. */ | 326 | /* Definitions for 8xx embedded chips. */ |
320 | #define _PAGE_PRESENT 0x0001 /* Page is valid */ | 327 | #define _PAGE_PRESENT 0x0001 /* Page is valid */ |
@@ -345,6 +352,9 @@ extern int icache_44x_need_flush; | |||
345 | 352 | ||
346 | #define _PTE_NONE_MASK _PAGE_ACCESSED | 353 | #define _PTE_NONE_MASK _PAGE_ACCESSED |
347 | 354 | ||
355 | /* Until my rework is finished, 8xx still needs atomic PTE updates */ | ||
356 | #define PTE_ATOMIC_UPDATES 1 | ||
357 | |||
348 | #else /* CONFIG_6xx */ | 358 | #else /* CONFIG_6xx */ |
349 | /* Definitions for 60x, 740/750, etc. */ | 359 | /* Definitions for 60x, 740/750, etc. */ |
350 | #define _PAGE_PRESENT 0x001 /* software: pte contains a translation */ | 360 | #define _PAGE_PRESENT 0x001 /* software: pte contains a translation */ |
@@ -365,6 +375,10 @@ extern int icache_44x_need_flush; | |||
365 | #define _PMD_PRESENT 0 | 375 | #define _PMD_PRESENT 0 |
366 | #define _PMD_PRESENT_MASK (PAGE_MASK) | 376 | #define _PMD_PRESENT_MASK (PAGE_MASK) |
367 | #define _PMD_BAD (~PAGE_MASK) | 377 | #define _PMD_BAD (~PAGE_MASK) |
378 | |||
379 | /* Hash table based platforms need atomic updates of the linux PTE */ | ||
380 | #define PTE_ATOMIC_UPDATES 1 | ||
381 | |||
368 | #endif | 382 | #endif |
369 | 383 | ||
370 | /* | 384 | /* |
@@ -557,9 +571,11 @@ extern void add_hash_page(unsigned context, unsigned long va, | |||
557 | * low PTE word since we expect ALL flag bits to be there | 571 | * low PTE word since we expect ALL flag bits to be there |
558 | */ | 572 | */ |
559 | #ifndef CONFIG_PTE_64BIT | 573 | #ifndef CONFIG_PTE_64BIT |
560 | static inline unsigned long pte_update(pte_t *p, unsigned long clr, | 574 | static inline unsigned long pte_update(pte_t *p, |
575 | unsigned long clr, | ||
561 | unsigned long set) | 576 | unsigned long set) |
562 | { | 577 | { |
578 | #ifdef PTE_ATOMIC_UPDATES | ||
563 | unsigned long old, tmp; | 579 | unsigned long old, tmp; |
564 | 580 | ||
565 | __asm__ __volatile__("\ | 581 | __asm__ __volatile__("\ |
@@ -572,16 +588,26 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr, | |||
572 | : "=&r" (old), "=&r" (tmp), "=m" (*p) | 588 | : "=&r" (old), "=&r" (tmp), "=m" (*p) |
573 | : "r" (p), "r" (clr), "r" (set), "m" (*p) | 589 | : "r" (p), "r" (clr), "r" (set), "m" (*p) |
574 | : "cc" ); | 590 | : "cc" ); |
591 | #else /* PTE_ATOMIC_UPDATES */ | ||
592 | unsigned long old = pte_val(*p); | ||
593 | *p = __pte((old & ~clr) | set); | ||
594 | #endif /* !PTE_ATOMIC_UPDATES */ | ||
595 | |||
575 | #ifdef CONFIG_44x | 596 | #ifdef CONFIG_44x |
576 | if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC)) | 597 | if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC)) |
577 | icache_44x_need_flush = 1; | 598 | icache_44x_need_flush = 1; |
578 | #endif | 599 | #endif |
579 | return old; | 600 | return old; |
580 | } | 601 | } |
581 | #else | 602 | #else /* CONFIG_PTE_64BIT */ |
582 | static inline unsigned long long pte_update(pte_t *p, unsigned long clr, | 603 | /* TODO: Change that to only modify the low word and move set_pte_at() |
583 | unsigned long set) | 604 | * out of line |
605 | */ | ||
606 | static inline unsigned long long pte_update(pte_t *p, | ||
607 | unsigned long clr, | ||
608 | unsigned long set) | ||
584 | { | 609 | { |
610 | #ifdef PTE_ATOMIC_UPDATES | ||
585 | unsigned long long old; | 611 | unsigned long long old; |
586 | unsigned long tmp; | 612 | unsigned long tmp; |
587 | 613 | ||
@@ -596,13 +622,18 @@ static inline unsigned long long pte_update(pte_t *p, unsigned long clr, | |||
596 | : "=&r" (old), "=&r" (tmp), "=m" (*p) | 622 | : "=&r" (old), "=&r" (tmp), "=m" (*p) |
597 | : "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set), "m" (*p) | 623 | : "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set), "m" (*p) |
598 | : "cc" ); | 624 | : "cc" ); |
625 | #else /* PTE_ATOMIC_UPDATES */ | ||
626 | unsigned long long old = pte_val(*p); | ||
627 | *p = __pte((old & ~clr) | set); | ||
628 | #endif /* !PTE_ATOMIC_UPDATES */ | ||
629 | |||
599 | #ifdef CONFIG_44x | 630 | #ifdef CONFIG_44x |
600 | if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC)) | 631 | if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC)) |
601 | icache_44x_need_flush = 1; | 632 | icache_44x_need_flush = 1; |
602 | #endif | 633 | #endif |
603 | return old; | 634 | return old; |
604 | } | 635 | } |
605 | #endif | 636 | #endif /* CONFIG_PTE_64BIT */ |
606 | 637 | ||
607 | /* | 638 | /* |
608 | * set_pte stores a linux PTE into the linux page table. | 639 | * set_pte stores a linux PTE into the linux page table. |
@@ -671,7 +702,7 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty) | |||
671 | ({ \ | 702 | ({ \ |
672 | int __changed = !pte_same(*(__ptep), __entry); \ | 703 | int __changed = !pte_same(*(__ptep), __entry); \ |
673 | if (__changed) { \ | 704 | if (__changed) { \ |
674 | __ptep_set_access_flags(__ptep, __entry, __dirty); \ | 705 | __ptep_set_access_flags(__ptep, __entry, __dirty); \ |
675 | flush_tlb_page_nohash(__vma, __address); \ | 706 | flush_tlb_page_nohash(__vma, __address); \ |
676 | } \ | 707 | } \ |
677 | __changed; \ | 708 | __changed; \ |