1 #ifndef __LUNAIX_ARCH_PAGETABLE_H
2 #define __LUNAIX_ARCH_PAGETABLE_H
4 #include <lunaix/types.h>
5 #include <lunaix/compiler.h>
9 /* ******** Page Table Manipulation ******** */
14 // Note: we set VMS_SIZE = VMS_MASK as it is impossible
15 // to express 4Gi in 32bit unsigned integer
20 #define PMS_BITS CONFIG_AA64_OA_SIZE
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 )
27 #define __index(va) ( (va) & VMS_MASK )
29 ( (__index(va) ^ ((VMS_MASK + 1) >> 1)) - ((VMS_MASK + 1) >> 1) )
30 #define __paddr(pa) ( (pa) & PMS_MASK )
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
41 #define _PAGE_BASE_SIZE ( 1UL << _PAGE_BASE_SHIFT )
42 #define _PAGE_BASE_MASK ( (_PAGE_BASE_SIZE - 1) & VMS_MASK )
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)) )
50 /* General size of a LnT huge page */
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)
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)
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)
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)
82 #define __OA_HIGH_MASK (0)
83 #define __OA_HEAD(pa) (__paddr(pa) & ~PAGE_MASK)
84 #define __OA_TAIL(pa) (0)
87 #define _PTE_OA(pa) (__OA_HEAD(pa) | __OA_TAIL(pa))
91 #define _PTE_nG (1UL << 11)
92 #define _PTE_AF (1UL << 10)
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
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 )
113 #define __MEMGUARD 0xf0f0f0f0f0f0f0f0UL
115 typedef unsigned long pte_attr_t;
116 typedef unsigned long pfn_t;
118 // always do sign extend on x86_64
122 /* General mask to get page offset of a LnT huge page */
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 )
130 /* Masks to get index of a LnTE */
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 )
138 #define PAGE_SHIFT _PAGE_BASE_SHIFT
139 #define PAGE_SIZE _PAGE_BASE_SIZE
140 #define PAGE_MASK _PAGE_BASE_MASK
142 #define LEVEL_SHIFT _PAGE_LEVEL_SHIFT
143 #define LEVEL_SIZE _PAGE_LEVEL_SIZE
144 #define LEVEL_MASK _PAGE_LEVEL_MASK
147 #define MAX_PTEN _PAGE_LEVEL_SIZE
149 // max translation level supported
150 #define MAX_LEVEL _PTW_LEVEL
152 typedef struct __pte pte_t;
154 #define _PTE_PROT_MASK ( ~((1UL << 50) - 1) | (PAGE_MASK & __OA_HIGH_MASK) )
155 #define _PTE_PPFN_MASK ( ~_PTE_PROT_MASK )
157 #define _PAGE_BASIC ( _PTE_VALID )
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 )
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 )
171 #define SELF_MAP ( KERNEL_DATA | _PTE_TABDESC )
173 #define __mkpte_from(pte_val) ((pte_t){ .val = (pte_val) })
175 #define null_pte ( __mkpte_from(0) )
176 #define guard_pte ( __mkpte_from(__MEMGUARD) )
177 #define pte_val(pte) ( pte.val )
181 pte_isguardian(pte_t pte)
183 return pte.val == __MEMGUARD;
187 mkpte_prot(pte_attr_t prot)
189 pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_LFTDESC;
190 return __mkpte_from(attrs);
194 mkpte(ptr_t paddr, pte_attr_t prot)
196 pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_LFTDESC;
197 return __mkpte_from((paddr & ~_PAGE_BASE_MASK) | attrs);
201 mkpte_root(ptr_t paddr, pte_attr_t prot)
203 pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_TABDESC;
204 return __mkpte_from((paddr & ~_PAGE_BASE_MASK) | attrs);
208 mkpte_raw(unsigned long pte_val)
210 return __mkpte_from(pte_val);
214 pte_setpaddr(pte_t pte, ptr_t paddr)
216 return __mkpte_from((pte.val & _PTE_PROT_MASK) | (paddr & ~_PTE_PROT_MASK));
220 pte_setppfn(pte_t pte, pfn_t ppfn)
222 return pte_setpaddr(pte, ppfn * PAGE_SIZE);
228 return __paddr(pte.val) & ~_PTE_PROT_MASK;
234 return pte_paddr(pte) >> _PAGE_BASE_SHIFT;
238 pte_setprot(pte_t pte, ptr_t prot)
240 return __mkpte_from((pte.val & ~_PTE_PROT_MASK) | (prot & _PTE_PROT_MASK));
243 static inline pte_attr_t
246 return (pte.val & _PTE_PROT_MASK);
250 pte_isnull(pte_t pte)
256 pte_mkhuge(pte_t pte)
258 return __mkpte_from(_PTE_SET_DESC(pte.val, _PTE_BLKDESC));
262 pte_mkvolatile(pte_t pte)
264 return __mkpte_from(pte.val);
268 pte_mkroot(pte_t pte)
270 return __mkpte_from(_PTE_SET_DESC(pte.val, _PTE_TABDESC));
276 return _PTE_GET_DESC(pte.val) == _PTE_BLKDESC;
280 pte_mkloaded(pte_t pte)
282 return __mkpte_from(pte.val | _PTE_VALID);
286 pte_mkunloaded(pte_t pte)
288 return __mkpte_from(pte.val & ~_PTE_VALID);
292 pte_isloaded(pte_t pte)
294 return !!(pte.val & _PTE_VALID);
298 pte_mkwprotect(pte_t pte)
300 return __mkpte_from(pte.val | _PTE_PRO);
304 pte_mkwritable(pte_t pte)
306 return __mkpte_from(pte.val & ~_PTE_PRO);
310 pte_iswprotect(pte_t pte)
312 return !(pte.val & _PTE_PRO);
316 pte_mkuser(pte_t pte)
318 return __mkpte_from(pte.val | _PTE_U);
322 pte_mkkernel(pte_t pte)
324 return __mkpte_from(pte.val & ~_PTE_U);
328 pte_allow_user(pte_t pte)
330 return !!(pte.val & _PTE_U);
334 pte_mkexec(pte_t pte)
336 return __mkpte_from(pte.val & ~_PTE_PXN);
340 pte_mknexec(pte_t pte)
342 return __mkpte_from(pte.val | _PTE_PXN);
346 pte_mkuexec(pte_t pte)
348 return __mkpte_from(pte.val & ~_PTE_UXN);
352 pte_mknuexec(pte_t pte)
354 return __mkpte_from(pte.val | _PTE_UXN);
358 pte_isexec(pte_t pte)
360 return !(pte.val & _PTE_PXN);
364 pte_isuexec(pte_t pte)
366 return !(pte.val & _PTE_UXN);
370 pte_mkuntouch(pte_t pte)
372 return __mkpte_from(pte.val & ~_PTE_AF);
376 pte_istouched(pte_t pte)
378 return !!(pte.val & _PTE_AF);
382 pte_mkclean(pte_t pte)
384 return __mkpte_from(pte.val & ~_PTE_DBM);
390 return !!(pte.val & _PTE_DBM);
394 set_pte(pte_t* ptep, pte_t pte)
400 pte_at(pte_t* ptep) {
405 translate_vmr_prot(unsigned int vmr_prot, pte_t pte);
407 #endif /* __LUNAIX_ARCH_PAGETABLE_H */