~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-i386/pgtable-3level.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #ifndef _I386_PGTABLE_3LEVEL_H
  2 #define _I386_PGTABLE_3LEVEL_H
  3 
  4 /*
  5  * Intel Physical Address Extension (PAE) Mode - three-level page
  6  * tables on PPro+ CPUs.
  7  *
  8  * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
  9  */
 10 
 11 /*
 12  * PGDIR_SHIFT determines what a top-level page table entry can map
 13  */
 14 #define PGDIR_SHIFT     30
 15 #define PTRS_PER_PGD    4
 16 
 17 /*
 18  * PMD_SHIFT determines the size of the area a middle-level
 19  * page table can map
 20  */
 21 #define PMD_SHIFT       21
 22 #define PTRS_PER_PMD    512
 23 
 24 /*
 25  * entries per page directory level
 26  */
 27 #define PTRS_PER_PTE    512
 28 
 29 #define pte_ERROR(e) \
 30         printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, &(e), (e).pte_high, (e).pte_low)
 31 #define pmd_ERROR(e) \
 32         printk("%s:%d: bad pmd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pmd_val(e))
 33 #define pgd_ERROR(e) \
 34         printk("%s:%d: bad pgd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
 35 
 36 /*
 37  * Subtle, in PAE mode we cannot have zeroes in the top level
 38  * page directory, the CPU enforces this. (ie. the PGD entry
 39  * always has to have the present bit set.) The CPU caches
 40  * the 4 pgd entries internally, so there is no extra memory
 41  * load on TLB miss, despite one more level of indirection.
 42  */
 43 #define EMPTY_PGD (__pa(empty_zero_page) + 1)
 44 #define pgd_none(x)     (pgd_val(x) == EMPTY_PGD)
 45 extern inline int pgd_bad(pgd_t pgd)            { return 0; }
 46 extern inline int pgd_present(pgd_t pgd)        { return !pgd_none(pgd); }
 47 
 48 /* Rules for using set_pte: the pte being assigned *must* be
 49  * either not present or in a state where the hardware will
 50  * not attempt to update the pte.  In places where this is
 51  * not possible, use pte_get_and_clear to obtain the old pte
 52  * value and then use set_pte to update it.  -ben
 53  */
 54 static inline void set_pte(pte_t *ptep, pte_t pte)
 55 {
 56         ptep->pte_high = pte.pte_high;
 57         smp_wmb();
 58         ptep->pte_low = pte.pte_low;
 59 }
 60 #define set_pmd(pmdptr,pmdval) \
 61                 set_64bit((unsigned long long *)(pmdptr),pmd_val(pmdval))
 62 #define set_pgd(pgdptr,pgdval) \
 63                 set_64bit((unsigned long long *)(pgdptr),pgd_val(pgdval))
 64 
 65 /*
 66  * Pentium-II errata A13: in PAE mode we explicitly have to flush
 67  * the TLB via cr3 if the top-level pgd is changed... This was one tough
 68  * thing to find out - guess i should first read all the documentation
 69  * next time around ;)
 70  */
 71 extern inline void __pgd_clear (pgd_t * pgd)
 72 {
 73         set_pgd(pgd, __pgd(EMPTY_PGD));
 74 }
 75 
 76 extern inline void pgd_clear (pgd_t * pgd)
 77 {
 78         __pgd_clear(pgd);
 79         __flush_tlb();
 80 }
 81 
 82 #define pgd_page(pgd) \
 83 ((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
 84 
 85 /* Find an entry in the second-level page table.. */
 86 #define pmd_offset(dir, address) ((pmd_t *) pgd_page(*(dir)) + \
 87                         __pmd_offset(address))
 88 
 89 static inline pte_t ptep_get_and_clear(pte_t *ptep)
 90 {
 91         pte_t res;
 92 
 93         /* xchg acts as a barrier before the setting of the high bits */
 94         res.pte_low = xchg(&ptep->pte_low, 0);
 95         res.pte_high = ptep->pte_high;
 96         ptep->pte_high = 0;
 97 
 98         return res;
 99 }
100 
101 static inline int pte_same(pte_t a, pte_t b)
102 {
103         return a.pte_low == b.pte_low && a.pte_high == b.pte_high;
104 }
105 
106 #define pte_page(x)     (mem_map+(((x).pte_low >> PAGE_SHIFT) | ((x).pte_high << (32 - PAGE_SHIFT))))
107 #define pte_none(x)     (!(x).pte_low && !(x).pte_high)
108 
109 static inline pte_t __mk_pte(unsigned long page_nr, pgprot_t pgprot)
110 {
111         pte_t pte;
112 
113         pte.pte_high = page_nr >> (32 - PAGE_SHIFT);
114         pte.pte_low = (page_nr << PAGE_SHIFT) | pgprot_val(pgprot);
115         return pte;
116 }
117 
118 #endif /* _I386_PGTABLE_3LEVEL_H */
119 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.