This source file includes following definitions.
- init_pointer_table
- get_pointer_table
- free_pointer_table
- clear040
- cleari040
- push040
- pushcl040
- cache_clear
- cache_push
1
2
3
4
5
6
7
8 #include <linux/module.h>
9 #include <linux/mm.h>
10 #include <linux/kernel.h>
11 #include <linux/string.h>
12 #include <linux/types.h>
13 #include <linux/init.h>
14 #include <linux/pagemap.h>
15 #include <linux/gfp.h>
16
17 #include <asm/setup.h>
18 #include <asm/segment.h>
19 #include <asm/page.h>
20 #include <asm/pgalloc.h>
21 #include <asm/traps.h>
22 #include <asm/machdep.h>
23
24
25
26
27
28
29 typedef struct list_head ptable_desc;
30 static LIST_HEAD(ptable_list);
31
32 #define PD_PTABLE(page) ((ptable_desc *)&(virt_to_page(page)->lru))
33 #define PD_PAGE(ptable) (list_entry(ptable, struct page, lru))
34 #define PD_MARKBITS(dp) (*(unsigned char *)&PD_PAGE(dp)->index)
35
36 #define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t))
37
38 void __init init_pointer_table(unsigned long ptable)
39 {
40 ptable_desc *dp;
41 unsigned long page = ptable & PAGE_MASK;
42 unsigned char mask = 1 << ((ptable - page)/PTABLE_SIZE);
43
44 dp = PD_PTABLE(page);
45 if (!(PD_MARKBITS(dp) & mask)) {
46 PD_MARKBITS(dp) = 0xff;
47 list_add(dp, &ptable_list);
48 }
49
50 PD_MARKBITS(dp) &= ~mask;
51 pr_debug("init_pointer_table: %lx, %x\n", ptable, PD_MARKBITS(dp));
52
53
54 __ClearPageReserved(PD_PAGE(dp));
55 init_page_count(PD_PAGE(dp));
56
57 return;
58 }
59
60 pmd_t *get_pointer_table (void)
61 {
62 ptable_desc *dp = ptable_list.next;
63 unsigned char mask = PD_MARKBITS (dp);
64 unsigned char tmp;
65 unsigned int off;
66
67
68
69
70
71
72
73 if (mask == 0) {
74 void *page;
75 ptable_desc *new;
76
77 if (!(page = (void *)get_zeroed_page(GFP_KERNEL)))
78 return NULL;
79
80 flush_tlb_kernel_page(page);
81 nocache_page(page);
82
83 new = PD_PTABLE(page);
84 PD_MARKBITS(new) = 0xfe;
85 list_add_tail(new, dp);
86
87 return (pmd_t *)page;
88 }
89
90 for (tmp = 1, off = 0; (mask & tmp) == 0; tmp <<= 1, off += PTABLE_SIZE)
91 ;
92 PD_MARKBITS(dp) = mask & ~tmp;
93 if (!PD_MARKBITS(dp)) {
94
95 list_move_tail(dp, &ptable_list);
96 }
97 return (pmd_t *) (page_address(PD_PAGE(dp)) + off);
98 }
99
100 int free_pointer_table (pmd_t *ptable)
101 {
102 ptable_desc *dp;
103 unsigned long page = (unsigned long)ptable & PAGE_MASK;
104 unsigned char mask = 1 << (((unsigned long)ptable - page)/PTABLE_SIZE);
105
106 dp = PD_PTABLE(page);
107 if (PD_MARKBITS (dp) & mask)
108 panic ("table already free!");
109
110 PD_MARKBITS (dp) |= mask;
111
112 if (PD_MARKBITS(dp) == 0xff) {
113
114 list_del(dp);
115 cache_page((void *)page);
116 free_page (page);
117 return 1;
118 } else if (ptable_list.next != dp) {
119
120
121
122
123 list_move(dp, &ptable_list);
124 }
125 return 0;
126 }
127
128
129 static inline void clear040(unsigned long paddr)
130 {
131 asm volatile (
132 "nop\n\t"
133 ".chip 68040\n\t"
134 "cinvp %%bc,(%0)\n\t"
135 ".chip 68k"
136 : : "a" (paddr));
137 }
138
139
140 static inline void cleari040(unsigned long paddr)
141 {
142 asm volatile (
143 "nop\n\t"
144 ".chip 68040\n\t"
145 "cinvp %%ic,(%0)\n\t"
146 ".chip 68k"
147 : : "a" (paddr));
148 }
149
150
151
152 static inline void push040(unsigned long paddr)
153 {
154 asm volatile (
155 "nop\n\t"
156 ".chip 68040\n\t"
157 "cpushp %%bc,(%0)\n\t"
158 ".chip 68k"
159 : : "a" (paddr));
160 }
161
162
163
164 static inline void pushcl040(unsigned long paddr)
165 {
166 unsigned long flags;
167
168 local_irq_save(flags);
169 push040(paddr);
170 if (CPU_IS_060)
171 clear040(paddr);
172 local_irq_restore(flags);
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 void cache_clear (unsigned long paddr, int len)
203 {
204 if (CPU_IS_COLDFIRE) {
205 clear_cf_bcache(0, DCACHE_MAX_ADDR);
206 } else if (CPU_IS_040_OR_060) {
207 int tmp;
208
209
210
211
212
213
214 if ((tmp = -paddr & (PAGE_SIZE - 1))) {
215 pushcl040(paddr & PAGE_MASK);
216 if ((len -= tmp) <= 0)
217 return;
218 paddr += tmp;
219 }
220 tmp = PAGE_SIZE;
221 paddr &= PAGE_MASK;
222 while ((len -= tmp) >= 0) {
223 clear040(paddr);
224 paddr += tmp;
225 }
226 if ((len += tmp))
227
228 pushcl040(paddr);
229 }
230 else
231 asm volatile ("movec %/cacr,%/d0\n\t"
232 "oriw %0,%/d0\n\t"
233 "movec %/d0,%/cacr"
234 : : "i" (FLUSH_I_AND_D)
235 : "d0");
236 #ifdef CONFIG_M68K_L2_CACHE
237 if(mach_l2_flush)
238 mach_l2_flush(0);
239 #endif
240 }
241 EXPORT_SYMBOL(cache_clear);
242
243
244
245
246
247
248
249
250
251 void cache_push (unsigned long paddr, int len)
252 {
253 if (CPU_IS_COLDFIRE) {
254 flush_cf_bcache(0, DCACHE_MAX_ADDR);
255 } else if (CPU_IS_040_OR_060) {
256 int tmp = PAGE_SIZE;
257
258
259
260
261
262
263 len += paddr & (PAGE_SIZE - 1);
264
265
266
267
268
269 paddr &= PAGE_MASK;
270
271 do {
272 push040(paddr);
273 paddr += tmp;
274 } while ((len -= tmp) > 0);
275 }
276
277
278
279
280
281
282
283
284
285 else
286 asm volatile ("movec %/cacr,%/d0\n\t"
287 "oriw %0,%/d0\n\t"
288 "movec %/d0,%/cacr"
289 : : "i" (FLUSH_I)
290 : "d0");
291 #ifdef CONFIG_M68K_L2_CACHE
292 if(mach_l2_flush)
293 mach_l2_flush(1);
294 #endif
295 }
296 EXPORT_SYMBOL(cache_push);
297