aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/include/asm/pgtable-ppc32.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/include/asm/pgtable-ppc32.h')
-rw-r--r--arch/powerpc/include/asm/pgtable-ppc32.h72
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; }
533static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } 550static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
534static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } 551static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
535static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } 552static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
536static inline int pte_special(pte_t pte) { return 0; } 553static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
537 554
538static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; } 555static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
539static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; } 556static 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) {
552static inline pte_t pte_mkyoung(pte_t pte) { 569static inline pte_t pte_mkyoung(pte_t pte) {
553 pte_val(pte) |= _PAGE_ACCESSED; return pte; } 570 pte_val(pte) |= _PAGE_ACCESSED; return pte; }
554static inline pte_t pte_mkspecial(pte_t pte) { 571static inline pte_t pte_mkspecial(pte_t pte) {
555 return pte; } 572 pte_val(pte) |= _PAGE_SPECIAL; return pte; }
556static inline unsigned long pte_pgprot(pte_t pte) 573static 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
561static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 578static 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,
575extern void add_hash_page(unsigned context, unsigned long va, 592extern 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 */
596extern 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 */
618static inline unsigned long long pte_update(pte_t *p, 636static 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 */
655static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, 673
674static 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
696static 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/*