1
2
3
4
5
6
7
8
9
10
11#ifndef _XTENSA_PGTABLE_H
12#define _XTENSA_PGTABLE_H
13
14#include <asm-generic/pgtable-nopmd.h>
15#include <asm/page.h>
16
17
18
19
20
21#define USER_RING 1
22#define KERNEL_RING 0
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#define PGDIR_SHIFT 22
47#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
48#define PGDIR_MASK (~(PGDIR_SIZE-1))
49
50
51
52
53
54#define PTRS_PER_PTE 1024
55#define PTRS_PER_PTE_SHIFT 10
56#define PTRS_PER_PMD 1
57#define PTRS_PER_PGD 1024
58#define PGD_ORDER 0
59#define PMD_ORDER 0
60#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
61#define FIRST_USER_ADDRESS 0
62#define FIRST_USER_PGD_NR (FIRST_USER_ADDRESS >> PGDIR_SHIFT)
63
64
65
66
67
68
69
70#define VMALLOC_START 0xC0000000
71#define VMALLOC_END 0xC7FF0000
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89#define _PAGE_VALID (1<<0)
90#define _PAGE_WRENABLE (1<<1)
91
92
93#define _PAGE_NO_CACHE (0<<2)
94#if XCHAL_DCACHE_IS_WRITEBACK
95# define _PAGE_WRITEBACK (1<<2)
96# define _PAGE_WRITETHRU (2<<2)
97#else
98# define _PAGE_WRITEBACK (1<<2)
99# define _PAGE_WRITETHRU (1<<2)
100#endif
101#define _PAGE_NOALLOC (3<<2)
102#define _CACHE_MASK (3<<2)
103
104#define _PAGE_USER (1<<4)
105#define _PAGE_KERNEL (0<<4)
106
107
108#define _PAGE_RW (1<<6)
109#define _PAGE_DIRTY (1<<7)
110#define _PAGE_ACCESSED (1<<8)
111#define _PAGE_FILE (1<<9)
112
113#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _CACHE_MASK | _PAGE_DIRTY)
114#define _PAGE_PRESENT ( _PAGE_VALID | _PAGE_WRITEBACK | _PAGE_ACCESSED)
115
116#ifdef CONFIG_MMU
117
118# define PAGE_NONE __pgprot(_PAGE_PRESENT)
119# define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_RW)
120# define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER)
121# define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER)
122# define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_KERNEL | _PAGE_WRENABLE)
123# define PAGE_INVALID __pgprot(_PAGE_USER)
124
125# if (DCACHE_WAY_SIZE > PAGE_SIZE)
126# define PAGE_DIRECTORY __pgprot(_PAGE_VALID | _PAGE_ACCESSED | _PAGE_KERNEL)
127# else
128# define PAGE_DIRECTORY __pgprot(_PAGE_PRESENT | _PAGE_KERNEL)
129# endif
130
131#else
132
133# define PAGE_NONE __pgprot(0)
134# define PAGE_SHARED __pgprot(0)
135# define PAGE_COPY __pgprot(0)
136# define PAGE_READONLY __pgprot(0)
137# define PAGE_KERNEL __pgprot(0)
138
139#endif
140
141
142
143
144
145
146
147
148#define __P000 PAGE_NONE
149#define __P001 PAGE_READONLY
150#define __P010 PAGE_COPY
151#define __P011 PAGE_COPY
152#define __P100 PAGE_READONLY
153#define __P101 PAGE_READONLY
154#define __P110 PAGE_COPY
155#define __P111 PAGE_COPY
156
157#define __S000 PAGE_NONE
158#define __S001 PAGE_READONLY
159#define __S010 PAGE_SHARED
160#define __S011 PAGE_SHARED
161#define __S100 PAGE_READONLY
162#define __S101 PAGE_READONLY
163#define __S110 PAGE_SHARED
164#define __S111 PAGE_SHARED
165
166#ifndef __ASSEMBLY__
167
168#define pte_ERROR(e) \
169 printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
170#define pgd_ERROR(e) \
171 printk("%s:%d: bad pgd entry %08lx.\n", __FILE__, __LINE__, pgd_val(e))
172
173extern unsigned long empty_zero_page[1024];
174
175#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
176
177extern pgd_t swapper_pg_dir[PAGE_SIZE/sizeof(pgd_t)];
178
179
180
181
182#define pmd_page_vaddr(pmd) ((unsigned long)(pmd_val(pmd) & PAGE_MASK))
183#define pmd_page(pmd) virt_to_page(pmd_val(pmd))
184
185
186
187
188#define pte_none(pte) (!(pte_val(pte) ^ _PAGE_USER))
189#define pte_present(pte) (pte_val(pte) & _PAGE_VALID)
190#define pte_clear(mm,addr,ptep) \
191 do { update_pte(ptep, __pte(_PAGE_USER)); } while(0)
192
193#define pmd_none(pmd) (!pmd_val(pmd))
194#define pmd_present(pmd) (pmd_val(pmd) & PAGE_MASK)
195#define pmd_clear(pmdp) do { set_pmd(pmdp, __pmd(0)); } while (0)
196#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK)
197
198
199
200static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
201static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
202static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
203static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
204static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
205static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~(_PAGE_RW | _PAGE_WRENABLE); return pte; }
206static inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; }
207static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
208static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
209static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; }
210static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
211static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
212static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; }
213
214
215
216
217
218#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
219#define pte_same(a,b) (pte_val(a) == pte_val(b))
220#define pte_page(x) pfn_to_page(pte_pfn(x))
221#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
222#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
223
224static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
225{
226 return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
227}
228
229
230
231
232
233
234static inline void update_pte(pte_t *ptep, pte_t pteval)
235{
236 *ptep = pteval;
237#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
238 __asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (ptep));
239#endif
240}
241
242struct mm_struct;
243
244static inline void
245set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval)
246{
247 update_pte(ptep, pteval);
248}
249
250
251static inline void
252set_pmd(pmd_t *pmdp, pmd_t pmdval)
253{
254 *pmdp = pmdval;
255#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
256 __asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
257#endif
258}
259
260struct vm_area_struct;
261
262static inline int
263ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr,
264 pte_t *ptep)
265{
266 pte_t pte = *ptep;
267 if (!pte_young(pte))
268 return 0;
269 update_pte(ptep, pte_mkold(pte));
270 return 1;
271}
272
273static inline int
274ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr,
275 pte_t *ptep)
276{
277 pte_t pte = *ptep;
278 if (!pte_dirty(pte))
279 return 0;
280 update_pte(ptep, pte_mkclean(pte));
281 return 1;
282}
283
284static inline pte_t
285ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
286{
287 pte_t pte = *ptep;
288 pte_clear(mm, addr, ptep);
289 return pte;
290}
291
292static inline void
293ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
294{
295 pte_t pte = *ptep;
296 update_pte(ptep, pte_wrprotect(pte));
297}
298
299
300#define pgd_offset_k(address) pgd_offset(&init_mm, address)
301
302
303#define pgd_offset(mm,address) ((mm)->pgd + pgd_index(address))
304
305#define pgd_index(address) ((address) >> PGDIR_SHIFT)
306
307
308#define pmd_offset(dir,address) ((pmd_t*)(dir))
309
310
311#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
312#define pte_offset_kernel(dir,addr) \
313 ((pte_t*) pmd_page_vaddr(*(dir)) + pte_index(addr))
314#define pte_offset_map(dir,addr) pte_offset_kernel((dir),(addr))
315#define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir),(addr))
316
317#define pte_unmap(pte) do { } while (0)
318#define pte_unmap_nested(pte) do { } while (0)
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359#define __swp_type(entry) (((entry).val >> 7) & 0x3f)
360#define __swp_offset(entry) ((entry).val >> 13)
361#define __swp_entry(type,offs) ((swp_entry_t) {((type) << 7) | ((offs) << 13)})
362#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
363#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
364
365#define PTE_FILE_MAX_BITS 29
366#define pte_to_pgoff(pte) (pte_val(pte) >> 3)
367#define pgoff_to_pte(off) ((pte_t) { ((off) << 3) | _PAGE_FILE })
368
369
370#endif
371
372
373#ifdef __ASSEMBLY__
374
375
376
377
378
379
380
381
382
383
384
385
386#define _PGD_INDEX(rt,rs) extui rt, rs, PGDIR_SHIFT, 32-PGDIR_SHIFT
387#define _PTE_INDEX(rt,rs) extui rt, rs, PAGE_SHIFT, PTRS_PER_PTE_SHIFT
388
389#define _PGD_OFFSET(mm,adr,tmp) l32i mm, mm, MM_PGD; \
390 _PGD_INDEX(tmp, adr); \
391 addx4 mm, tmp, mm
392
393#define _PTE_OFFSET(pmd,adr,tmp) _PTE_INDEX(tmp, adr); \
394 srli pmd, pmd, PAGE_SHIFT; \
395 slli pmd, pmd, PAGE_SHIFT; \
396 addx4 pmd, tmp, pmd
397
398#else
399
400extern void paging_init(void);
401
402#define kern_addr_valid(addr) (1)
403
404extern void update_mmu_cache(struct vm_area_struct * vma,
405 unsigned long address, pte_t pte);
406
407
408
409
410
411#define io_remap_pfn_range(vma,from,pfn,size,prot) \
412 remap_pfn_range(vma, from, pfn, size, prot)
413
414
415
416
417#define pgtable_cache_init() do { } while (0)
418
419typedef pte_t *pte_addr_t;
420
421#endif
422
423#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
424#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
425#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
426#define __HAVE_ARCH_PTEP_SET_WRPROTECT
427#define __HAVE_ARCH_PTEP_MKDIRTY
428#define __HAVE_ARCH_PTE_SAME
429
430#include <asm-generic/pgtable.h>
431
432#endif
433