1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#ifndef _ASM_PGTABLE_H
17#define _ASM_PGTABLE_H
18
19#include <asm/mem-layout.h>
20#include <asm/setup.h>
21#include <asm/processor.h>
22
23#ifndef __ASSEMBLY__
24#include <linux/threads.h>
25#include <linux/slab.h>
26#include <linux/list.h>
27#include <linux/spinlock.h>
28#include <linux/sched.h>
29struct vm_area_struct;
30#endif
31
32#ifndef __ASSEMBLY__
33#if defined(CONFIG_HIGHPTE)
34typedef unsigned long pte_addr_t;
35#else
36typedef pte_t *pte_addr_t;
37#endif
38#endif
39
40
41
42
43
44#ifndef CONFIG_MMU
45
46#define pgd_present(pgd) (1)
47#define pgd_none(pgd) (0)
48#define pgd_bad(pgd) (0)
49#define pgd_clear(pgdp)
50#define kern_addr_valid(addr) (1)
51#define pmd_offset(a, b) ((void *) 0)
52
53#define PAGE_NONE __pgprot(0)
54#define PAGE_SHARED __pgprot(0)
55#define PAGE_COPY __pgprot(0)
56#define PAGE_READONLY __pgprot(0)
57#define PAGE_KERNEL __pgprot(0)
58
59#define __swp_type(x) (0)
60#define __swp_offset(x) (0)
61#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
62#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
63#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
64
65#ifndef __ASSEMBLY__
66static inline int pte_file(pte_t pte) { return 0; }
67#endif
68
69#define ZERO_PAGE(vaddr) ({ BUG(); NULL; })
70
71#define swapper_pg_dir ((pgd_t *) NULL)
72
73#define pgtable_cache_init() do {} while (0)
74#define arch_enter_lazy_mmu_mode() do {} while (0)
75#define arch_leave_lazy_mmu_mode() do {} while (0)
76#define arch_enter_lazy_cpu_mode() do {} while (0)
77#define arch_leave_lazy_cpu_mode() do {} while (0)
78
79#else
80
81
82
83
84
85
86
87
88
89#ifndef __ASSEMBLY__
90extern unsigned long empty_zero_page;
91#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
92#endif
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127#define PGDIR_SHIFT 26
128#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
129#define PGDIR_MASK (~(PGDIR_SIZE - 1))
130#define PTRS_PER_PGD 64
131
132#define PUD_SHIFT 26
133#define PTRS_PER_PUD 1
134#define PUD_SIZE (1UL << PUD_SHIFT)
135#define PUD_MASK (~(PUD_SIZE - 1))
136#define PUE_SIZE 256
137
138#define PMD_SHIFT 26
139#define PMD_SIZE (1UL << PMD_SHIFT)
140#define PMD_MASK (~(PMD_SIZE - 1))
141#define PTRS_PER_PMD 1
142#define PME_SIZE 256
143
144#define __frv_PT_SIZE 256
145
146#define PTRS_PER_PTE 4096
147
148#define USER_PGDS_IN_LAST_PML4 (TASK_SIZE / PGDIR_SIZE)
149#define FIRST_USER_ADDRESS 0
150
151#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
152#define KERNEL_PGD_PTRS (PTRS_PER_PGD - USER_PGD_PTRS)
153
154#define TWOLEVEL_PGDIR_SHIFT 26
155#define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
156#define BOOT_KERNEL_PGD_PTRS (PTRS_PER_PGD - BOOT_USER_PGD_PTRS)
157
158#ifndef __ASSEMBLY__
159
160extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
161
162#define pte_ERROR(e) \
163 printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte)
164#define pmd_ERROR(e) \
165 printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
166#define pud_ERROR(e) \
167 printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pmd_val(pud_val(e)))
168#define pgd_ERROR(e) \
169 printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pmd_val(pud_val(pgd_val(e))))
170
171
172
173
174
175
176#define set_pte(pteptr, pteval) \
177do { \
178 *(pteptr) = (pteval); \
179 asm volatile("dcf %M0" :: "U"(*pteptr)); \
180} while(0)
181#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
182
183
184
185
186
187#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
188
189
190
191
192
193#define pgd_offset_k(address) pgd_offset(&init_mm, address)
194
195
196
197
198
199
200static inline int pgd_none(pgd_t pgd) { return 0; }
201static inline int pgd_bad(pgd_t pgd) { return 0; }
202static inline int pgd_present(pgd_t pgd) { return 1; }
203static inline void pgd_clear(pgd_t *pgd) { }
204
205#define pgd_populate(mm, pgd, pud) do { } while (0)
206
207
208
209
210#define set_pgd(pgdptr, pgdval) \
211do { \
212 memcpy((pgdptr), &(pgdval), sizeof(pgd_t)); \
213 asm volatile("dcf %M0" :: "U"(*(pgdptr))); \
214} while(0)
215
216static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address)
217{
218 return (pud_t *) pgd;
219}
220
221#define pgd_page(pgd) (pud_page((pud_t){ pgd }))
222#define pgd_page_vaddr(pgd) (pud_page_vaddr((pud_t){ pgd }))
223
224
225
226
227
228#define pud_alloc_one(mm, address) NULL
229#define pud_free(mm, x) do { } while (0)
230#define __pud_free_tlb(tlb, x) do { } while (0)
231
232
233
234
235
236
237static inline int pud_none(pud_t pud) { return 0; }
238static inline int pud_bad(pud_t pud) { return 0; }
239static inline int pud_present(pud_t pud) { return 1; }
240static inline void pud_clear(pud_t *pud) { }
241
242#define pud_populate(mm, pmd, pte) do { } while (0)
243
244
245
246
247
248#define set_pud(pudptr, pudval) set_pmd((pmd_t *)(pudptr), (pmd_t) { pudval })
249
250#define pud_page(pud) (pmd_page((pmd_t){ pud }))
251#define pud_page_vaddr(pud) (pmd_page_vaddr((pmd_t){ pud }))
252
253
254
255
256
257extern void __set_pmd(pmd_t *pmdptr, unsigned long __pmd);
258
259#define set_pmd(pmdptr, pmdval) \
260do { \
261 __set_pmd((pmdptr), (pmdval).ste[0]); \
262} while(0)
263
264#define __pmd_index(address) 0
265
266static inline pmd_t *pmd_offset(pud_t *dir, unsigned long address)
267{
268 return (pmd_t *) dir + __pmd_index(address);
269}
270
271#define pte_same(a, b) ((a).pte == (b).pte)
272#define pte_page(x) (mem_map + ((unsigned long)(((x).pte >> PAGE_SHIFT))))
273#define pte_none(x) (!(x).pte)
274#define pte_pfn(x) ((unsigned long)(((x).pte >> PAGE_SHIFT)))
275#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
276#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
277
278#define VMALLOC_VMADDR(x) ((unsigned long) (x))
279
280#endif
281
282
283
284
285#define _PAGE_BIT_PRESENT xAMPRx_V_BIT
286#define _PAGE_BIT_WP DAMPRx_WP_BIT
287#define _PAGE_BIT_NOCACHE xAMPRx_C_BIT
288#define _PAGE_BIT_SUPER xAMPRx_S_BIT
289#define _PAGE_BIT_ACCESSED xAMPRx_RESERVED8_BIT
290#define _PAGE_BIT_DIRTY xAMPRx_M_BIT
291#define _PAGE_BIT_NOTGLOBAL xAMPRx_NG_BIT
292
293#define _PAGE_PRESENT xAMPRx_V
294#define _PAGE_WP DAMPRx_WP
295#define _PAGE_NOCACHE xAMPRx_C
296#define _PAGE_SUPER xAMPRx_S
297#define _PAGE_ACCESSED xAMPRx_RESERVED8
298#define _PAGE_DIRTY xAMPRx_M
299#define _PAGE_NOTGLOBAL xAMPRx_NG
300
301#define _PAGE_RESERVED_MASK (xAMPRx_RESERVED8 | xAMPRx_RESERVED13)
302
303#define _PAGE_FILE 0x002
304#define _PAGE_PROTNONE 0x000
305
306#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
307
308#define __PGPROT_BASE \
309 (_PAGE_PRESENT | xAMPRx_SS_16Kb | xAMPRx_D | _PAGE_NOTGLOBAL | _PAGE_ACCESSED)
310
311#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
312#define PAGE_SHARED __pgprot(__PGPROT_BASE)
313#define PAGE_COPY __pgprot(__PGPROT_BASE | _PAGE_WP)
314#define PAGE_READONLY __pgprot(__PGPROT_BASE | _PAGE_WP)
315
316#define __PAGE_KERNEL (__PGPROT_BASE | _PAGE_SUPER | _PAGE_DIRTY)
317#define __PAGE_KERNEL_NOCACHE (__PGPROT_BASE | _PAGE_SUPER | _PAGE_DIRTY | _PAGE_NOCACHE)
318#define __PAGE_KERNEL_RO (__PGPROT_BASE | _PAGE_SUPER | _PAGE_DIRTY | _PAGE_WP)
319
320#define MAKE_GLOBAL(x) __pgprot((x) & ~_PAGE_NOTGLOBAL)
321
322#define PAGE_KERNEL MAKE_GLOBAL(__PAGE_KERNEL)
323#define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO)
324#define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
325
326#define _PAGE_TABLE (_PAGE_PRESENT | xAMPRx_SS_16Kb)
327
328#ifndef __ASSEMBLY__
329
330
331
332
333
334
335#define __P000 PAGE_NONE
336#define __P001 PAGE_READONLY
337#define __P010 PAGE_COPY
338#define __P011 PAGE_COPY
339#define __P100 PAGE_READONLY
340#define __P101 PAGE_READONLY
341#define __P110 PAGE_COPY
342#define __P111 PAGE_COPY
343
344#define __S000 PAGE_NONE
345#define __S001 PAGE_READONLY
346#define __S010 PAGE_SHARED
347#define __S011 PAGE_SHARED
348#define __S100 PAGE_READONLY
349#define __S101 PAGE_READONLY
350#define __S110 PAGE_SHARED
351#define __S111 PAGE_SHARED
352
353
354
355
356
357#undef TEST_ACCESS_OK
358
359#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
360#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
361
362#define pmd_none(x) (!pmd_val(x))
363#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
364#define pmd_bad(x) (pmd_val(x) & xAMPRx_SS)
365#define pmd_clear(xp) do { __set_pmd(xp, 0); } while(0)
366
367#define pmd_page_vaddr(pmd) \
368 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
369
370#ifndef CONFIG_DISCONTIGMEM
371#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
372#endif
373
374#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
375
376
377
378
379
380static inline int pte_dirty(pte_t pte) { return (pte).pte & _PAGE_DIRTY; }
381static inline int pte_young(pte_t pte) { return (pte).pte & _PAGE_ACCESSED; }
382static inline int pte_write(pte_t pte) { return !((pte).pte & _PAGE_WP); }
383static inline int pte_special(pte_t pte) { return 0; }
384
385static inline pte_t pte_mkclean(pte_t pte) { (pte).pte &= ~_PAGE_DIRTY; return pte; }
386static inline pte_t pte_mkold(pte_t pte) { (pte).pte &= ~_PAGE_ACCESSED; return pte; }
387static inline pte_t pte_wrprotect(pte_t pte) { (pte).pte |= _PAGE_WP; return pte; }
388static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte |= _PAGE_DIRTY; return pte; }
389static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte |= _PAGE_ACCESSED; return pte; }
390static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte &= ~_PAGE_WP; return pte; }
391static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
392
393static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
394{
395 int i = test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
396 asm volatile("dcf %M0" :: "U"(*ptep));
397 return i;
398}
399
400static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
401{
402 unsigned long x = xchg(&ptep->pte, 0);
403 asm volatile("dcf %M0" :: "U"(*ptep));
404 return __pte(x);
405}
406
407static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
408{
409 set_bit(_PAGE_BIT_WP, ptep);
410 asm volatile("dcf %M0" :: "U"(*ptep));
411}
412
413
414
415
416#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NOCACHE))
417
418
419
420
421
422
423#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
424#define mk_pte_huge(entry) ((entry).pte_low |= _PAGE_PRESENT | _PAGE_PSE)
425
426
427#define mk_pte_phys(physpage, pgprot) pfn_pte((physpage) >> PAGE_SHIFT, pgprot)
428
429static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
430{
431 pte.pte &= _PAGE_CHG_MASK;
432 pte.pte |= pgprot_val(newprot);
433 return pte;
434}
435
436
437#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
438#define pgd_index_k(addr) pgd_index(addr)
439
440
441#define __pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
442
443
444
445
446
447
448
449#define pte_index(address) \
450 (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
451#define pte_offset_kernel(dir, address) \
452 ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address))
453
454#if defined(CONFIG_HIGHPTE)
455#define pte_offset_map(dir, address) \
456 ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
457#define pte_offset_map_nested(dir, address) \
458 ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
459#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
460#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
461#else
462#define pte_offset_map(dir, address) \
463 ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
464#define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address))
465#define pte_unmap(pte) do { } while (0)
466#define pte_unmap_nested(pte) do { } while (0)
467#endif
468
469
470
471
472
473
474
475
476
477
478#define __swp_type(x) (((x).val >> 2) & 0x1f)
479#define __swp_offset(x) ((x).val >> 8)
480#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 8) })
481#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte })
482#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
483
484static inline int pte_file(pte_t pte)
485{
486 return pte.pte & _PAGE_FILE;
487}
488
489#define PTE_FILE_MAX_BITS 29
490
491#define pte_to_pgoff(PTE) ((PTE).pte >> 2)
492#define pgoff_to_pte(off) __pte((off) << 2 | _PAGE_FILE)
493
494
495#define PageSkip(page) (0)
496#define kern_addr_valid(addr) (1)
497
498#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
499 remap_pfn_range(vma, vaddr, pfn, size, prot)
500
501#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
502#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
503#define __HAVE_ARCH_PTEP_SET_WRPROTECT
504#define __HAVE_ARCH_PTE_SAME
505#include <asm-generic/pgtable.h>
506
507
508
509
510static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
511{
512 struct mm_struct *mm;
513 unsigned long ampr;
514
515 mm = current->mm;
516 if (mm) {
517 pgd_t *pge = pgd_offset(mm, address);
518 pud_t *pue = pud_offset(pge, address);
519 pmd_t *pme = pmd_offset(pue, address);
520
521 ampr = pme->ste[0] & 0xffffff00;
522 ampr |= xAMPRx_L | xAMPRx_SS_16Kb | xAMPRx_S | xAMPRx_C |
523 xAMPRx_V;
524 } else {
525 address = ULONG_MAX;
526 ampr = 0;
527 }
528
529 asm volatile("movgs %0,scr0\n"
530 "movgs %0,scr1\n"
531 "movgs %1,dampr4\n"
532 "movgs %1,dampr5\n"
533 :
534 : "r"(address), "r"(ampr)
535 );
536}
537
538#ifdef CONFIG_PROC_FS
539extern char *proc_pid_status_frv_cxnr(struct mm_struct *mm, char *buffer);
540#endif
541
542extern void __init pgtable_cache_init(void);
543
544#endif
545#endif
546
547#ifndef __ASSEMBLY__
548extern void __init paging_init(void);
549#endif
550
551#endif
552