1use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
2
3use crate::Gfn;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum PagingMode {
8 Legacy,
10
11 PAE,
14
15 Ia32e,
17
18 Ia32eLA57,
20}
21
22impl PagingMode {
23 pub fn address_width(self) -> usize {
26 match self {
27 Self::Legacy => 4,
28 Self::PAE => 4,
29 Self::Ia32e => 8,
30 Self::Ia32eLA57 => 8,
31 }
32 }
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
37#[repr(u8)]
38pub enum PageTableLevel {
39 Pt,
41
42 Pd,
44
45 Pdpt,
48
49 Pml4,
51}
52
53impl PageTableLevel {
54 pub fn next(self) -> Option<Self> {
56 match self {
57 Self::Pt => None,
58 Self::Pd => Some(Self::Pt),
59 Self::Pdpt => Some(Self::Pd),
60 Self::Pml4 => Some(Self::Pdpt),
61 }
62 }
63
64 pub fn previous(self) -> Option<Self> {
66 match self {
67 Self::Pt => Some(Self::Pd),
68 Self::Pd => Some(Self::Pdpt),
69 Self::Pdpt => Some(Self::Pml4),
70 Self::Pml4 => None,
71 }
72 }
73}
74
75#[repr(transparent)]
77#[derive(Default, Clone, Copy, PartialEq, Eq, FromBytes, IntoBytes, Immutable, KnownLayout)]
78pub struct PageTableEntry(pub u64);
79
80impl PageTableEntry {
81 pub fn present(self) -> bool {
83 self.0 & 1 != 0
84 }
85
86 pub fn write(self) -> bool {
88 (self.0 >> 1) & 1 != 0
89 }
90
91 pub fn supervisor(self) -> bool {
94 (self.0 >> 2) & 1 != 0
95 }
96
97 pub fn page_level_write_through(self) -> bool {
99 (self.0 >> 3) & 1 != 0
100 }
101
102 pub fn page_level_cache_disable(self) -> bool {
104 (self.0 >> 4) & 1 != 0
105 }
106
107 pub fn accessed(self) -> bool {
109 (self.0 >> 5) & 1 != 0
110 }
111
112 pub fn dirty(self) -> bool {
114 (self.0 >> 6) & 1 != 0
115 }
116
117 pub fn large(self) -> bool {
119 (self.0 >> 7) & 1 != 0
120 }
121
122 pub fn global(self) -> bool {
124 (self.0 >> 8) & 1 != 0
125 }
126
127 pub fn pfn(self) -> Gfn {
129 const BITS: u64 = 40;
130 const MASK: u64 = (1 << BITS) - 1;
131 Gfn::new((self.0 >> 12) & MASK)
132 }
133}
134
135impl std::fmt::Debug for PageTableEntry {
136 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
137 f.debug_struct("PageTableEntry")
138 .field("present", &self.present())
139 .field("write", &self.write())
140 .field("supervisor", &self.supervisor())
141 .field("page_level_write_through", &self.page_level_write_through())
142 .field("page_level_cache_disable", &self.page_level_cache_disable())
143 .field("accessed", &self.accessed())
144 .field("dirty", &self.dirty())
145 .field("large", &self.large())
146 .field("global", &self.global())
147 .field("pfn", &self.pfn())
148 .finish()
149 }
150}