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
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.