.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> |
---|
3 | 4 | * Copyright (C) 2008-2009 PetaLogix |
---|
4 | 5 | * Copyright (C) 2006 Atmark Techno, Inc. |
---|
5 | | - * |
---|
6 | | - * This file is subject to the terms and conditions of the GNU General Public |
---|
7 | | - * License. See the file "COPYING" in the main directory of this archive |
---|
8 | | - * for more details. |
---|
9 | 6 | */ |
---|
10 | 7 | |
---|
11 | 8 | #ifndef _ASM_MICROBLAZE_PGALLOC_H |
---|
.. | .. |
---|
15 | 12 | |
---|
16 | 13 | #include <linux/kernel.h> /* For min/max macros */ |
---|
17 | 14 | #include <linux/highmem.h> |
---|
| 15 | +#include <linux/pgtable.h> |
---|
18 | 16 | #include <asm/setup.h> |
---|
19 | 17 | #include <asm/io.h> |
---|
20 | 18 | #include <asm/page.h> |
---|
21 | 19 | #include <asm/cache.h> |
---|
22 | | -#include <asm/pgtable.h> |
---|
23 | 20 | |
---|
24 | | -#define PGDIR_ORDER 0 |
---|
25 | | - |
---|
26 | | -/* |
---|
27 | | - * This is handled very differently on MicroBlaze since out page tables |
---|
28 | | - * are all 0's and I want to be able to use these zero'd pages elsewhere |
---|
29 | | - * as well - it gives us quite a speedup. |
---|
30 | | - * -- Cort |
---|
31 | | - */ |
---|
32 | | -extern struct pgtable_cache_struct { |
---|
33 | | - unsigned long *pgd_cache; |
---|
34 | | - unsigned long *pte_cache; |
---|
35 | | - unsigned long pgtable_cache_sz; |
---|
36 | | -} quicklists; |
---|
37 | | - |
---|
38 | | -#define pgd_quicklist (quicklists.pgd_cache) |
---|
39 | | -#define pmd_quicklist ((unsigned long *)0) |
---|
40 | | -#define pte_quicklist (quicklists.pte_cache) |
---|
41 | | -#define pgtable_cache_size (quicklists.pgtable_cache_sz) |
---|
42 | | - |
---|
43 | | -extern unsigned long *zero_cache; /* head linked list of pre-zero'd pages */ |
---|
44 | | -extern atomic_t zero_sz; /* # currently pre-zero'd pages */ |
---|
45 | | -extern atomic_t zeropage_hits; /* # zero'd pages request that we've done */ |
---|
46 | | -extern atomic_t zeropage_calls; /* # zero'd pages request that've been made */ |
---|
47 | | -extern atomic_t zerototal; /* # pages zero'd over time */ |
---|
48 | | - |
---|
49 | | -#define zero_quicklist (zero_cache) |
---|
50 | | -#define zero_cache_sz (zero_sz) |
---|
51 | | -#define zero_cache_calls (zeropage_calls) |
---|
52 | | -#define zero_cache_hits (zeropage_hits) |
---|
53 | | -#define zero_cache_total (zerototal) |
---|
54 | | - |
---|
55 | | -/* |
---|
56 | | - * return a pre-zero'd page from the list, |
---|
57 | | - * return NULL if none available -- Cort |
---|
58 | | - */ |
---|
59 | | -extern unsigned long get_zero_page_fast(void); |
---|
| 21 | +#define __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL |
---|
| 22 | +#include <asm-generic/pgalloc.h> |
---|
60 | 23 | |
---|
61 | 24 | extern void __bad_pte(pmd_t *pmd); |
---|
62 | 25 | |
---|
63 | | -static inline pgd_t *get_pgd_slow(void) |
---|
| 26 | +static inline pgd_t *get_pgd(void) |
---|
64 | 27 | { |
---|
65 | | - pgd_t *ret; |
---|
66 | | - |
---|
67 | | - ret = (pgd_t *)__get_free_pages(GFP_KERNEL, PGDIR_ORDER); |
---|
68 | | - if (ret != NULL) |
---|
69 | | - clear_page(ret); |
---|
70 | | - return ret; |
---|
| 28 | + return (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0); |
---|
71 | 29 | } |
---|
72 | 30 | |
---|
73 | | -static inline pgd_t *get_pgd_fast(void) |
---|
74 | | -{ |
---|
75 | | - unsigned long *ret; |
---|
76 | | - |
---|
77 | | - ret = pgd_quicklist; |
---|
78 | | - if (ret != NULL) { |
---|
79 | | - pgd_quicklist = (unsigned long *)(*ret); |
---|
80 | | - ret[0] = 0; |
---|
81 | | - pgtable_cache_size--; |
---|
82 | | - } else |
---|
83 | | - ret = (unsigned long *)get_pgd_slow(); |
---|
84 | | - return (pgd_t *)ret; |
---|
85 | | -} |
---|
86 | | - |
---|
87 | | -static inline void free_pgd_fast(pgd_t *pgd) |
---|
88 | | -{ |
---|
89 | | - *(unsigned long **)pgd = pgd_quicklist; |
---|
90 | | - pgd_quicklist = (unsigned long *) pgd; |
---|
91 | | - pgtable_cache_size++; |
---|
92 | | -} |
---|
93 | | - |
---|
94 | | -static inline void free_pgd_slow(pgd_t *pgd) |
---|
95 | | -{ |
---|
96 | | - free_page((unsigned long)pgd); |
---|
97 | | -} |
---|
98 | | - |
---|
99 | | -#define pgd_free(mm, pgd) free_pgd_fast(pgd) |
---|
100 | | -#define pgd_alloc(mm) get_pgd_fast() |
---|
| 31 | +#define pgd_alloc(mm) get_pgd() |
---|
101 | 32 | |
---|
102 | 33 | #define pmd_pgtable(pmd) pmd_page(pmd) |
---|
103 | 34 | |
---|
104 | | -/* |
---|
105 | | - * We don't have any real pmd's, and this code never triggers because |
---|
106 | | - * the pgd will always be present.. |
---|
107 | | - */ |
---|
108 | | -#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); }) |
---|
109 | | -#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) |
---|
110 | | - |
---|
111 | | -extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); |
---|
112 | | - |
---|
113 | | -static inline struct page *pte_alloc_one(struct mm_struct *mm, |
---|
114 | | - unsigned long address) |
---|
115 | | -{ |
---|
116 | | - struct page *ptepage; |
---|
117 | | - |
---|
118 | | -#ifdef CONFIG_HIGHPTE |
---|
119 | | - int flags = GFP_KERNEL | __GFP_HIGHMEM; |
---|
120 | | -#else |
---|
121 | | - int flags = GFP_KERNEL; |
---|
122 | | -#endif |
---|
123 | | - |
---|
124 | | - ptepage = alloc_pages(flags, 0); |
---|
125 | | - if (!ptepage) |
---|
126 | | - return NULL; |
---|
127 | | - clear_highpage(ptepage); |
---|
128 | | - if (!pgtable_page_ctor(ptepage)) { |
---|
129 | | - __free_page(ptepage); |
---|
130 | | - return NULL; |
---|
131 | | - } |
---|
132 | | - return ptepage; |
---|
133 | | -} |
---|
134 | | - |
---|
135 | | -static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, |
---|
136 | | - unsigned long address) |
---|
137 | | -{ |
---|
138 | | - unsigned long *ret; |
---|
139 | | - |
---|
140 | | - ret = pte_quicklist; |
---|
141 | | - if (ret != NULL) { |
---|
142 | | - pte_quicklist = (unsigned long *)(*ret); |
---|
143 | | - ret[0] = 0; |
---|
144 | | - pgtable_cache_size--; |
---|
145 | | - } |
---|
146 | | - return (pte_t *)ret; |
---|
147 | | -} |
---|
148 | | - |
---|
149 | | -static inline void pte_free_fast(pte_t *pte) |
---|
150 | | -{ |
---|
151 | | - *(unsigned long **)pte = pte_quicklist; |
---|
152 | | - pte_quicklist = (unsigned long *) pte; |
---|
153 | | - pgtable_cache_size++; |
---|
154 | | -} |
---|
155 | | - |
---|
156 | | -static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) |
---|
157 | | -{ |
---|
158 | | - free_page((unsigned long)pte); |
---|
159 | | -} |
---|
160 | | - |
---|
161 | | -static inline void pte_free_slow(struct page *ptepage) |
---|
162 | | -{ |
---|
163 | | - __free_page(ptepage); |
---|
164 | | -} |
---|
165 | | - |
---|
166 | | -static inline void pte_free(struct mm_struct *mm, struct page *ptepage) |
---|
167 | | -{ |
---|
168 | | - pgtable_page_dtor(ptepage); |
---|
169 | | - __free_page(ptepage); |
---|
170 | | -} |
---|
| 35 | +extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm); |
---|
171 | 36 | |
---|
172 | 37 | #define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, (pte)) |
---|
173 | 38 | |
---|
.. | .. |
---|
177 | 42 | #define pmd_populate_kernel(mm, pmd, pte) \ |
---|
178 | 43 | (pmd_val(*(pmd)) = (unsigned long) (pte)) |
---|
179 | 44 | |
---|
180 | | -/* |
---|
181 | | - * We don't have any real pmd's, and this code never triggers because |
---|
182 | | - * the pgd will always be present.. |
---|
183 | | - */ |
---|
184 | | -#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) |
---|
185 | | -#define pmd_free(mm, x) do { } while (0) |
---|
186 | | -#define __pmd_free_tlb(tlb, x, addr) pmd_free((tlb)->mm, x) |
---|
187 | | -#define pgd_populate(mm, pmd, pte) BUG() |
---|
188 | | - |
---|
189 | | -extern int do_check_pgt_cache(int, int); |
---|
190 | | - |
---|
191 | 45 | #endif /* CONFIG_MMU */ |
---|
192 | | - |
---|
193 | | -#define check_pgt_cache() do { } while (0) |
---|
194 | 46 | |
---|
195 | 47 | #endif /* _ASM_MICROBLAZE_PGALLOC_H */ |
---|