1 /*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1994 - 1999 by Ralf Baechle at alii
7 * Copyright (C) 1999 Silicon Graphics, Inc.
8 */
9 #ifndef _ASM_PGTABLE_H
10 #define _ASM_PGTABLE_H
11
12 #include <asm/addrspace.h>
13 #include <asm/page.h>
14
15 #ifndef _LANGUAGE_ASSEMBLY
16
17 #include <linux/linkage.h>
18 #include <asm/cachectl.h>
19 #include <linux/config.h>
20
21 /* Cache flushing:
22 *
23 * - flush_cache_all() flushes entire cache
24 * - flush_cache_mm(mm) flushes the specified mm context's cache lines
25 * - flush_cache_page(mm, vmaddr) flushes a single page
26 * - flush_cache_range(mm, start, end) flushes a range of pages
27 * - flush_page_to_ram(page) write back kernel page to ram
28 */
29 extern void (*_flush_cache_all)(void);
30 extern void (*_flush_cache_mm)(struct mm_struct *mm);
31 extern void (*_flush_cache_range)(struct mm_struct *mm, unsigned long start,
32 unsigned long end);
33 extern void (*_flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
34 extern void (*_flush_cache_sigtramp)(unsigned long addr);
35 extern void (*_flush_page_to_ram)(struct page * page);
36
37 #define flush_dcache_page(page) do { } while (0)
38
39 #define flush_cache_all() _flush_cache_all()
40 #define flush_cache_mm(mm) _flush_cache_mm(mm)
41 #define flush_cache_range(mm,start,end) _flush_cache_range(mm,start,end)
42 #define flush_cache_page(vma,page) _flush_cache_page(vma, page)
43 #define flush_cache_sigtramp(addr) _flush_cache_sigtramp(addr)
44 #define flush_page_to_ram(page) _flush_page_to_ram(page)
45
46 #define flush_icache_range(start, end) flush_cache_all()
47
48 #define flush_icache_page(vma, page) \
49 do { \
50 unsigned long addr; \
51 addr = (unsigned long) page_address(page); \
52 _flush_cache_page(vma, addr); \
53 } while (0)
54
55
56 /*
57 * - add_wired_entry() add a fixed TLB entry, and move wired register
58 */
59 extern void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
60 unsigned long entryhi, unsigned long pagemask);
61
62
63 /* Basically we have the same two-level (which is the logical three level
64 * Linux page table layout folded) page tables as the i386. Some day
65 * when we have proper page coloring support we can have a 1% quicker
66 * tlb refill handling mechanism, but for now it is a bit slower but
67 * works even with the cache aliasing problem the R4k and above have.
68 */
69
70 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
71
72 /* PMD_SHIFT determines the size of the area a second-level page table can map */
73 #define PMD_SHIFT 22
74 #define PMD_SIZE (1UL << PMD_SHIFT)
75 #define PMD_MASK (~(PMD_SIZE-1))
76
77 /* PGDIR_SHIFT determines what a third-level page table entry can map */
78 #define PGDIR_SHIFT 22
79 #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
80 #define PGDIR_MASK (~(PGDIR_SIZE-1))
81
82 /* Entries per page directory level: we use two-level, so
83 * we don't really have any PMD directory physically.
84 */
85 #define PTRS_PER_PTE 1024
86 #define PTRS_PER_PMD 1
87 #define PTRS_PER_PGD 1024
88 #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
89 #define FIRST_USER_PGD_NR 0
90
91 #define VMALLOC_START KSEG2
92 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
93 #define VMALLOC_END KSEG3
94
95 /* Note that we shift the lower 32bits of each EntryLo[01] entry
96 * 6 bits to the left. That way we can convert the PFN into the
97 * physical address by a single 'and' operation and gain 6 additional
98 * bits for storing information which isn't present in a normal
99 * MIPS page table.
100 *
101 * Similar to the Alpha port, we need to keep track of the ref
102 * and mod bits in software. We have a software "yeah you can read
103 * from this page" bit, and a hardware one which actually lets the
104 * process read from the page. On the same token we have a software
105 * writable bit and the real hardware one which actually lets the
106 * process write to the page, this keeps a mod bit via the hardware
107 * dirty bit.
108 *
109 * Certain revisions of the R4000 and R5000 have a bug where if a
110 * certain sequence occurs in the last 3 instructions of an executable
111 * page, and the following page is not mapped, the cpu can do
112 * unpredictable things. The code (when it is written) to deal with
113 * this problem will be in the update_mmu_cache() code for the r4k.
114 */
115 #define _PAGE_PRESENT (1<<0) /* implemented in software */
116 #define _PAGE_READ (1<<1) /* implemented in software */
117 #define _PAGE_WRITE (1<<2) /* implemented in software */
118 #define _PAGE_ACCESSED (1<<3) /* implemented in software */
119 #define _PAGE_MODIFIED (1<<4) /* implemented in software */
120
121 #if defined(CONFIG_CPU_R3000)
122
123 #define _PAGE_GLOBAL (1<<8)
124 #define _PAGE_VALID (1<<9)
125 #define _PAGE_SILENT_READ (1<<9) /* synonym */
126 #define _PAGE_DIRTY (1<<10) /* The MIPS dirty bit */
127 #define _PAGE_SILENT_WRITE (1<<10)
128 #define _CACHE_UNCACHED (1<<11) /* R4[0246]00 */
129 #define _CACHE_MASK (1<<11)
130 #define _CACHE_CACHABLE_NONCOHERENT 0
131
132 #else
133
134 #define _PAGE_R4KBUG (1<<5) /* workaround for r4k bug */
135 #define _PAGE_GLOBAL (1<<6)
136 #define _PAGE_VALID (1<<7)
137 #define _PAGE_SILENT_READ (1<<7) /* synonym */
138 #define _PAGE_DIRTY (1<<8) /* The MIPS dirty bit */
139 #define _PAGE_SILENT_WRITE (1<<8)
140 #define _CACHE_CACHABLE_NO_WA (0<<9) /* R4600 only */
141 #define _CACHE_CACHABLE_WA (1<<9) /* R4600 only */
142 #define _CACHE_UNCACHED (2<<9) /* R4[0246]00 */
143 #define _CACHE_CACHABLE_NONCOHERENT (3<<9) /* R4[0246]00 */
144 #define _CACHE_CACHABLE_CE (4<<9) /* R4[04]00 only */
145 #define _CACHE_CACHABLE_COW (5<<9) /* R4[04]00 only */
146 #define _CACHE_CACHABLE_CUW (6<<9) /* R4[04]00 only */
147 #define _CACHE_CACHABLE_ACCELERATED (7<<9) /* R10000 only */
148 #define _CACHE_MASK (7<<9)
149
150 #endif
151
152 #define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
153 #define __WRITEABLE (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
154
155 #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | _CACHE_MASK)
156
157 #define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
158 #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
159 _CACHE_CACHABLE_NONCOHERENT)
160 #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | \
161 _CACHE_CACHABLE_NONCOHERENT)
162 #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | \
163 _CACHE_CACHABLE_NONCOHERENT)
164 #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
165 _CACHE_CACHABLE_NONCOHERENT)
166 #define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
167 _CACHE_UNCACHED)
168 #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
169 _CACHE_UNCACHED)
170
171 /*
172 * MIPS can't do page protection for execute, and considers that the same like
173 * read. Also, write permissions imply read permissions. This is the closest
174 * we can get by reasonable means..
175 */
176 #define __P000 PAGE_NONE
177 #define __P001 PAGE_READONLY
178 #define __P010 PAGE_COPY
179 #define __P011 PAGE_COPY
180 #define __P100 PAGE_READONLY
181 #define __P101 PAGE_READONLY
182 #define __P110 PAGE_COPY
183 #define __P111 PAGE_COPY
184
185 #define __S000 PAGE_NONE
186 #define __S001 PAGE_READONLY
187 #define __S010 PAGE_SHARED
188 #define __S011 PAGE_SHARED
189 #define __S100 PAGE_READONLY
190 #define __S101 PAGE_READONLY
191 #define __S110 PAGE_SHARED
192 #define __S111 PAGE_SHARED
193
194 #if !defined (_LANGUAGE_ASSEMBLY)
195
196 #define pte_ERROR(e) \
197 printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
198 #define pmd_ERROR(e) \
199 printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
200 #define pgd_ERROR(e) \
201 printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
202
203 /*
204 * BAD_PAGETABLE is used when we need a bogus page-table, while
205 * BAD_PAGE is used for a bogus page.
206 *
207 * ZERO_PAGE is a global shared page that is always zero: used
208 * for zero-mapped memory areas etc..
209 */
210 extern pte_t __bad_page(void);
211 extern pte_t *__bad_pagetable(void);
212
213 extern unsigned long empty_zero_page;
214 extern unsigned long zero_page_mask;
215
216 #define BAD_PAGETABLE __bad_pagetable()
217 #define BAD_PAGE __bad_page()
218 #define ZERO_PAGE(vaddr) \
219 (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
220
221 /* number of bits that fit into a memory pointer */
222 #define BITS_PER_PTR (8*sizeof(unsigned long))
223
224 /* to align the pointer to a pointer address */
225 #define PTR_MASK (~(sizeof(void*)-1))
226
227 /*
228 * sizeof(void*) == (1 << SIZEOF_PTR_LOG2)
229 */
230 #define SIZEOF_PTR_LOG2 2
231
232 /* to find an entry in a page-table */
233 #define PAGE_PTR(address) \
234 ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
235
236 extern void load_pgd(unsigned long pg_dir);
237
238 extern pmd_t invalid_pte_table[PAGE_SIZE/sizeof(pmd_t)];
239
240 /*
241 * Conversion functions: convert a page and protection to a page entry,
242 * and a page entry and page directory to the page they refer to.
243 */
244 extern inline unsigned long pmd_page(pmd_t pmd)
245 {
246 return pmd_val(pmd);
247 }
248
249 extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
250 {
251 pmd_val(*pmdp) = (((unsigned long) ptep) & PAGE_MASK);
252 }
253
254 extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
255 extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
256
257 /* Certain architectures need to do special things when pte's
258 * within a page table are directly modified. Thus, the following
259 * hook is made available.
260 */
261 extern inline void set_pte(pte_t *ptep, pte_t pteval)
262 {
263 *ptep = pteval;
264 }
265
266 extern inline void pte_clear(pte_t *ptep)
267 {
268 set_pte(ptep, __pte(0));
269 }
270
271 /*
272 * Empty pgd/pmd entries point to the invalid_pte_table.
273 */
274 extern inline int pmd_none(pmd_t pmd)
275 {
276 return pmd_val(pmd) == (unsigned long) invalid_pte_table;
277 }
278
279 extern inline int pmd_bad(pmd_t pmd)
280 {
281 return ((pmd_page(pmd) > (unsigned long) high_memory) ||
282 (pmd_page(pmd) < PAGE_OFFSET));
283 }
284
285 extern inline int pmd_present(pmd_t pmd)
286 {
287 return pmd_val(pmd);
288 }
289
290 extern inline void pmd_clear(pmd_t *pmdp)
291 {
292 pmd_val(*pmdp) = ((unsigned long) invalid_pte_table);
293 }
294
295 /*
296 * The "pgd_xxx()" functions here are trivial for a folded two-level
297 * setup: the pgd is never bad, and a pmd always exists (as it's folded
298 * into the pgd entry)
299 */
300 extern inline int pgd_none(pgd_t pgd) { return 0; }
301 extern inline int pgd_bad(pgd_t pgd) { return 0; }
302 extern inline int pgd_present(pgd_t pgd) { return 1; }
303 extern inline void pgd_clear(pgd_t *pgdp) { }
304
305 /*
306 * Permanent address of a page. On MIPS64 we never have highmem, so this
307 * is simple.
308 */
309 #define page_address(page) ((page)->virtual)
310 #define pte_page(x) (mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
311
312 /*
313 * The following only work if pte_present() is true.
314 * Undefined behaviour if not..
315 */
316 extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
317 extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
318 extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
319 extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
320
321 extern inline pte_t pte_wrprotect(pte_t pte)
322 {
323 pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
324 return pte;
325 }
326
327 extern inline pte_t pte_rdprotect(pte_t pte)
328 {
329 pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
330 return pte;
331 }
332
333 extern inline pte_t pte_mkclean(pte_t pte)
334 {
335 pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
336 return pte;
337 }
338
339 extern inline pte_t pte_mkold(pte_t pte)
340 {
341 pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
342 return pte;
343 }
344
345 extern inline pte_t pte_mkwrite(pte_t pte)
346 {
347 pte_val(pte) |= _PAGE_WRITE;
348 if (pte_val(pte) & _PAGE_MODIFIED)
349 pte_val(pte) |= _PAGE_SILENT_WRITE;
350 return pte;
351 }
352
353 extern inline pte_t pte_mkread(pte_t pte)
354 {
355 pte_val(pte) |= _PAGE_READ;
356 if (pte_val(pte) & _PAGE_ACCESSED)
357 pte_val(pte) |= _PAGE_SILENT_READ;
358 return pte;
359 }
360
361 extern inline pte_t pte_mkdirty(pte_t pte)
362 {
363 pte_val(pte) |= _PAGE_MODIFIED;
364 if (pte_val(pte) & _PAGE_WRITE)
365 pte_val(pte) |= _PAGE_SILENT_WRITE;
366 return pte;
367 }
368
369 extern inline pte_t pte_mkyoung(pte_t pte)
370 {
371 pte_val(pte) |= _PAGE_ACCESSED;
372 if (pte_val(pte) & _PAGE_READ)
373 pte_val(pte) |= _PAGE_SILENT_READ;
374 return pte;
375 }
376
377 /*
378 * Conversion functions: convert a page and protection to a page entry,
379 * and a page entry and page directory to the page they refer to.
380 */
381 #define mk_pte(page, pgprot) \
382 ({ \
383 pte_t __pte; \
384 \
385 pte_val(__pte) = ((unsigned long)(page - mem_map) << PAGE_SHIFT) | \
386 pgprot_val(pgprot); \
387 \
388 __pte; \
389 })
390
391 extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
392 {
393 return __pte(((physpage & PAGE_MASK) - PAGE_OFFSET) | pgprot_val(pgprot));
394 }
395
396 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
397 {
398 return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
399 }
400
401 #define page_pte(page) page_pte_prot(page, __pgprot(0))
402
403 /* to find an entry in a kernel page-table-directory */
404 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
405
406 #define pgd_index(address) ((address) >> PGDIR_SHIFT)
407
408 /* to find an entry in a page-table-directory */
409 extern inline pgd_t *pgd_offset(struct mm_struct *mm, unsigned long address)
410 {
411 return mm->pgd + pgd_index(address);
412 }
413
414 /* Find an entry in the second-level page table.. */
415 extern inline pmd_t *pmd_offset(pgd_t *dir, unsigned long address)
416 {
417 return (pmd_t *) dir;
418 }
419
420 /* Find an entry in the third-level page table.. */
421 extern inline pte_t *pte_offset(pmd_t * dir, unsigned long address)
422 {
423 return (pte_t *) (pmd_page(*dir)) +
424 ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
425 }
426
427 /*
428 * Initialize new page directory with pointers to invalid ptes
429 */
430 extern void pgd_init(unsigned long page);
431
432 extern void __bad_pte(pmd_t *pmd);
433 extern void __bad_pte_kernel(pmd_t *pmd);
434
435 #define pte_free_kernel(pte) free_pte_fast(pte)
436 #define pte_free(pte) free_pte_fast(pte)
437 #define pgd_free(pgd) free_pgd_fast(pgd)
438 #define pgd_alloc() get_pgd_fast()
439
440 extern int do_check_pgt_cache(int, int);
441
442 extern pgd_t swapper_pg_dir[1024];
443 extern void paging_init(void);
444
445 extern void update_mmu_cache(struct vm_area_struct *vma,
446 unsigned long address, pte_t pte);
447
448 #define SWP_TYPE(x) (((x).val >> 1) & 0x3f)
449 #define SWP_OFFSET(x) ((x).val >> 8)
450 #define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
451 #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
452 #define swp_entry_to_pte(x) ((pte_t) { (x).val })
453
454
455 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
456 #define PageSkip(page) (0)
457 #define kern_addr_valid(addr) (1)
458
459 /* TLB operations. */
460 extern inline void tlb_probe(void)
461 {
462 __asm__ __volatile__(
463 ".set push\n\t"
464 ".set reorder\n\t"
465 "tlbp\n\t"
466 ".set pop");
467 }
468
469 extern inline void tlb_read(void)
470 {
471 __asm__ __volatile__(
472 ".set push\n\t"
473 ".set reorder\n\t"
474 "tlbr\n\t"
475 ".set pop");
476 }
477
478 extern inline void tlb_write_indexed(void)
479 {
480 __asm__ __volatile__(
481 ".set push\n\t"
482 ".set reorder\n\t"
483 "tlbwi\n\t"
484 ".set pop");
485 }
486
487 extern inline void tlb_write_random(void)
488 {
489 __asm__ __volatile__(
490 ".set push\n\t"
491 ".set reorder\n\t"
492 "tlbwr\n\t"
493 ".set pop");
494 }
495
496 /* Dealing with various CP0 mmu/cache related registers. */
497
498 /* CP0_PAGEMASK register */
499 extern inline unsigned long get_pagemask(void)
500 {
501 unsigned long val;
502
503 __asm__ __volatile__(
504 ".set push\n\t"
505 ".set reorder\n\t"
506 "mfc0 %0, $5\n\t"
507 ".set pop"
508 : "=r" (val));
509 return val;
510 }
511
512 extern inline void set_pagemask(unsigned long val)
513 {
514 __asm__ __volatile__(
515 ".set push\n\t"
516 ".set reorder\n\t"
517 "mtc0 %0, $5\n\t"
518 ".set pop"
519 : : "r" (val));
520 }
521
522 /* CP0_ENTRYLO0 and CP0_ENTRYLO1 registers */
523 extern inline unsigned long get_entrylo0(void)
524 {
525 unsigned long val;
526
527 __asm__ __volatile__(
528 ".set push\n\t"
529 ".set reorder\n\t"
530 "mfc0 %0, $2\n\t"
531 ".set pop"
532 : "=r" (val));
533 return val;
534 }
535
536 extern inline void set_entrylo0(unsigned long val)
537 {
538 __asm__ __volatile__(
539 ".set push\n\t"
540 ".set reorder\n\t"
541 "mtc0 %0, $2\n\t"
542 ".set pop"
543 : : "r" (val));
544 }
545
546 extern inline unsigned long get_entrylo1(void)
547 {
548 unsigned long val;
549
550 __asm__ __volatile__(
551 ".set push\n\t"
552 ".set reorder\n\t"
553 "mfc0 %0, $3\n\t"
554 ".set pop" : "=r" (val));
555
556 return val;
557 }
558
559 extern inline void set_entrylo1(unsigned long val)
560 {
561 __asm__ __volatile__(
562 ".set push\n\t"
563 ".set reorder\n\t"
564 "mtc0 %0, $3\n\t"
565 ".set pop"
566 : : "r" (val));
567 }
568
569 /* CP0_ENTRYHI register */
570 extern inline unsigned long get_entryhi(void)
571 {
572 unsigned long val;
573
574 __asm__ __volatile__(
575 ".set push\n\t"
576 ".set reorder\n\t"
577 "mfc0 %0, $10\n\t"
578 ".set pop"
579 : "=r" (val));
580
581 return val;
582 }
583
584 extern inline void set_entryhi(unsigned long val)
585 {
586 __asm__ __volatile__(
587 ".set push\n\t"
588 ".set reorder\n\t"
589 "mtc0 %0, $10\n\t"
590 ".set pop"
591 : : "r" (val));
592 }
593
594 /* CP0_INDEX register */
595 extern inline unsigned long get_index(void)
596 {
597 unsigned long val;
598
599 __asm__ __volatile__(
600 ".set push\n\t"
601 ".set reorder\n\t"
602 "mfc0 %0, $0\n\t"
603 ".set pop"
604 : "=r" (val));
605 return val;
606 }
607
608 extern inline void set_index(unsigned long val)
609 {
610 __asm__ __volatile__(
611 ".set push\n\t"
612 ".set reorder\n\t"
613 "mtc0 %0, $0\n\t"
614 ".set pop"
615 : : "r" (val));
616 }
617
618 /* CP0_WIRED register */
619 extern inline unsigned long get_wired(void)
620 {
621 unsigned long val;
622
623 __asm__ __volatile__(
624 ".set push\n\t"
625 ".set reorder\n\t"
626 "mfc0 %0, $6\n\t"
627 ".set pop"
628 : "=r" (val));
629 return val;
630 }
631
632 extern inline void set_wired(unsigned long val)
633 {
634 __asm__ __volatile__(
635 ".set push\n\t"
636 ".set reorder\n\t"
637 "mtc0 %0, $6\n\t"
638 ".set pop"
639 : : "r" (val));
640 }
641
642 /* CP0_TAGLO and CP0_TAGHI registers */
643 extern inline unsigned long get_taglo(void)
644 {
645 unsigned long val;
646
647 __asm__ __volatile__(
648 ".set push\n\t"
649 ".set reorder\n\t"
650 "mfc0 %0, $28\n\t"
651 ".set pop"
652 : "=r" (val));
653 return val;
654 }
655
656 extern inline void set_taglo(unsigned long val)
657 {
658 __asm__ __volatile__(
659 ".set push\n\t"
660 ".set reorder\n\t"
661 "mtc0 %0, $28\n\t"
662 ".set pop"
663 : : "r" (val));
664 }
665
666 extern inline unsigned long get_taghi(void)
667 {
668 unsigned long val;
669
670 __asm__ __volatile__(
671 ".set push\n\t"
672 ".set reorder\n\t"
673 "mfc0 %0, $29\n\t"
674 ".set pop"
675 : "=r" (val));
676 return val;
677 }
678
679 extern inline void set_taghi(unsigned long val)
680 {
681 __asm__ __volatile__(
682 ".set push\n\t"
683 ".set reorder\n\t"
684 "mtc0 %0, $29\n\t"
685 ".set pop"
686 : : "r" (val));
687 }
688
689 /* CP0_CONTEXT register */
690 extern inline unsigned long get_context(void)
691 {
692 unsigned long val;
693
694 __asm__ __volatile__(
695 ".set push\n\t"
696 ".set reorder\n\t"
697 "mfc0 %0, $4\n\t"
698 ".set pop"
699 : "=r" (val));
700
701 return val;
702 }
703
704 extern inline void set_context(unsigned long val)
705 {
706 __asm__ __volatile__(
707 ".set push\n\t"
708 ".set reorder\n\t"
709 "mtc0 %0, $4\n\t"
710 ".set pop"
711 : : "r" (val));
712 }
713
714 #include <asm-generic/pgtable.h>
715
716 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
717
718 #define io_remap_page_range remap_page_range
719
720 #endif /* _ASM_PGTABLE_H */
721
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.