ld-tool portability fix: MacOS build experience
[lunaix-os.git] / lunaix-os / arch / i386 / includes / sys / mm / 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 /* ******** Page Table Manipulation ******** */
8
9 // Levels of page table to traverse for a single page walk
10 #define _PTW_LEVEL          2
11
12 #define _PAGE_BASE_SHIFT    12
13 #define _PAGE_BASE_SIZE     ( 1UL << _PAGE_BASE_SHIFT )
14 #define _PAGE_BASE_MASK     ( _PAGE_BASE_SIZE - 1)
15
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)) )
20
21 // Note: we set VMS_SIZE = VMS_MASK as it is impossible
22 //       to express 4Gi in 32bit unsigned integer
23
24 #define VMS_MASK            ( -1UL )
25 #define VMS_SIZE            VMS_MASK
26
27 /* General size of a LnT huge page */
28
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)
34
35 /* General mask to get page offset of a LnT huge page */
36
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 )
42
43 /* Masks to get index of a LnTE */
44
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 )
50
51 #define PAGE_SHIFT          _PAGE_BASE_SHIFT
52 #define PAGE_SIZE           _PAGE_BASE_SIZE
53 #define PAGE_MASK           _PAGE_BASE_MASK
54
55 #define LEVEL_SHIFT         _PAGE_LEVEL_SHIFT
56 #define LEVEL_SIZE          _PAGE_LEVEL_SIZE
57 #define LEVEL_MASK          _PAGE_LEVEL_MASK
58
59 // max PTEs number
60 #define MAX_PTEN            _PAGE_LEVEL_SIZE
61
62 // max translation level supported
63 #define MAX_LEVEL           _PTW_LEVEL
64
65
66 /* ******** PTE Manipulation ******** */
67
68 struct __pte {
69     unsigned int val;
70 } align(4);
71
72 #ifndef pte_t
73 typedef struct __pte pte_t;
74 #endif
75
76 typedef unsigned int pfn_t;
77 typedef unsigned int pte_attr_t;
78
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)
89 #define _PTE_X                  (0)
90 #define _PTE_R                  (0)
91
92 #define _PTE_PROT_MASK          ( _PTE_W | _PTE_U | _PTE_X )
93
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 )
98
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 )
103
104 #define SELF_MAP                ( KERNEL_DATA | _PTE_WT | _PTE_CD )
105
106 #define __mkpte_from(pte_val)   ((pte_t){ .val = (pte_val) })
107 #define __MEMGUARD               0xdeadc0deUL
108
109 #define null_pte                ( __mkpte_from(0) )
110 #define guard_pte               ( __mkpte_from(__MEMGUARD) )
111 #define pte_val(pte)            ( pte.val )
112
113
114 static inline bool
115 pte_isguardian(pte_t pte)
116 {
117     return pte.val == __MEMGUARD;
118 }
119
120 static inline pte_t
121 mkpte_prot(pte_attr_t prot)
122 {
123     pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_P;
124     return __mkpte_from(attrs);
125 }
126
127 static inline pte_t
128 mkpte(ptr_t paddr, pte_attr_t prot)
129 {
130     pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_P;
131     return __mkpte_from((paddr & ~_PAGE_BASE_MASK) | attrs);
132 }
133
134 static inline pte_t
135 mkpte_root(ptr_t paddr, pte_attr_t prot)
136 {
137     pte_attr_t attrs = (prot & _PTE_PROT_MASK) | _PTE_P;
138     return __mkpte_from((paddr & ~_PAGE_BASE_MASK) | attrs);
139 }
140
141 static inline pte_t
142 mkpte_raw(unsigned long pte_val)
143 {
144     return __mkpte_from(pte_val);
145 }
146
147 static inline pte_t
148 pte_setpaddr(pte_t pte, ptr_t paddr)
149 {
150     return __mkpte_from((pte.val & _PAGE_BASE_MASK) | (paddr & ~_PAGE_BASE_MASK));
151 }
152
153 static inline pte_t
154 pte_setppfn(pte_t pte, pfn_t ppfn)
155 {
156     return __mkpte_from((pte.val & _PAGE_BASE_MASK) | (ppfn * PAGE_SIZE));
157 }
158
159 static inline ptr_t
160 pte_paddr(pte_t pte)
161 {
162     return pte.val & ~_PAGE_BASE_MASK;
163 }
164
165 static inline pfn_t
166 pte_ppfn(pte_t pte)
167 {
168     return pte.val >> _PAGE_BASE_SHIFT;
169 }
170
171 static inline pte_t
172 pte_setprot(pte_t pte, ptr_t prot)
173 {
174     return __mkpte_from((pte.val & ~_PTE_PROT_MASK) | (prot & _PTE_PROT_MASK));
175 }
176
177 static inline pte_attr_t
178 pte_prot(pte_t pte)
179 {
180     return (pte.val & _PTE_PROT_MASK);
181 }
182
183 static inline bool
184 pte_isnull(pte_t pte)
185 {
186     return !pte.val;
187 }
188
189 static inline pte_t
190 pte_mkhuge(pte_t pte) 
191 {
192     return __mkpte_from(pte.val | _PTE_PS);
193 }
194
195 static inline pte_t
196 pte_mkvolatile(pte_t pte) 
197 {
198     return __mkpte_from(pte.val | _PTE_WT | _PTE_CD);
199 }
200
201 static inline pte_t
202 pte_mkroot(pte_t pte) 
203 {
204     return __mkpte_from(pte.val & ~_PTE_PS);
205 }
206
207 static inline pte_t
208 pte_usepat(pte_t pte) 
209 {
210     return __mkpte_from(pte.val | _PTE_PAT);
211 }
212
213 static inline bool
214 pte_huge(pte_t pte) 
215 {
216     return !!(pte.val & _PTE_PS);
217 }
218
219 static inline pte_t
220 pte_mkloaded(pte_t pte) 
221 {
222     return __mkpte_from(pte.val | _PTE_P);
223 }
224
225 static inline pte_t
226 pte_mkunloaded(pte_t pte) 
227 {
228     return __mkpte_from(pte.val & ~_PTE_P);
229 }
230
231 static inline bool
232 pte_isloaded(pte_t pte) 
233 {
234     return !!(pte.val & _PTE_P);
235 }
236
237 static inline pte_t
238 pte_mkwprotect(pte_t pte) 
239 {
240     return __mkpte_from(pte.val & ~_PTE_W);
241 }
242
243 static inline pte_t
244 pte_mkwritable(pte_t pte) 
245 {
246     return __mkpte_from(pte.val | _PTE_W);
247 }
248
249 static inline bool
250 pte_iswprotect(pte_t pte) 
251 {
252     return !(pte.val & _PTE_W);
253 }
254
255 static inline pte_t
256 pte_mkuser(pte_t pte) 
257 {
258     return __mkpte_from(pte.val | _PTE_U);
259 }
260
261 static inline pte_t
262 pte_mkkernel(pte_t pte) 
263 {
264     return __mkpte_from(pte.val & ~_PTE_U);
265 }
266
267 static inline bool
268 pte_allow_user(pte_t pte) 
269 {
270     return !!(pte.val & _PTE_U);
271 }
272
273 static inline pte_t
274 pte_mkexec(pte_t pte)
275 {
276     return __mkpte_from(pte.val | _PTE_X);
277 }
278
279 static inline pte_t
280 pte_mknonexec(pte_t pte)
281 {
282     return __mkpte_from(pte.val & ~_PTE_X);
283 }
284
285 static inline bool
286 pte_isexec(pte_t pte)
287 {
288     return !!(pte.val & _PTE_X);
289 }
290
291 static inline pte_t
292 pte_mkuntouch(pte_t pte) 
293 {
294     return __mkpte_from(pte.val & ~_PTE_A);
295 }
296
297 static inline bool
298 pte_istouched(pte_t pte) 
299 {
300     return !!(pte.val & _PTE_A);
301 }
302
303 static inline pte_t
304 pte_mkclean(pte_t pte) 
305 {
306     return __mkpte_from(pte.val & ~_PTE_D);
307 }
308
309 static inline bool
310 pte_dirty(pte_t pte) 
311 {
312     return !!(pte.val & _PTE_D);
313 }
314
315 static inline void
316 set_pte(pte_t* ptep, pte_t pte)
317 {
318     ptep->val = pte.val;
319 }
320
321 static inline pte_t
322 pte_at(pte_t* ptep) {
323     return *ptep;
324 }
325
326
327 #endif /* __LUNAIX_ARCH_PAGETABLE_H */