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