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