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

Linux Cross Reference
Linux/include/asm-sh/pgalloc.h

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

  1 #ifndef __ASM_SH_PGALLOC_H
  2 #define __ASM_SH_PGALLOC_H
  3 
  4 #include <asm/processor.h>
  5 #include <linux/threads.h>
  6 #include <linux/slab.h>
  7 
  8 #define pgd_quicklist (current_cpu_data.pgd_quick)
  9 #define pmd_quicklist ((unsigned long *)0)
 10 #define pte_quicklist (current_cpu_data.pte_quick)
 11 #define pgtable_cache_size (current_cpu_data.pgtable_cache_sz)
 12 
 13 #include <asm/pgalloc-2level.h>
 14 
 15 /*
 16  * Allocate and free page tables. The xxx_kernel() versions are
 17  * used to allocate a kernel page table - this turns on ASN bits
 18  * if any.
 19  */
 20 
 21 static __inline__ pgd_t *get_pgd_slow(void)
 22 {
 23         unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
 24         pgd_t *ret = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
 25 
 26         if (ret)
 27                 memset(ret, 0, pgd_size);
 28 
 29         return ret;
 30 }
 31 
 32 static __inline__ pgd_t *get_pgd_fast(void)
 33 {
 34         unsigned long *ret;
 35 
 36         if ((ret = pgd_quicklist) != NULL) {
 37                 pgd_quicklist = (unsigned long *)(*ret);
 38                 ret[0] = 0;
 39                 pgtable_cache_size--;
 40         } else
 41                 ret = (unsigned long *)get_pgd_slow();
 42         return (pgd_t *)ret;
 43 }
 44 
 45 static __inline__ void free_pgd_fast(pgd_t *pgd)
 46 {
 47         *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
 48         pgd_quicklist = (unsigned long *) pgd;
 49         pgtable_cache_size++;
 50 }
 51 
 52 static __inline__ void free_pgd_slow(pgd_t *pgd)
 53 {
 54         kfree(pgd);
 55 }
 56 
 57 extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
 58 extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
 59 
 60 static __inline__ pte_t *get_pte_fast(void)
 61 {
 62         unsigned long *ret;
 63 
 64         if((ret = (unsigned long *)pte_quicklist) != NULL) {
 65                 pte_quicklist = (unsigned long *)(*ret);
 66                 ret[0] = ret[1];
 67                 pgtable_cache_size--;
 68         }
 69         return (pte_t *)ret;
 70 }
 71 
 72 static __inline__ void free_pte_fast(pte_t *pte)
 73 {
 74         *(unsigned long *)pte = (unsigned long) pte_quicklist;
 75         pte_quicklist = (unsigned long *) pte;
 76         pgtable_cache_size++;
 77 }
 78 
 79 static __inline__ void free_pte_slow(pte_t *pte)
 80 {
 81         free_page((unsigned long)pte);
 82 }
 83 
 84 #define pte_free_kernel(pte)    free_pte_slow(pte)
 85 #define pte_free(pte)      free_pte_slow(pte)
 86 #define pgd_free(pgd)      free_pgd_slow(pgd)
 87 #define pgd_alloc()          get_pgd_fast()
 88 
 89 static __inline__ pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
 90 {
 91         if (!pmd)
 92                 BUG();
 93         address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
 94         if (pmd_none(*pmd)) {
 95                 pte_t * page = (pte_t *) get_pte_fast();
 96                 
 97                 if (!page)
 98                         return get_pte_kernel_slow(pmd, address);
 99                 set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(page)));
100                 return page + address;
101         }
102         if (pmd_bad(*pmd)) {
103                 __handle_bad_pmd_kernel(pmd);
104                 return NULL;
105         }
106         return (pte_t *) pmd_page(*pmd) + address;
107 }
108 
109 static __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
110 {
111         address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
112 
113         if (pmd_none(*pmd))
114                 goto getnew;
115         if (pmd_bad(*pmd))
116                 goto fix;
117         return (pte_t *)pmd_page(*pmd) + address;
118 getnew:
119 {
120         unsigned long page = (unsigned long) get_pte_fast();
121         
122         if (!page)
123                 return get_pte_slow(pmd, address);
124         set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(page)));
125         return (pte_t *)page + address;
126 }
127 fix:
128         __handle_bad_pmd(pmd);
129         return NULL;
130 }
131 
132 /*
133  * allocating and freeing a pmd is trivial: the 1-entry pmd is
134  * inside the pgd, so has no extra memory associated with it.
135  */
136 static __inline__ void pmd_free(pmd_t * pmd)
137 {
138 }
139 
140 #define pmd_free_kernel         pmd_free
141 #define pmd_alloc_kernel        pmd_alloc
142 
143 extern int do_check_pgt_cache(int, int);
144 
145 /*
146  * TLB flushing:
147  *
148  *  - flush_tlb() flushes the current mm struct TLBs
149  *  - flush_tlb_all() flushes all processes TLBs
150  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
151  *  - flush_tlb_page(vma, vmaddr) flushes one page
152  *  - flush_tlb_range(mm, start, end) flushes a range of pages
153  *
154  */
155 
156 extern void flush_tlb(void);
157 extern void flush_tlb_all(void);
158 extern void flush_tlb_mm(struct mm_struct *mm);
159 extern void flush_tlb_range(struct mm_struct *mm, unsigned long start,
160                             unsigned long end);
161 extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
162 
163 static __inline__ void flush_tlb_pgtables(struct mm_struct *mm,
164                                           unsigned long start, unsigned long end)
165 {
166 }
167 
168 #endif /* __ASM_SH_PGALLOC_H */
169 

~ [ 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.