This source file includes following definitions.
- pte_page
- pmd_page
- pmd_set
- pte_none
- pte_present
- pte_inuse
- pte_clear
- pte_reuse
- pmd_none
- pmd_bad
- pmd_present
- pmd_inuse
- pmd_clear
- pmd_reuse
- pgd_none
- pgd_bad
- pgd_present
- pgd_inuse
- pgd_clear
- pte_read
- pte_write
- pte_exec
- pte_dirty
- pte_young
- pte_cow
- pte_wrprotect
- pte_rdprotect
- pte_exprotect
- pte_mkclean
- pte_mkold
- pte_uncow
- pte_mkwrite
- pte_mkread
- pte_mkexec
- pte_mkdirty
- pte_mkyoung
- pte_mkcow
- mk_pte
- pte_modify
- pgd_offset
- pmd_offset
- pte_offset
- pte_free_kernel
- pte_alloc_kernel
- pmd_free_kernel
- pmd_alloc_kernel
- pte_free
- pte_alloc
- pmd_free
- pmd_alloc
- pgd_free
- pgd_init
- pgd_alloc
1 #ifndef __ASM_MIPS_PGTABLE_H
2 #define __ASM_MIPS_PGTABLE_H
3
4 #ifndef __LANGUAGE_ASSEMBLY__
5
6 #include <linux/linkage.h>
7 #include <asm/cachectl.h>
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 extern asmlinkage void tlbflush(void);
38 #define invalidate() ({sys_cacheflush(0, ~0, BCACHE);tlbflush();})
39
40 #define invalidate_all() invalidate()
41 #define invalidate_mm(mm_struct) \
42 do { if ((mm_struct) == current->mm) invalidate(); } while (0)
43 #define invalidate_page(mm_struct,addr) \
44 do { if ((mm_struct) == current->mm) invalidate(); } while (0)
45 #define invalidate_range(mm_struct,start,end) \
46 do { if ((mm_struct) == current->mm) invalidate(); } while (0)
47
48
49
50
51
52
53 extern void __copy_page(unsigned long from, unsigned long to);
54 #define copy_page(from,to) __copy_page((unsigned long)from, (unsigned long)to)
55
56
57
58
59
60 #define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
61
62 #endif
63
64
65 #define PMD_SHIFT 22
66 #define PMD_SIZE (1UL << PMD_SHIFT)
67 #define PMD_MASK (~(PMD_SIZE-1))
68
69
70 #define PGDIR_SHIFT 22
71 #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
72 #define PGDIR_MASK (~(PGDIR_SIZE-1))
73
74
75
76
77
78 #define PTRS_PER_PTE 1024
79 #define PTRS_PER_PMD 1
80 #define PTRS_PER_PGD 1024
81
82 #define VMALLOC_START KSEG2
83 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
84
85
86
87
88
89
90
91
92
93
94
95 #define _PAGE_PRESENT (1<<0)
96 #define _PAGE_COW (1<<1)
97 #define _PAGE_READ (1<<2)
98 #define _PAGE_WRITE (1<<3)
99 #define _PAGE_ACCESSED (1<<4)
100 #define _PAGE_MODIFIED (1<<5)
101 #define _PAGE_GLOBAL (1<<6)
102 #define _PAGE_VALID (1<<7)
103 #define _PAGE_SILENT_READ (1<<7)
104 #define _PAGE_DIRTY (1<<8)
105 #define _PAGE_SILENT_WRITE (1<<8)
106 #define _CACHE_CACHABLE_NO_WA (0<<9)
107 #define _CACHE_CACHABLE_WA (1<<9)
108 #define _CACHE_UNCACHED (2<<9)
109 #define _CACHE_CACHABLE_NONCOHERENT (3<<9)
110 #define _CACHE_CACHABLE_CE (4<<9)
111 #define _CACHE_CACHABLE_COW (5<<9)
112 #define _CACHE_CACHABLE_CUW (6<<9)
113 #define _CACHE_CACHABLE_ACCELERATED (7<<9)
114 #define _CACHE_MASK (7<<9)
115
116 #define __READABLE (_PAGE_READ|_PAGE_SILENT_READ|_PAGE_ACCESSED)
117 #define __WRITEABLE (_PAGE_WRITE|_PAGE_SILENT_WRITE|_PAGE_MODIFIED)
118
119 #define _PAGE_TABLE (_PAGE_PRESENT | __READABLE | __WRITEABLE | \
120 _PAGE_DIRTY | _CACHE_UNCACHED)
121 #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _CACHE_MASK)
122
123 #define PAGE_NONE __pgprot(_PAGE_PRESENT | __READABLE | _CACHE_UNCACHED)
124 #define PAGE_SHARED __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_WRITE | \
125 _PAGE_ACCESSED | _CACHE_CACHABLE_NONCOHERENT)
126 #define PAGE_COPY __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_COW | \
127 _CACHE_CACHABLE_NONCOHERENT)
128 #define PAGE_READONLY __pgprot(_PAGE_PRESENT | __READABLE | \
129 _CACHE_CACHABLE_NONCOHERENT)
130 #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
131 _CACHE_CACHABLE_NONCOHERENT)
132
133
134
135
136
137
138 #define __P000 PAGE_NONE
139 #define __P001 PAGE_READONLY
140 #define __P010 PAGE_COPY
141 #define __P011 PAGE_COPY
142 #define __P100 PAGE_READONLY
143 #define __P101 PAGE_READONLY
144 #define __P110 PAGE_COPY
145 #define __P111 PAGE_COPY
146
147 #define __S000 PAGE_NONE
148 #define __S001 PAGE_READONLY
149 #define __S010 PAGE_SHARED
150 #define __S011 PAGE_SHARED
151 #define __S100 PAGE_READONLY
152 #define __S101 PAGE_READONLY
153 #define __S110 PAGE_SHARED
154 #define __S111 PAGE_SHARED
155
156 #if !defined (__LANGUAGE_ASSEMBLY__)
157
158
159 extern unsigned long pg0[1024];
160
161
162
163
164
165
166
167
168 extern pte_t __bad_page(void);
169 extern pte_t * __bad_pagetable(void);
170
171 extern unsigned long __zero_page(void);
172
173 #define BAD_PAGETABLE __bad_pagetable()
174 #define BAD_PAGE __bad_page()
175 #define ZERO_PAGE __zero_page()
176
177
178 #define BITS_PER_PTR (8*sizeof(unsigned long))
179
180
181 #define PTR_MASK (~(sizeof(void*)-1))
182
183
184
185
186 #if __mips == 3
187 #define SIZEOF_PTR_LOG2 3
188 #else
189 #define SIZEOF_PTR_LOG2 2
190 #endif
191
192
193 #define PAGE_PTR(address) \
194 ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
195
196
197 #define SET_PAGE_DIR(tsk,pgdir) \
198 do { \
199 (tsk)->tss.pg_dir = ((unsigned long) (pgdir)) - PT_OFFSET; \
200 if ((tsk) == current) \
201 { \
202 void load_pgd(unsigned long pg_dir); \
203 \
204 load_pgd((tsk)->tss.pg_dir); \
205 } \
206 } while (0)
207
208 extern unsigned long high_memory;
209 extern pmd_t invalid_pte_table[PAGE_SIZE/sizeof(pmd_t)];
210
211
212
213
214
215 extern inline unsigned long pte_page(pte_t pte)
216 { return PAGE_OFFSET + (pte_val(pte) & PAGE_MASK); }
217
218 extern inline unsigned long pmd_page(pmd_t pmd)
219 { return PAGE_OFFSET + (pmd_val(pmd) & PAGE_MASK); }
220
221 extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
222 { pmd_val(*pmdp) = _PAGE_TABLE | ((unsigned long) ptep - PT_OFFSET); }
223
224 extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
225 extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
226 extern inline int pte_inuse(pte_t *ptep) { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
227 extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; }
228 extern inline void pte_reuse(pte_t * ptep)
229 {
230 if (!mem_map[MAP_NR(ptep)].reserved)
231 mem_map[MAP_NR(ptep)].count++;
232 }
233
234
235
236
237 extern inline int pmd_none(pmd_t pmd) { return (pmd_val(pmd) & PAGE_MASK) == ((unsigned long) invalid_pte_table - PAGE_OFFSET); }
238
239 extern inline int pmd_bad(pmd_t pmd)
240 {
241 return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE ||
242 pmd_page(pmd) > high_memory ||
243 pmd_page(pmd) < PAGE_OFFSET;
244 }
245 extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_PRESENT; }
246 extern inline int pmd_inuse(pmd_t *pmdp) { return 0; }
247 extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = ((unsigned long) invalid_pte_table - PAGE_OFFSET); }
248 extern inline void pmd_reuse(pmd_t * pmdp) { }
249
250
251
252
253
254
255 extern inline int pgd_none(pgd_t pgd) { return 0; }
256 extern inline int pgd_bad(pgd_t pgd) { return 0; }
257 extern inline int pgd_present(pgd_t pgd) { return 1; }
258 extern inline int pgd_inuse(pgd_t * pgdp) { return mem_map[MAP_NR(pgdp)].reserved; }
259 extern inline void pgd_clear(pgd_t * pgdp) { }
260
261
262
263
264
265 extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
266 extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
267 extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
268 extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
269 extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
270 extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; }
271
272 extern inline pte_t pte_wrprotect(pte_t pte)
273 {
274 pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
275 return pte;
276 }
277 extern inline pte_t pte_rdprotect(pte_t pte)
278 {
279 pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte;
280 }
281 extern inline pte_t pte_exprotect(pte_t pte)
282 {
283 pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte;
284 }
285 extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE); return pte; }
286 extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ|_PAGE_SILENT_WRITE); return pte; }
287 extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; }
288 extern inline pte_t pte_mkwrite(pte_t pte)
289 {
290 pte_val(pte) |= _PAGE_WRITE;
291 if (pte_val(pte) & _PAGE_MODIFIED)
292 pte_val(pte) |= _PAGE_SILENT_WRITE;
293 return pte;
294 }
295 extern inline pte_t pte_mkread(pte_t pte)
296 {
297 pte_val(pte) |= _PAGE_READ;
298 if (pte_val(pte) & _PAGE_ACCESSED)
299 pte_val(pte) |= _PAGE_SILENT_READ;
300 return pte;
301 }
302 extern inline pte_t pte_mkexec(pte_t pte)
303 {
304 pte_val(pte) |= _PAGE_READ;
305 if (pte_val(pte) & _PAGE_ACCESSED)
306 pte_val(pte) |= _PAGE_SILENT_READ;
307 return pte;
308 }
309 extern inline pte_t pte_mkdirty(pte_t pte)
310 {
311 pte_val(pte) |= _PAGE_MODIFIED;
312 if (pte_val(pte) & _PAGE_WRITE)
313 pte_val(pte) |= _PAGE_SILENT_WRITE;
314 return pte;
315 }
316 extern inline pte_t pte_mkyoung(pte_t pte)
317 {
318 pte_val(pte) |= _PAGE_ACCESSED;
319 if (pte_val(pte) & _PAGE_READ)
320 {
321 pte_val(pte) |= _PAGE_SILENT_READ;
322 if ((pte_val(pte) & (_PAGE_WRITE|_PAGE_MODIFIED)) == (_PAGE_WRITE|_PAGE_MODIFIED))
323 pte_val(pte) |= _PAGE_SILENT_WRITE;
324 }
325 return pte;
326 }
327 extern inline pte_t pte_mkcow(pte_t pte)
328 {
329 pte_val(pte) |= _PAGE_COW;
330 return pte;
331 }
332
333
334
335
336
337 extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
338 { pte_t pte; pte_val(pte) = (page - PAGE_OFFSET) | pgprot_val(pgprot); return pte; }
339
340 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
341 { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
342
343
344 extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
345 {
346 return mm->pgd + (address >> PGDIR_SHIFT);
347 }
348
349
350 extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
351 {
352 return (pmd_t *) dir;
353 }
354
355
356 extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
357 {
358 return (pte_t *) (pmd_page(*dir) + (PT_OFFSET - PAGE_OFFSET)) +
359 ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
360 }
361
362
363
364
365
366
367 extern inline void pte_free_kernel(pte_t * pte)
368 {
369 unsigned long page = (unsigned long) pte;
370
371 mem_map[MAP_NR(pte)].reserved = 0;
372 if(!page)
373 return;
374 page -= (PT_OFFSET - PAGE_OFFSET);
375 free_page(page);
376 }
377
378 extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
379 {
380 address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
381 if (pmd_none(*pmd)) {
382 unsigned long page = __get_free_page(GFP_KERNEL);
383 if (pmd_none(*pmd)) {
384 if (page) {
385 mem_map[MAP_NR(page)].reserved = 1;
386 memset((void *) page, 0, PAGE_SIZE);
387 sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
388 sync_mem();
389 page += (PT_OFFSET - PAGE_OFFSET);
390 pmd_set(pmd, (pte_t *)page);
391 return ((pte_t *)page) + address;
392 }
393 pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
394 return NULL;
395 }
396 free_page(page);
397 }
398 if (pmd_bad(*pmd)) {
399 printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
400 pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
401 return NULL;
402 }
403 return (pte_t *) (pmd_page(*pmd) + (PT_OFFSET - PAGE_OFFSET)) + address;
404 }
405
406
407
408
409
410 extern inline void pmd_free_kernel(pmd_t * pmd)
411 {
412 }
413
414 extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
415 {
416 return (pmd_t *) pgd;
417 }
418
419 extern inline void pte_free(pte_t * pte)
420 {
421 unsigned long page = (unsigned long) pte;
422
423 if(!page)
424 return;
425 page -= (PT_OFFSET - PAGE_OFFSET);
426 free_page(page);
427 }
428
429 extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
430 {
431 address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
432 if (pmd_none(*pmd)) {
433 unsigned long page = __get_free_page(GFP_KERNEL);
434 if (pmd_none(*pmd)) {
435 if (page) {
436 memset((void *) page, 0, PAGE_SIZE);
437 sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
438 sync_mem();
439 page += (PT_OFFSET - PAGE_OFFSET);
440 pmd_set(pmd, (pte_t *)page);
441 return ((pte_t *)page) + address;
442 }
443 pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
444 return NULL;
445 }
446 free_page(page);
447 }
448 if (pmd_bad(*pmd)) {
449 printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
450 pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
451 return NULL;
452 }
453 return (pte_t *) (pmd_page(*pmd) + (PT_OFFSET - PAGE_OFFSET)) + address;
454 }
455
456
457
458
459
460 extern inline void pmd_free(pmd_t * pmd)
461 {
462 }
463
464 extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
465 {
466 return (pmd_t *) pgd;
467 }
468
469 extern inline void pgd_free(pgd_t * pgd)
470 {
471 unsigned long page = (unsigned long) pgd;
472
473 if(!page)
474 return;
475 page -= (PT_OFFSET - PAGE_OFFSET);
476 free_page(page);
477 }
478
479
480
481
482 extern inline void pgd_init(unsigned long page)
483 {
484 unsigned long dummy1, dummy2;
485
486 page += (PT_OFFSET - PAGE_OFFSET);
487 #if __mips >= 3
488
489
490
491 __asm__ __volatile__(
492 ".set\tnoreorder\n\t"
493 ".set\tnoat\n\t"
494 ".set\tmips3\n\t"
495 "dsll32\t$1,%2,0\n\t"
496 "dsrl32\t%2,$1,0\n\t"
497 "or\t%2,$1\n"
498 "1:\tsd\t%2,(%0)\n\t"
499 "subu\t%1,1\n\t"
500 "bnez\t%1,1b\n\t"
501 "addiu\t%0,8\n\t"
502 ".set\tmips0\n\t"
503 ".set\tat\n\t"
504 ".set\treorder"
505 :"=r" (dummy1),
506 "=r" (dummy2)
507 :"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) |
508 _PAGE_TABLE),
509 "0" (page),
510 "1" (PAGE_SIZE/(sizeof(pmd_t)*2))
511 :"$1");
512 #else
513 __asm__ __volatile__(
514 ".set\tnoreorder\n"
515 "1:\tsw\t%2,(%0)\n\t"
516 "subu\t%1,1\n\t"
517 "bnez\t%1,1b\n\t"
518 "addiu\t%0,4\n\t"
519 ".set\treorder"
520 :"=r" (dummy1),
521 "=r" (dummy2)
522 :"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) |
523 _PAGE_TABLE),
524 "0" (page),
525 "1" (PAGE_SIZE/sizeof(pmd_t)));
526 #endif
527 }
528
529 extern inline pgd_t * pgd_alloc(void)
530 {
531 unsigned long page;
532
533 if(!(page = __get_free_page(GFP_KERNEL)))
534 return NULL;
535
536 sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
537 sync_mem();
538 pgd_init(page);
539
540 return (pgd_t *) (page + (PT_OFFSET - PAGE_OFFSET));
541 }
542
543 extern pgd_t swapper_pg_dir[1024];
544
545
546
547
548
549
550
551 extern void update_mmu_cache(struct vm_area_struct * vma,
552 unsigned long address, pte_t pte);
553
554 #if __mips >= 3
555
556 #define SWP_TYPE(entry) (((entry) >> 32) & 0xff)
557 #define SWP_OFFSET(entry) ((entry) >> 40)
558 #define SWP_ENTRY(type,offset) pte_val(mk_swap_pte((type),(offset)))
559
560 #else
561
562 #define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
563 #define SWP_OFFSET(entry) ((entry) >> 8)
564 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
565
566 #endif
567
568 #endif
569
570 #endif