aa64: finalise context switch, page fault handler and syscall
[lunaix-os.git] / lunaix-os / arch / aarch64 / includes / asm / pagetable.h
1 #ifndef __LUNAIX_ARCH_PAGETABLE_H
2 #define __LUNAIX_ARCH_PAGETABLE_H
3
4 #include <lunaix/types.h>
5 #include <lunaix/compiler.h>
6
7 #include "aa64_mmu.h"
8 #include <lunaix/bits.h>
9
10 /* ******** Page Table Manipulation ******** */
11
12 #define _PTW_LEVEL          4
13
14
15 // Note: we set VMS_SIZE = VMS_MASK as it is impossible
16 //       to express 4Gi in 32bit unsigned integer
17
18
19 #define VMS_BITS            48
20
21 #define PMS_BITS            CONFIG_AA64_OA_SIZE
22
23 #define VMS_SIZE            ( 1UL << VMS_BITS)
24 #define VMS_MASK            ( VMS_SIZE - 1 )
25 #define PMS_SIZE            ( 1UL << PMS_BITS )
26 #define PMS_MASK            ( PMS_SIZE - 1 )
27
28 #define __index(va)             ( (va) & VMS_MASK )
29 #define __vaddr(va)             \
30         ( (__index(va) ^ ((VMS_MASK + 1) >> 1)) - ((VMS_MASK + 1) >> 1) )
31 #define __paddr(pa)             ( (pa) & PMS_MASK )
32
33
34 #if    defined(CONFIG_AA64_PAGE_GRAN_4K)
35 #define _PAGE_BASE_SHIFT    12
36 #elif  defined(CONFIG_AA64_PAGE_GRAN_16K)
37 #define _PAGE_BASE_SHIFT    14
38 #elif  defined(CONFIG_AA64_PAGE_GRAN_64K)
39 #define _PAGE_BASE_SHIFT    16
40 #endif
41
42 #define _PAGE_BASE_SIZE     ( 1UL << _PAGE_BASE_SHIFT )
43 #define _PAGE_BASE_MASK     ( (_PAGE_BASE_SIZE - 1) & VMS_MASK )
44
45 #define _PAGE_LEVEL_SHIFT   9
46 #define _PAGE_LEVEL_SIZE    ( 1UL << _PAGE_LEVEL_SHIFT )
47 #define _PAGE_LEVEL_MASK    ( _PAGE_LEVEL_SIZE - 1 )
48 #define _PAGE_Ln_SIZE(n)    \
49     ( 1UL << (_PAGE_BASE_SHIFT + _PAGE_LEVEL_SHIFT * (_PTW_LEVEL - (n) - 1)) )
50
51 /* General size of a LnT huge page */
52
53 #define L0T_SIZE            _PAGE_Ln_SIZE(0)
54 #define L1T_SIZE            _PAGE_Ln_SIZE(1)
55 #define L2T_SIZE            _PAGE_Ln_SIZE(2)
56 #define L3T_SIZE            _PAGE_Ln_SIZE(3)
57 #define LFT_SIZE            _PAGE_Ln_SIZE(3)
58
59
60 struct __pte {
61     unsigned long val;
62 } align(8);
63
64 // upper attributes
65
66 #define _PTE_UXN                BITFLAG(54)
67 #define _PTE_PXN                BITFLAG(53)
68 #define _PTE_XN                 (_PTE_UXN | _PTE_PXN)
69 #define _PTE_Contig             BITFLAG(52)
70 #define _PTE_DBM                BITFLAG(51)
71
72 #ifdef _MMU_USE_OA52
73 #if  CONFIG_AA64_PAGE_GRAN_64K
74 #define __OA_HIGH_MASK          ( 0b1111 << 12 )
75 #define __OA_HEAD(pa)           ((pa) & ((1UL << 48) - 1) & ~PAGE_MASK)
76 #define __OA_TAIL(pa)           ((((pa) >> 48) & 0b1111) << 12)
77 #else
78 #define __OA_HIGH_MASK          ( 0b0011 << 8 )
79 #define __OA_HEAD(pa)           ((pa) & ((1UL << 50) - 1) & ~PAGE_MASK)
80 #define __OA_TAIL(pa)           ((((pa) >> 50) & 0b0011) << 8)
81 #endif
82 #else
83 #define __OA_HIGH_MASK          (0)
84 #define __OA_HEAD(pa)           (__paddr(pa) & ~PAGE_MASK)
85 #define __OA_TAIL(pa)           (0)
86 #endif
87
88 #define _PTE_OA(pa)             (__OA_HEAD(pa) | __OA_TAIL(pa))
89
90 // lower attributes
91
92 #define _PTE_nG                 BITFLAG(11)
93 #define _PTE_AF                 BITFLAG(10)
94
95 // AP bits: R_RNGJG
96
97 #define _PTE_AP(p, u)           ((((p) & 1) << 1 | ((u) & 1)) << 6)
98
99 // el1 rw, el0 deny all
100 #define _PTE_PRW                _PTE_AP(0 , 0)
101 // el1 rw, el0 rw
102 #define _PTE_PRWURW             _PTE_AP(0 , 1)
103 // el0 allow
104 #define _PTE_U                  _PTE_AP(0 , 1)
105 #define _PTE_nDIRTY             _PTE_AP(1 , 0)
106 // el1 ro, el0 deny all
107 #define _PTE_PRO                _PTE_AP(1 , 0) | _PTE_DBM
108 // el1 ro, el0 ro
109 #define _PTE_PROURO             _PTE_AP(1 , 1) | _PTE_DBM
110
111 #define _PTE_BLKDESC            (0b01)
112 #define _PTE_TABDESC            (0b11)
113 #define _PTE_LFTDESC            (0b11)
114 #define _PTE_VALID              (0b01)
115 #define _PTE_DESC_MASK          (0b11)
116 #define _PTE_SET_DESC(pte_val, desc)    \
117         ( ((pte_val) & ~_PTE_DESC_MASK) | ((desc) & _PTE_DESC_MASK) )
118 #define _PTE_GET_DESC(pte_val)          \
119         ( (pte_val) & _PTE_DESC_MASK )
120
121 #define __MEMGUARD               0xf0f0f0f0f0f0f0f0UL
122
123 typedef unsigned long pte_attr_t;
124 typedef unsigned long pfn_t;
125
126 // always do sign extend on x86_64
127
128
129
130 /* General mask to get page offset of a LnT huge page */
131
132 #define L0T_MASK            ( L0T_SIZE - 1 )
133 #define L1T_MASK            ( L1T_SIZE - 1 )
134 #define L2T_MASK            ( L2T_SIZE - 1 )
135 #define L3T_MASK            ( L3T_SIZE - 1 )
136 #define LFT_MASK            ( LFT_SIZE - 1 )
137
138 /* Masks to get index of a LnTE */
139
140 #define L0T_INDEX_MASK      ( VMS_MASK ^ L0T_MASK )
141 #define L1T_INDEX_MASK      ( L0T_MASK ^ L1T_MASK )
142 #define L2T_INDEX_MASK      ( L1T_MASK ^ L2T_MASK )
143 #define L3T_INDEX_MASK      ( L2T_MASK ^ L3T_MASK )
144 #define LFT_INDEX_MASK      ( L3T_MASK ^ LFT_MASK )
145
146 #define PAGE_SHIFT          _PAGE_BASE_SHIFT
147 #define PAGE_SIZE           _PAGE_BASE_SIZE
148 #define PAGE_MASK           _PAGE_BASE_MASK
149
150 #define LEVEL_SHIFT         _PAGE_LEVEL_SHIFT
151 #define LEVEL_SIZE          _PAGE_LEVEL_SIZE
152 #define LEVEL_MASK          _PAGE_LEVEL_MASK
153
154 // max PTEs number
155 #define MAX_PTEN            _PAGE_LEVEL_SIZE
156
157 // max translation level supported
158 #define MAX_LEVEL           _PTW_LEVEL
159
160 typedef struct __pte pte_t;
161
162 #define _PTE_PROT_MASK          ( ~((1UL << 50) - 1) | (PAGE_MASK & __OA_HIGH_MASK) )
163 #define _PTE_PPFN_MASK          ( ~_PTE_PROT_MASK )
164
165 #define _PAGE_BASIC             ( _PTE_VALID )
166
167 #define KERNEL_EXEC             ( _PAGE_BASIC | _PTE_PRO | _PTE_UXN )
168 #define KERNEL_DATA             ( _PAGE_BASIC | _PTE_PRW | _PTE_XN )
169 #define KERNEL_RDONLY           ( _PAGE_BASIC | _PTE_PRO | _PTE_XN )
170 #define KERNEL_ROEXEC           KERNEL_EXEC
171 #define KERNEL_PGTAB            ( _PAGE_BASIC | _PTE_TABDESC )
172
173 #define USER_EXEC               ( _PAGE_BASIC | _PTE_PROURO | _PTE_PXN )
174 #define USER_DATA               ( _PAGE_BASIC | _PTE_PRWURW | _PTE_XN )
175 #define USER_RDONLY             ( _PAGE_BASIC | _PTE_PROURO )
176 #define USER_ROEXEC             USER_EXEC
177 #define USER_PGTAB              ( _PAGE_BASIC | _PTE_TABDESC )
178
179 #define SELF_MAP                ( KERNEL_DATA | _PTE_TABDESC )
180
181 #define __mkpte_from(pte_val)   ((pte_t){ .val = (pte_val) })
182
183 #define null_pte                ( __mkpte_from(0) )
184 #define guard_pte               ( __mkpte_from(__MEMGUARD) )
185 #define pte_val(pte)            ( pte.val )
186
187
188 static inline bool
189 pte_isguardian(pte_t pte)
190 {
191     return pte.val == __MEMGUARD;
192 }
193
194 static inline pte_t
195 mkpte_prot(pte_attr_t prot)
196 {
197     pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_LFTDESC;
198     return __mkpte_from(attrs);
199 }
200
201 static inline pte_t
202 mkpte(ptr_t paddr, pte_attr_t prot)
203 {
204     pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_LFTDESC;
205     return __mkpte_from((paddr & ~_PAGE_BASE_MASK) | attrs);
206 }
207
208 static inline pte_t
209 mkpte_root(ptr_t paddr, pte_attr_t prot)
210 {
211     pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_TABDESC;
212     return __mkpte_from((paddr & ~_PAGE_BASE_MASK) | attrs);
213 }
214
215 static inline pte_t
216 mkpte_raw(unsigned long pte_val)
217 {
218     return __mkpte_from(pte_val);
219 }
220
221 static inline pte_t
222 pte_setpaddr(pte_t pte, ptr_t paddr)
223 {
224     return __mkpte_from((pte.val & _PTE_PROT_MASK) | (paddr & ~_PTE_PROT_MASK));
225 }
226
227 static inline pte_t
228 pte_setppfn(pte_t pte, pfn_t ppfn)
229 {
230     return pte_setpaddr(pte, ppfn * PAGE_SIZE);
231 }
232
233 static inline ptr_t
234 pte_paddr(pte_t pte)
235 {
236     return __paddr(pte.val) & ~_PTE_PROT_MASK;
237 }
238
239 static inline pfn_t
240 pte_ppfn(pte_t pte)
241 {
242     return pte_paddr(pte) >> _PAGE_BASE_SHIFT;
243 }
244
245 static inline pte_t
246 pte_setprot(pte_t pte, ptr_t prot)
247 {
248     return __mkpte_from((pte.val & ~_PTE_PROT_MASK) | (prot & _PTE_PROT_MASK));
249 }
250
251 static inline pte_attr_t
252 pte_prot(pte_t pte)
253 {
254     return (pte.val & _PTE_PROT_MASK);
255 }
256
257 static inline bool
258 pte_isnull(pte_t pte)
259 {
260     return !pte.val;
261 }
262
263 static inline pte_t
264 pte_mkhuge(pte_t pte) 
265 {
266     return __mkpte_from(_PTE_SET_DESC(pte.val, _PTE_BLKDESC));
267 }
268
269 static inline pte_t
270 pte_mkvolatile(pte_t pte) 
271 {
272     return __mkpte_from(pte.val);
273 }
274
275 static inline pte_t
276 pte_mkroot(pte_t pte) 
277 {
278     return __mkpte_from(_PTE_SET_DESC(pte.val, _PTE_TABDESC));
279 }
280
281 static inline bool
282 pte_huge(pte_t pte) 
283 {
284     return _PTE_GET_DESC(pte.val) == _PTE_BLKDESC;
285 }
286
287 static inline pte_t
288 pte_mkloaded(pte_t pte) 
289 {
290     return __mkpte_from(pte.val | _PTE_VALID);
291 }
292
293 static inline pte_t
294 pte_mkunloaded(pte_t pte) 
295 {
296     return __mkpte_from(pte.val & ~_PTE_VALID);
297 }
298
299 static inline bool
300 pte_isloaded(pte_t pte) 
301 {
302     return !!(pte.val & _PTE_VALID);
303 }
304
305 static inline pte_t
306 pte_mkwprotect(pte_t pte) 
307 {
308     return __mkpte_from(pte.val | _PTE_PRO);
309 }
310
311 static inline pte_t
312 pte_mkwritable(pte_t pte) 
313 {
314     return __mkpte_from(pte.val & ~_PTE_PRO);
315 }
316
317 static inline bool
318 pte_iswprotect(pte_t pte) 
319 {
320     return !(pte.val & _PTE_PRO);
321 }
322
323 static inline pte_t
324 pte_mkuser(pte_t pte) 
325 {
326     return __mkpte_from(pte.val | _PTE_U);
327 }
328
329 static inline pte_t
330 pte_mkkernel(pte_t pte) 
331 {
332     return __mkpte_from(pte.val & ~_PTE_U);
333 }
334
335 static inline bool
336 pte_allow_user(pte_t pte) 
337 {
338     return !!(pte.val & _PTE_U);
339 }
340
341 static inline pte_t
342 pte_mkexec(pte_t pte)
343 {
344     return __mkpte_from(pte.val & ~_PTE_PXN);
345 }
346
347 static inline pte_t
348 pte_mknexec(pte_t pte)
349 {
350     return __mkpte_from(pte.val | _PTE_PXN);
351 }
352
353 static inline pte_t
354 pte_mkuexec(pte_t pte)
355 {
356     return __mkpte_from(pte.val & ~_PTE_UXN);
357 }
358
359 static inline pte_t
360 pte_mknuexec(pte_t pte)
361 {
362     return __mkpte_from(pte.val | _PTE_UXN);
363 }
364
365 static inline bool
366 pte_isexec(pte_t pte)
367 {
368     return !(pte.val & _PTE_PXN);
369 }
370
371 static inline bool
372 pte_isuexec(pte_t pte)
373 {
374     return !(pte.val & _PTE_UXN);
375 }
376
377 static inline pte_t
378 pte_mkuntouch(pte_t pte) 
379 {
380     return __mkpte_from(pte.val & ~_PTE_AF);
381 }
382
383 static inline bool
384 pte_istouched(pte_t pte) 
385 {
386     return !!(pte.val & _PTE_AF);
387 }
388
389 static inline pte_t
390 pte_mkclean(pte_t pte) 
391 {
392     return __mkpte_from(pte.val | _PTE_nDIRTY);
393 }
394
395 static inline bool
396 pte_dirty(pte_t pte) 
397 {
398     return (pte.val & _PTE_DBM) && (pte.val & ~_PTE_nDIRTY);
399 }
400
401 static inline void
402 set_pte(pte_t* ptep, pte_t pte)
403 {
404     ptep->val = pte.val;
405 }
406
407 static inline pte_t
408 pte_at(pte_t* ptep) {
409     return *ptep;
410 }
411
412 pte_t
413 translate_vmr_prot(unsigned int vmr_prot, pte_t pte);
414
415 #endif /* __LUNAIX_ARCH_PAGETABLE_H */