1 #ifndef __LUNAIX_ARCH_PAGETABLE_H
2 #define __LUNAIX_ARCH_PAGETABLE_H
4 #include <lunaix/types.h>
5 #include <lunaix/compiler.h>
8 #include <lunaix/bits.h>
10 /* ******** Page Table Manipulation ******** */
15 // Note: we set VMS_SIZE = VMS_MASK as it is impossible
16 // to express 4Gi in 32bit unsigned integer
21 #define PMS_BITS CONFIG_AA64_OA_SIZE
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 )
28 #define __index(va) ( (va) & VMS_MASK )
30 ( (__index(va) ^ ((VMS_MASK + 1) >> 1)) - ((VMS_MASK + 1) >> 1) )
31 #define __paddr(pa) ( (pa) & PMS_MASK )
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
42 #define _PAGE_BASE_SIZE ( 1UL << _PAGE_BASE_SHIFT )
43 #define _PAGE_BASE_MASK ( (_PAGE_BASE_SIZE - 1) & VMS_MASK )
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)) )
51 /* General size of a LnT huge page */
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)
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)
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)
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)
83 #define __OA_HIGH_MASK (0)
84 #define __OA_HEAD(pa) (__paddr(pa) & ~PAGE_MASK)
85 #define __OA_TAIL(pa) (0)
88 #define _PTE_OA(pa) (__OA_HEAD(pa) | __OA_TAIL(pa))
92 #define _PTE_nG BITFLAG(11)
93 #define _PTE_AF BITFLAG(10)
97 #define _PTE_AP(p, u) ((((p) & 1) << 1 | ((u) & 1)) << 6)
99 // el1 rw, el0 deny all
100 #define _PTE_PRW _PTE_AP(0 , 0)
102 #define _PTE_PRWURW _PTE_AP(0 , 1)
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
109 #define _PTE_PROURO _PTE_AP(1 , 1) | _PTE_DBM
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 )
121 #define __MEMGUARD 0xf0f0f0f0f0f0f0f0UL
123 typedef unsigned long pte_attr_t;
124 typedef unsigned long pfn_t;
126 // always do sign extend on x86_64
130 /* General mask to get page offset of a LnT huge page */
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 )
138 /* Masks to get index of a LnTE */
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 )
146 #define PAGE_SHIFT _PAGE_BASE_SHIFT
147 #define PAGE_SIZE _PAGE_BASE_SIZE
148 #define PAGE_MASK _PAGE_BASE_MASK
150 #define LEVEL_SHIFT _PAGE_LEVEL_SHIFT
151 #define LEVEL_SIZE _PAGE_LEVEL_SIZE
152 #define LEVEL_MASK _PAGE_LEVEL_MASK
155 #define MAX_PTEN _PAGE_LEVEL_SIZE
157 // max translation level supported
158 #define MAX_LEVEL _PTW_LEVEL
160 typedef struct __pte pte_t;
162 #define _PTE_PROT_MASK ( ~((1UL << 50) - 1) | (PAGE_MASK & __OA_HIGH_MASK) )
163 #define _PTE_PPFN_MASK ( ~_PTE_PROT_MASK )
165 #define _PAGE_BASIC ( _PTE_VALID )
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 )
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 )
179 #define SELF_MAP ( KERNEL_DATA | _PTE_TABDESC )
181 #define __mkpte_from(pte_val) ((pte_t){ .val = (pte_val) })
183 #define null_pte ( __mkpte_from(0) )
184 #define guard_pte ( __mkpte_from(__MEMGUARD) )
185 #define pte_val(pte) ( pte.val )
189 pte_isguardian(pte_t pte)
191 return pte.val == __MEMGUARD;
195 mkpte_prot(pte_attr_t prot)
197 pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_LFTDESC;
198 return __mkpte_from(attrs);
202 mkpte(ptr_t paddr, pte_attr_t prot)
204 pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_LFTDESC;
205 return __mkpte_from((paddr & ~_PAGE_BASE_MASK) | attrs);
209 mkpte_root(ptr_t paddr, pte_attr_t prot)
211 pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_TABDESC;
212 return __mkpte_from((paddr & ~_PAGE_BASE_MASK) | attrs);
216 mkpte_raw(unsigned long pte_val)
218 return __mkpte_from(pte_val);
222 pte_setpaddr(pte_t pte, ptr_t paddr)
224 return __mkpte_from((pte.val & _PTE_PROT_MASK) | (paddr & ~_PTE_PROT_MASK));
228 pte_setppfn(pte_t pte, pfn_t ppfn)
230 return pte_setpaddr(pte, ppfn * PAGE_SIZE);
236 return __paddr(pte.val) & ~_PTE_PROT_MASK;
242 return pte_paddr(pte) >> _PAGE_BASE_SHIFT;
246 pte_setprot(pte_t pte, ptr_t prot)
248 return __mkpte_from((pte.val & ~_PTE_PROT_MASK) | (prot & _PTE_PROT_MASK));
251 static inline pte_attr_t
254 return (pte.val & _PTE_PROT_MASK);
258 pte_isnull(pte_t pte)
264 pte_mkhuge(pte_t pte)
266 return __mkpte_from(_PTE_SET_DESC(pte.val, _PTE_BLKDESC));
270 pte_mkvolatile(pte_t pte)
272 return __mkpte_from(pte.val);
276 pte_mkroot(pte_t pte)
278 return __mkpte_from(_PTE_SET_DESC(pte.val, _PTE_TABDESC));
284 return _PTE_GET_DESC(pte.val) == _PTE_BLKDESC;
288 pte_mkloaded(pte_t pte)
290 return __mkpte_from(pte.val | _PTE_VALID);
294 pte_mkunloaded(pte_t pte)
296 return __mkpte_from(pte.val & ~_PTE_VALID);
300 pte_isloaded(pte_t pte)
302 return !!(pte.val & _PTE_VALID);
306 pte_mkwprotect(pte_t pte)
308 return __mkpte_from(pte.val | _PTE_PRO);
312 pte_mkwritable(pte_t pte)
314 return __mkpte_from(pte.val & ~_PTE_PRO);
318 pte_iswprotect(pte_t pte)
320 return !(pte.val & _PTE_PRO);
324 pte_mkuser(pte_t pte)
326 return __mkpte_from(pte.val | _PTE_U);
330 pte_mkkernel(pte_t pte)
332 return __mkpte_from(pte.val & ~_PTE_U);
336 pte_allow_user(pte_t pte)
338 return !!(pte.val & _PTE_U);
342 pte_mkexec(pte_t pte)
344 return __mkpte_from(pte.val & ~_PTE_PXN);
348 pte_mknexec(pte_t pte)
350 return __mkpte_from(pte.val | _PTE_PXN);
354 pte_mkuexec(pte_t pte)
356 return __mkpte_from(pte.val & ~_PTE_UXN);
360 pte_mknuexec(pte_t pte)
362 return __mkpte_from(pte.val | _PTE_UXN);
366 pte_isexec(pte_t pte)
368 return !(pte.val & _PTE_PXN);
372 pte_isuexec(pte_t pte)
374 return !(pte.val & _PTE_UXN);
378 pte_mkuntouch(pte_t pte)
380 return __mkpte_from(pte.val & ~_PTE_AF);
384 pte_istouched(pte_t pte)
386 return !!(pte.val & _PTE_AF);
390 pte_mkclean(pte_t pte)
392 return __mkpte_from(pte.val | _PTE_nDIRTY);
398 return (pte.val & _PTE_DBM) && (pte.val & ~_PTE_nDIRTY);
402 set_pte(pte_t* ptep, pte_t pte)
408 pte_at(pte_t* ptep) {
413 translate_vmr_prot(unsigned int vmr_prot, pte_t pte);
415 #endif /* __LUNAIX_ARCH_PAGETABLE_H */