diff options
Diffstat (limited to 'arch/powerpc/include/asm/pgtable-ppc32.h')
-rw-r--r-- | arch/powerpc/include/asm/pgtable-ppc32.h | 72 |
1 files changed, 56 insertions, 16 deletions
diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h index 6fe39e327047..6ab7c67cb5ab 100644 --- a/arch/powerpc/include/asm/pgtable-ppc32.h +++ b/arch/powerpc/include/asm/pgtable-ppc32.h | |||
@@ -261,6 +261,7 @@ extern int icache_44x_need_flush; | |||
261 | #define _PAGE_HWEXEC 0x00000004 /* H: Execute permission */ | 261 | #define _PAGE_HWEXEC 0x00000004 /* H: Execute permission */ |
262 | #define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */ | 262 | #define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */ |
263 | #define _PAGE_DIRTY 0x00000010 /* S: Page dirty */ | 263 | #define _PAGE_DIRTY 0x00000010 /* S: Page dirty */ |
264 | #define _PAGE_SPECIAL 0x00000020 /* S: Special page */ | ||
264 | #define _PAGE_USER 0x00000040 /* S: User page */ | 265 | #define _PAGE_USER 0x00000040 /* S: User page */ |
265 | #define _PAGE_ENDIAN 0x00000080 /* H: E bit */ | 266 | #define _PAGE_ENDIAN 0x00000080 /* H: E bit */ |
266 | #define _PAGE_GUARDED 0x00000100 /* H: G bit */ | 267 | #define _PAGE_GUARDED 0x00000100 /* H: G bit */ |
@@ -276,6 +277,7 @@ extern int icache_44x_need_flush; | |||
276 | /* ERPN in a PTE never gets cleared, ignore it */ | 277 | /* ERPN in a PTE never gets cleared, ignore it */ |
277 | #define _PTE_NONE_MASK 0xffffffff00000000ULL | 278 | #define _PTE_NONE_MASK 0xffffffff00000000ULL |
278 | 279 | ||
280 | #define __HAVE_ARCH_PTE_SPECIAL | ||
279 | 281 | ||
280 | #elif defined(CONFIG_FSL_BOOKE) | 282 | #elif defined(CONFIG_FSL_BOOKE) |
281 | /* | 283 | /* |
@@ -305,6 +307,7 @@ extern int icache_44x_need_flush; | |||
305 | #define _PAGE_COHERENT 0x00100 /* H: M bit */ | 307 | #define _PAGE_COHERENT 0x00100 /* H: M bit */ |
306 | #define _PAGE_NO_CACHE 0x00200 /* H: I bit */ | 308 | #define _PAGE_NO_CACHE 0x00200 /* H: I bit */ |
307 | #define _PAGE_WRITETHRU 0x00400 /* H: W bit */ | 309 | #define _PAGE_WRITETHRU 0x00400 /* H: W bit */ |
310 | #define _PAGE_SPECIAL 0x00800 /* S: Special page */ | ||
308 | 311 | ||
309 | #ifdef CONFIG_PTE_64BIT | 312 | #ifdef CONFIG_PTE_64BIT |
310 | /* ERPN in a PTE never gets cleared, ignore it */ | 313 | /* ERPN in a PTE never gets cleared, ignore it */ |
@@ -315,6 +318,8 @@ extern int icache_44x_need_flush; | |||
315 | #define _PMD_PRESENT_MASK (PAGE_MASK) | 318 | #define _PMD_PRESENT_MASK (PAGE_MASK) |
316 | #define _PMD_BAD (~PAGE_MASK) | 319 | #define _PMD_BAD (~PAGE_MASK) |
317 | 320 | ||
321 | #define __HAVE_ARCH_PTE_SPECIAL | ||
322 | |||
318 | #elif defined(CONFIG_8xx) | 323 | #elif defined(CONFIG_8xx) |
319 | /* Definitions for 8xx embedded chips. */ | 324 | /* Definitions for 8xx embedded chips. */ |
320 | #define _PAGE_PRESENT 0x0001 /* Page is valid */ | 325 | #define _PAGE_PRESENT 0x0001 /* Page is valid */ |
@@ -362,8 +367,14 @@ extern int icache_44x_need_flush; | |||
362 | #define _PAGE_ACCESSED 0x100 /* R: page referenced */ | 367 | #define _PAGE_ACCESSED 0x100 /* R: page referenced */ |
363 | #define _PAGE_EXEC 0x200 /* software: i-cache coherency required */ | 368 | #define _PAGE_EXEC 0x200 /* software: i-cache coherency required */ |
364 | #define _PAGE_RW 0x400 /* software: user write access allowed */ | 369 | #define _PAGE_RW 0x400 /* software: user write access allowed */ |
370 | #define _PAGE_SPECIAL 0x800 /* software: Special page */ | ||
365 | 371 | ||
372 | #ifdef CONFIG_PTE_64BIT | ||
373 | /* We never clear the high word of the pte */ | ||
374 | #define _PTE_NONE_MASK (0xffffffff00000000ULL | _PAGE_HASHPTE) | ||
375 | #else | ||
366 | #define _PTE_NONE_MASK _PAGE_HASHPTE | 376 | #define _PTE_NONE_MASK _PAGE_HASHPTE |
377 | #endif | ||
367 | 378 | ||
368 | #define _PMD_PRESENT 0 | 379 | #define _PMD_PRESENT 0 |
369 | #define _PMD_PRESENT_MASK (PAGE_MASK) | 380 | #define _PMD_PRESENT_MASK (PAGE_MASK) |
@@ -372,6 +383,8 @@ extern int icache_44x_need_flush; | |||
372 | /* Hash table based platforms need atomic updates of the linux PTE */ | 383 | /* Hash table based platforms need atomic updates of the linux PTE */ |
373 | #define PTE_ATOMIC_UPDATES 1 | 384 | #define PTE_ATOMIC_UPDATES 1 |
374 | 385 | ||
386 | #define __HAVE_ARCH_PTE_SPECIAL | ||
387 | |||
375 | #endif | 388 | #endif |
376 | 389 | ||
377 | /* | 390 | /* |
@@ -404,6 +417,9 @@ extern int icache_44x_need_flush; | |||
404 | #ifndef _PAGE_WRITETHRU | 417 | #ifndef _PAGE_WRITETHRU |
405 | #define _PAGE_WRITETHRU 0 | 418 | #define _PAGE_WRITETHRU 0 |
406 | #endif | 419 | #endif |
420 | #ifndef _PAGE_SPECIAL | ||
421 | #define _PAGE_SPECIAL 0 | ||
422 | #endif | ||
407 | #ifndef _PMD_PRESENT_MASK | 423 | #ifndef _PMD_PRESENT_MASK |
408 | #define _PMD_PRESENT_MASK _PMD_PRESENT | 424 | #define _PMD_PRESENT_MASK _PMD_PRESENT |
409 | #endif | 425 | #endif |
@@ -415,11 +431,11 @@ extern int icache_44x_need_flush; | |||
415 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) | 431 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) |
416 | 432 | ||
417 | 433 | ||
418 | #define PAGE_PROT_BITS __pgprot(_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \ | 434 | #define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \ |
419 | _PAGE_WRITETHRU | _PAGE_ENDIAN | \ | 435 | _PAGE_WRITETHRU | _PAGE_ENDIAN | \ |
420 | _PAGE_USER | _PAGE_ACCESSED | \ | 436 | _PAGE_USER | _PAGE_ACCESSED | \ |
421 | _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \ | 437 | _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \ |
422 | _PAGE_EXEC | _PAGE_HWEXEC) | 438 | _PAGE_EXEC | _PAGE_HWEXEC) |
423 | /* | 439 | /* |
424 | * Note: the _PAGE_COHERENT bit automatically gets set in the hardware | 440 | * Note: the _PAGE_COHERENT bit automatically gets set in the hardware |
425 | * PTE if CONFIG_SMP is defined (hash_page does this); there is no need | 441 | * PTE if CONFIG_SMP is defined (hash_page does this); there is no need |
@@ -517,7 +533,8 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); | |||
517 | 533 | ||
518 | #define pte_none(pte) ((pte_val(pte) & ~_PTE_NONE_MASK) == 0) | 534 | #define pte_none(pte) ((pte_val(pte) & ~_PTE_NONE_MASK) == 0) |
519 | #define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) | 535 | #define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) |
520 | #define pte_clear(mm,addr,ptep) do { set_pte_at((mm), (addr), (ptep), __pte(0)); } while (0) | 536 | #define pte_clear(mm, addr, ptep) \ |
537 | do { pte_update(ptep, ~_PAGE_HASHPTE, 0); } while (0) | ||
521 | 538 | ||
522 | #define pmd_none(pmd) (!pmd_val(pmd)) | 539 | #define pmd_none(pmd) (!pmd_val(pmd)) |
523 | #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) | 540 | #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) |
@@ -533,7 +550,7 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } | |||
533 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } | 550 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } |
534 | static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } | 551 | static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } |
535 | static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } | 552 | static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } |
536 | static inline int pte_special(pte_t pte) { return 0; } | 553 | static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } |
537 | 554 | ||
538 | static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; } | 555 | static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; } |
539 | static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; } | 556 | static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; } |
@@ -552,10 +569,10 @@ static inline pte_t pte_mkdirty(pte_t pte) { | |||
552 | static inline pte_t pte_mkyoung(pte_t pte) { | 569 | static inline pte_t pte_mkyoung(pte_t pte) { |
553 | pte_val(pte) |= _PAGE_ACCESSED; return pte; } | 570 | pte_val(pte) |= _PAGE_ACCESSED; return pte; } |
554 | static inline pte_t pte_mkspecial(pte_t pte) { | 571 | static inline pte_t pte_mkspecial(pte_t pte) { |
555 | return pte; } | 572 | pte_val(pte) |= _PAGE_SPECIAL; return pte; } |
556 | static inline unsigned long pte_pgprot(pte_t pte) | 573 | static inline pgprot_t pte_pgprot(pte_t pte) |
557 | { | 574 | { |
558 | return __pgprot(pte_val(pte)) & PAGE_PROT_BITS; | 575 | return __pgprot(pte_val(pte) & PAGE_PROT_BITS); |
559 | } | 576 | } |
560 | 577 | ||
561 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 578 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
@@ -575,6 +592,10 @@ extern int flush_hash_pages(unsigned context, unsigned long va, | |||
575 | extern void add_hash_page(unsigned context, unsigned long va, | 592 | extern void add_hash_page(unsigned context, unsigned long va, |
576 | unsigned long pmdval); | 593 | unsigned long pmdval); |
577 | 594 | ||
595 | /* Flush an entry from the TLB/hash table */ | ||
596 | extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, | ||
597 | unsigned long address); | ||
598 | |||
578 | /* | 599 | /* |
579 | * Atomic PTE updates. | 600 | * Atomic PTE updates. |
580 | * | 601 | * |
@@ -612,9 +633,6 @@ static inline unsigned long pte_update(pte_t *p, | |||
612 | return old; | 633 | return old; |
613 | } | 634 | } |
614 | #else /* CONFIG_PTE_64BIT */ | 635 | #else /* CONFIG_PTE_64BIT */ |
615 | /* TODO: Change that to only modify the low word and move set_pte_at() | ||
616 | * out of line | ||
617 | */ | ||
618 | static inline unsigned long long pte_update(pte_t *p, | 636 | static inline unsigned long long pte_update(pte_t *p, |
619 | unsigned long clr, | 637 | unsigned long clr, |
620 | unsigned long set) | 638 | unsigned long set) |
@@ -652,14 +670,36 @@ static inline unsigned long long pte_update(pte_t *p, | |||
652 | * On machines which use an MMU hash table we avoid changing the | 670 | * On machines which use an MMU hash table we avoid changing the |
653 | * _PAGE_HASHPTE bit. | 671 | * _PAGE_HASHPTE bit. |
654 | */ | 672 | */ |
655 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | 673 | |
674 | static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
656 | pte_t *ptep, pte_t pte) | 675 | pte_t *ptep, pte_t pte) |
657 | { | 676 | { |
658 | #if _PAGE_HASHPTE != 0 | 677 | #if (_PAGE_HASHPTE != 0) && defined(CONFIG_SMP) && !defined(CONFIG_PTE_64BIT) |
659 | pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE); | 678 | pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE); |
679 | #elif defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP) | ||
680 | #if _PAGE_HASHPTE != 0 | ||
681 | if (pte_val(*ptep) & _PAGE_HASHPTE) | ||
682 | flush_hash_entry(mm, ptep, addr); | ||
683 | #endif | ||
684 | __asm__ __volatile__("\ | ||
685 | stw%U0%X0 %2,%0\n\ | ||
686 | eieio\n\ | ||
687 | stw%U0%X0 %L2,%1" | ||
688 | : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4)) | ||
689 | : "r" (pte) : "memory"); | ||
660 | #else | 690 | #else |
661 | *ptep = pte; | 691 | *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE) |
692 | | (pte_val(pte) & ~_PAGE_HASHPTE)); | ||
693 | #endif | ||
694 | } | ||
695 | |||
696 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
697 | pte_t *ptep, pte_t pte) | ||
698 | { | ||
699 | #if defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP) | ||
700 | WARN_ON(pte_present(*ptep)); | ||
662 | #endif | 701 | #endif |
702 | __set_pte_at(mm, addr, ptep, pte); | ||
663 | } | 703 | } |
664 | 704 | ||
665 | /* | 705 | /* |