1use crate::addresses::{PhysicalPage, Size1G, Size2M, Size4K};
2use crate::page_table::pd::{Pde, Pde2M};
3use crate::page_table::pdpt::{Pdpte, Pdpte1G};
4use crate::page_table::pml4::Pml4Entry;
5use crate::page_table::pt::PtEntry4k;
6use utils_accessors_derive::Setters;
7
8#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Setters)]
22#[allow(clippy::struct_excessive_bools)]
23pub struct VirtualMemoryPageBits {
24    pub present: bool,
26
27    pub writable: bool,
29
30    pub user: bool,
32
33    pub write_through: bool,
35
36    pub cache_disable: bool,
38
39    pub accessed: bool,
41
42    pub dirty: bool,
46
47    pub global: bool,
49
50    pub no_execute: bool,
55
56    pub protection_key: u8,
61
62    pub os_available_low: u8,
64
65    pub os_available_high: u8,
67
68    pub pat_bit2: bool,
78}
79
80impl VirtualMemoryPageBits {
81    #[inline]
83    #[must_use]
84    pub const fn with_write_combining(self) -> Self {
85        self.with_write_through(false)
86            .with_cache_disable(true)
87            .with_pat_bit2(true)
88    }
89
90    #[must_use]
92    pub const fn from_pml4e(e: &Pml4Entry) -> Self {
93        Self {
94            present: e.present(),
95            writable: e.writable(),
96            user: e.user(),
97            write_through: e.write_through(),
98            cache_disable: e.cache_disable(),
99            accessed: e.accessed(),
100            dirty: false,  global: false, no_execute: e.no_execute(),
103            protection_key: e.protection_key(),
104            os_available_low: e.os_available_low() & 0b111,
105            os_available_high: e.os_available_high() & 0x7F,
106            pat_bit2: false, }
108    }
109
110    #[must_use]
112    pub const fn from_pdpte(e: &Pdpte) -> Self {
113        Self {
114            present: e.present(),
115            writable: e.writable(),
116            user: e.user(),
117            write_through: e.write_through(),
118            cache_disable: e.cache_disable(),
119            accessed: e.accessed(),
120            dirty: false,
121            global: false,
122            no_execute: e.no_execute(),
123            protection_key: e.protection_key(),
124            os_available_low: e.os_available_low() & 0b111,
125            os_available_high: e.os_available_high() & 0x7F,
126            pat_bit2: false,
127        }
128    }
129
130    #[must_use]
132    pub const fn from_pdpte_1g(e: &Pdpte1G) -> Self {
133        Self {
134            present: e.present(),
135            writable: e.writable(),
136            user: e.user(),
137            write_through: e.write_through(),
138            cache_disable: e.cache_disable(),
139            accessed: e.accessed(),
140            dirty: e.dirty(),
141            global: e.global(),
142            no_execute: e.no_execute(),
143            protection_key: e.protection_key(),
144            os_available_low: e.os_available_low() & 0b111,
145            os_available_high: e.os_available_high() & 0x7F,
146            pat_bit2: e.pat_large(),
147        }
148    }
149
150    #[must_use]
152    pub const fn from_pde(e: &Pde) -> Self {
153        Self {
154            present: e.present(),
155            writable: e.writable(),
156            user: e.user(),
157            write_through: e.write_through(),
158            cache_disable: e.cache_disable(),
159            accessed: e.accessed(),
160            dirty: false,
161            global: false,
162            no_execute: e.no_execute(),
163            protection_key: e.protection_key(),
164            os_available_low: e.os_available_low() & 0b111,
165            os_available_high: e.os_available_high() & 0x7F,
166            pat_bit2: false,
167        }
168    }
169
170    #[must_use]
172    pub const fn from_pde_2m(e: &Pde2M) -> Self {
173        Self {
174            present: e.present(),
175            writable: e.writable(),
176            user: e.user(),
177            write_through: e.write_through(),
178            cache_disable: e.cache_disable(),
179            accessed: e.accessed(),
180            dirty: e.dirty(),
181            global: e.global(),
182            no_execute: e.no_execute(),
183            protection_key: e.protection_key(),
184            os_available_low: e.os_available_low() & 0b111,
185            os_available_high: e.os_available_high() & 0x7F,
186            pat_bit2: e.pat_large(),
187        }
188    }
189
190    #[must_use]
192    pub const fn from_pte_4k(e: &PtEntry4k) -> Self {
193        Self {
194            present: e.present(),
195            writable: e.writable(),
196            user: e.user(),
197            write_through: e.write_through(),
198            cache_disable: e.cache_disable(),
199            accessed: e.accessed(),
200            dirty: e.dirty(),
201            global: e.global(),
202            no_execute: e.no_execute(),
203            protection_key: e.protection_key(),
204            os_available_low: e.os_available_low() & 0b111,
205            os_available_high: e.os_available_high() & 0x7F,
206            pat_bit2: e.pat_small(),
207        }
208    }
209}
210
211impl VirtualMemoryPageBits {
212    #[must_use]
217    pub const fn to_pml4e(&self, page: PhysicalPage<Size4K>) -> Pml4Entry {
218        let mut e = Pml4Entry::new();
219        e.set_present(self.present);
220        e.set_writable(self.writable);
221        e.set_user(self.user);
222        e.set_write_through(self.write_through);
223        e.set_cache_disable(self.cache_disable);
224        e.set_accessed(self.accessed);
225        e.set_no_execute(self.no_execute);
226        e.set_os_available_low(self.os_available_low & 0b111);
227        e.set_os_available_high(self.os_available_high & 0x7F);
228        e.set_protection_key(self.protection_key & 0x0F);
229        e.set_physical_address(page);
230        e
231    }
232
233    #[must_use]
235    pub const fn to_pdpte(&self, page: PhysicalPage<Size4K>) -> Pdpte {
236        let mut e = Pdpte::new();
237        e.set_present(self.present);
238        e.set_writable(self.writable);
239        e.set_user(self.user);
240        e.set_write_through(self.write_through);
241        e.set_cache_disable(self.cache_disable);
242        e.set_accessed(self.accessed);
243        e.set_no_execute(self.no_execute);
244        e.set_os_available_low(self.os_available_low & 0b111);
245        e.set_os_available_high(self.os_available_high & 0x7F);
246        e.set_protection_key(self.protection_key & 0x0F);
247        e.set_physical_page(page);
248        e
249    }
250
251    #[must_use]
253    pub const fn to_pdpte_1g(&self, page: PhysicalPage<Size1G>) -> Pdpte1G {
254        let mut e = Pdpte1G::new();
255        e.set_present(self.present);
256        e.set_writable(self.writable);
257        e.set_user(self.user);
258        e.set_write_through(self.write_through);
259        e.set_cache_disable(self.cache_disable);
260        e.set_accessed(self.accessed);
261        e.set_dirty(self.dirty);
262        e.set_global(self.global);
263        e.set_no_execute(self.no_execute);
264        e.set_os_available_low(self.os_available_low & 0b111);
265        e.set_os_available_high(self.os_available_high & 0x7F);
266        e.set_protection_key(self.protection_key & 0x0F);
267        e.set_pat_large(self.pat_bit2);
268        e.set_physical_page(page);
269        e
271    }
272
273    #[must_use]
275    pub const fn to_pde(&self, page: PhysicalPage<Size4K>) -> Pde {
276        let mut e = Pde::new();
277        e.set_present(self.present);
278        e.set_writable(self.writable);
279        e.set_user(self.user);
280        e.set_write_through(self.write_through);
281        e.set_cache_disable(self.cache_disable);
282        e.set_accessed(self.accessed);
283        e.set_no_execute(self.no_execute);
284        e.set_os_available_low(self.os_available_low & 0b111);
285        e.set_os_available_high(self.os_available_high & 0x7F);
286        e.set_protection_key(self.protection_key & 0x0F);
287        e.set_physical_page(page);
288        e
289    }
290
291    #[must_use]
293    pub const fn to_pde_2m(&self, page: PhysicalPage<Size2M>) -> Pde2M {
294        let mut e = Pde2M::new();
295        e.set_present(self.present);
296        e.set_writable(self.writable);
297        e.set_user(self.user);
298        e.set_write_through(self.write_through);
299        e.set_cache_disable(self.cache_disable);
300        e.set_accessed(self.accessed);
301        e.set_dirty(self.dirty);
302        e.set_global(self.global);
303        e.set_no_execute(self.no_execute);
304        e.set_os_available_low(self.os_available_low & 0b111);
305        e.set_os_available_high(self.os_available_high & 0x7F);
306        e.set_protection_key(self.protection_key & 0x0F);
307        e.set_pat_large(self.pat_bit2);
308        e.set_physical_page(page);
309        e
311    }
312
313    #[must_use]
315    pub const fn to_pte_4k(&self, page: PhysicalPage<Size4K>) -> PtEntry4k {
316        let mut e = PtEntry4k::new();
317        e.set_present(self.present);
318        e.set_writable(self.writable);
319        e.set_user(self.user);
320        e.set_write_through(self.write_through);
321        e.set_cache_disable(self.cache_disable);
322        e.set_accessed(self.accessed);
323        e.set_dirty(self.dirty);
324        e.set_global(self.global);
325        e.set_no_execute(self.no_execute);
326        e.set_os_available_low(self.os_available_low & 0b111);
327        e.set_os_available_high(self.os_available_high & 0x7F);
328        e.set_protection_key(self.protection_key & 0x0F);
329        e.set_pat_small(self.pat_bit2);
330        e.set_physical_page(page);
331        e
332    }
333}
334
335impl From<Pml4Entry> for VirtualMemoryPageBits {
336    #[inline]
337    fn from(e: Pml4Entry) -> Self {
338        Self::from_pml4e(&e)
339    }
340}
341
342impl From<Pdpte> for VirtualMemoryPageBits {
343    #[inline]
344    fn from(e: Pdpte) -> Self {
345        Self::from_pdpte(&e)
346    }
347}
348
349impl From<Pdpte1G> for VirtualMemoryPageBits {
350    #[inline]
351    fn from(e: Pdpte1G) -> Self {
352        Self::from_pdpte_1g(&e)
353    }
354}
355
356impl From<Pde> for VirtualMemoryPageBits {
357    #[inline]
358    fn from(e: Pde) -> Self {
359        Self::from_pde(&e)
360    }
361}
362
363impl From<Pde2M> for VirtualMemoryPageBits {
364    #[inline]
365    fn from(e: Pde2M) -> Self {
366        Self::from_pde_2m(&e)
367    }
368}
369
370impl From<PtEntry4k> for VirtualMemoryPageBits {
371    #[inline]
372    fn from(e: PtEntry4k) -> Self {
373        Self::from_pte_4k(&e)
374    }
375}