1 #ifndef __LUNAIX_ARCH_PAGETABLE_H
2 #define __LUNAIX_ARCH_PAGETABLE_H
4 #include <lunaix/types.h>
5 #include <lunaix/compiler.h>
7 /* ******** Page Table Manipulation ******** */
9 // Levels of page table to traverse for a single page walk
12 #define _PAGE_BASE_SHIFT 12
13 #define _PAGE_BASE_SIZE ( 1UL << _PAGE_BASE_SHIFT )
14 #define _PAGE_BASE_MASK ( _PAGE_BASE_SIZE - 1)
16 #define _PAGE_LEVEL_SHIFT 10
17 #define _PAGE_LEVEL_SIZE ( 1UL << _PAGE_LEVEL_SHIFT )
18 #define _PAGE_LEVEL_MASK ( _PAGE_LEVEL_SIZE - 1 )
19 #define _PAGE_Ln_SIZE(n) ( 1UL << (_PAGE_BASE_SHIFT + _PAGE_LEVEL_SHIFT * (_PTW_LEVEL - (n) - 1)) )
21 // Note: we set VMS_SIZE = VMS_MASK as it is impossible
22 // to express 4Gi in 32bit unsigned integer
24 #define VMS_MASK ( -1UL )
25 #define VMS_SIZE VMS_MASK
27 /* General size of a LnT huge page */
29 #define L0T_SIZE _PAGE_Ln_SIZE(0)
30 #define L1T_SIZE _PAGE_Ln_SIZE(1)
31 #define L2T_SIZE _PAGE_Ln_SIZE(1)
32 #define L3T_SIZE _PAGE_Ln_SIZE(1)
33 #define LFT_SIZE _PAGE_Ln_SIZE(1)
35 /* General mask to get page offset of a LnT huge page */
37 #define L0T_MASK ( L0T_SIZE - 1 )
38 #define L1T_MASK ( L1T_SIZE - 1 )
39 #define L2T_MASK ( L2T_SIZE - 1 )
40 #define L3T_MASK ( L3T_SIZE - 1 )
41 #define LFT_MASK ( LFT_SIZE - 1 )
43 /* Masks to get index of a LnTE */
45 #define L0T_INDEX_MASK ( VMS_MASK ^ L0T_MASK )
46 #define L1T_INDEX_MASK ( L0T_MASK ^ L1T_MASK )
47 #define L2T_INDEX_MASK ( L1T_MASK ^ L2T_MASK )
48 #define L3T_INDEX_MASK ( L2T_MASK ^ L3T_MASK )
49 #define LFT_INDEX_MASK ( L3T_MASK ^ LFT_MASK )
51 #define PAGE_SHIFT _PAGE_BASE_SHIFT
52 #define PAGE_SIZE _PAGE_BASE_SIZE
53 #define PAGE_MASK _PAGE_BASE_MASK
55 #define LEVEL_SHIFT _PAGE_LEVEL_SHIFT
56 #define LEVEL_SIZE _PAGE_LEVEL_SIZE
57 #define LEVEL_MASK _PAGE_LEVEL_MASK
60 #define MAX_PTEN _PAGE_LEVEL_SIZE
62 // max translation level supported
63 #define MAX_LEVEL _PTW_LEVEL
66 /* ******** PTE Manipulation ******** */
73 typedef struct __pte pte_t;
76 typedef unsigned int pfn_t;
77 typedef unsigned int pte_attr_t;
79 #define _PTE_P (1 << 0)
80 #define _PTE_W (1 << 1)
81 #define _PTE_U (1 << 2)
82 #define _PTE_WT (1 << 3)
83 #define _PTE_CD (1 << 4)
84 #define _PTE_A (1 << 5)
85 #define _PTE_D (1 << 6)
86 #define _PTE_PS (1 << 7)
87 #define _PTE_PAT (1 << 7)
88 #define _PTE_G (1 << 8)
92 #define _PTE_PROT_MASK ( _PTE_W | _PTE_U | _PTE_X )
94 #define KERNEL_PAGE ( _PTE_P )
95 #define KERNEL_EXEC ( KERNEL_PAGE | _PTE_X )
96 #define KERNEL_DATA ( KERNEL_PAGE | _PTE_W )
97 #define KERNEL_RDONLY ( KERNEL_PAGE )
99 #define USER_PAGE ( _PTE_P | _PTE_U )
100 #define USER_EXEC ( USER_PAGE | _PTE_X )
101 #define USER_DATA ( USER_PAGE | _PTE_W )
102 #define USER_RDONLY ( USER_PAGE )
104 #define SELF_MAP ( KERNEL_DATA | _PTE_WT | _PTE_CD )
106 #define __mkpte_from(pte_val) ((pte_t){ .val = (pte_val) })
107 #define __MEMGUARD 0xdeadc0deUL
109 #define null_pte ( __mkpte_from(0) )
110 #define guard_pte ( __mkpte_from(__MEMGUARD) )
111 #define pte_val(pte) ( pte.val )
115 pte_isguardian(pte_t pte)
117 return pte.val == __MEMGUARD;
121 mkpte_prot(pte_attr_t prot)
123 pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_P;
124 return __mkpte_from(attrs);
128 mkpte(ptr_t paddr, pte_attr_t prot)
130 pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_P;
131 return __mkpte_from((paddr & ~_PAGE_BASE_MASK) | attrs);
135 mkpte_root(ptr_t paddr, pte_attr_t prot)
137 pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_P;
138 return __mkpte_from((paddr & ~_PAGE_BASE_MASK) | attrs);
142 mkpte_raw(unsigned long pte_val)
144 return __mkpte_from(pte_val);
148 pte_setpaddr(pte_t pte, ptr_t paddr)
150 return __mkpte_from((pte.val & _PAGE_BASE_MASK) | (paddr & ~_PAGE_BASE_MASK));
154 pte_setppfn(pte_t pte, pfn_t ppfn)
156 return __mkpte_from((pte.val & _PAGE_BASE_MASK) | (ppfn * PAGE_SIZE));
162 return pte.val & ~_PAGE_BASE_MASK;
168 return pte.val >> _PAGE_BASE_SHIFT;
172 pte_setprot(pte_t pte, ptr_t prot)
174 return __mkpte_from((pte.val & ~_PTE_PROT_MASK) | (prot & _PTE_PROT_MASK));
177 static inline pte_attr_t
180 return (pte.val & _PTE_PROT_MASK);
184 pte_isnull(pte_t pte)
190 pte_mkhuge(pte_t pte)
192 return __mkpte_from(pte.val | _PTE_PS);
196 pte_mkvolatile(pte_t pte)
198 return __mkpte_from(pte.val | _PTE_WT | _PTE_CD);
202 pte_mkroot(pte_t pte)
204 return __mkpte_from(pte.val & ~_PTE_PS);
208 pte_usepat(pte_t pte)
210 return __mkpte_from(pte.val | _PTE_PAT);
216 return !!(pte.val & _PTE_PS);
220 pte_mkloaded(pte_t pte)
222 return __mkpte_from(pte.val | _PTE_P);
226 pte_mkunloaded(pte_t pte)
228 return __mkpte_from(pte.val & ~_PTE_P);
232 pte_isloaded(pte_t pte)
234 return !!(pte.val & _PTE_P);
238 pte_mkwprotect(pte_t pte)
240 return __mkpte_from(pte.val & ~_PTE_W);
244 pte_mkwritable(pte_t pte)
246 return __mkpte_from(pte.val | _PTE_W);
250 pte_iswprotect(pte_t pte)
252 return !(pte.val & _PTE_W);
256 pte_mkuser(pte_t pte)
258 return __mkpte_from(pte.val | _PTE_U);
262 pte_mkkernel(pte_t pte)
264 return __mkpte_from(pte.val & ~_PTE_U);
268 pte_allow_user(pte_t pte)
270 return !!(pte.val & _PTE_U);
274 pte_mkexec(pte_t pte)
276 return __mkpte_from(pte.val | _PTE_X);
280 pte_mknonexec(pte_t pte)
282 return __mkpte_from(pte.val & ~_PTE_X);
286 pte_isexec(pte_t pte)
288 return !!(pte.val & _PTE_X);
292 pte_mkuntouch(pte_t pte)
294 return __mkpte_from(pte.val & ~_PTE_A);
298 pte_istouched(pte_t pte)
300 return !!(pte.val & _PTE_A);
304 pte_mkclean(pte_t pte)
306 return __mkpte_from(pte.val & ~_PTE_D);
312 return !!(pte.val & _PTE_D);
316 set_pte(pte_t* ptep, pte_t pte)
322 pte_at(pte_t* ptep) {
327 #endif /* __LUNAIX_ARCH_PAGETABLE_H */