Skip to main content

page_table_generic/
def.rs

1use core::ptr::NonNull;
2
3pub const KB: usize = 1024;
4pub const MB: usize = 1024 * KB;
5pub const GB: usize = 1024 * MB;
6
7macro_rules! def_addr {
8    ($name:ident, $t:ty) => {
9        #[repr(transparent)]
10        #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
11        pub struct $name($t);
12
13        impl From<$t> for $name {
14            #[inline(always)]
15            fn from(value: $t) -> Self {
16                Self(value)
17            }
18        }
19
20        impl From<$name> for $t {
21            #[inline(always)]
22            fn from(value: $name) -> Self {
23                value.0
24            }
25        }
26
27        impl $name {
28            #[inline(always)]
29            pub fn raw(&self) -> $t {
30                self.0
31            }
32
33            #[inline(always)]
34            pub const fn new(value: $t) -> Self {
35                Self(value)
36            }
37        }
38
39        impl core::ops::Add<$t> for $name {
40            type Output = Self;
41
42            #[inline(always)]
43            fn add(self, rhs: $t) -> Self::Output {
44                Self(self.0 + rhs)
45            }
46        }
47
48        impl core::ops::AddAssign<$t> for $name {
49            #[inline(always)]
50            fn add_assign(&mut self, rhs: $t) {
51                self.0 += rhs;
52            }
53        }
54
55        impl core::ops::Sub<$t> for $name {
56            type Output = Self;
57
58            #[inline(always)]
59            fn sub(self, rhs: $t) -> Self::Output {
60                Self(self.0 - rhs)
61            }
62        }
63
64        impl core::ops::Sub<Self> for $name {
65            type Output = $t;
66
67            #[inline(always)]
68            fn sub(self, rhs: Self) -> Self::Output {
69                self.0 - rhs.0
70            }
71        }
72
73        impl core::fmt::Debug for $name {
74            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
75                write!(f, "0x{:0>16x}", self.0)
76            }
77        }
78    };
79}
80
81def_addr!(PhysAddr, usize);
82def_addr!(VirtAddr, usize);
83
84impl VirtAddr {
85    #[inline(always)]
86    pub fn as_ptr(self) -> *mut u8 {
87        self.0 as _
88    }
89}
90
91impl From<*mut u8> for VirtAddr {
92    #[inline(always)]
93    fn from(val: *mut u8) -> Self {
94        Self(val as _)
95    }
96}
97
98impl From<NonNull<u8>> for VirtAddr {
99    #[inline(always)]
100    fn from(val: NonNull<u8>) -> Self {
101        Self(val.as_ptr() as _)
102    }
103}
104
105impl From<*const u8> for VirtAddr {
106    #[inline(always)]
107    fn from(val: *const u8) -> Self {
108        Self(val as _)
109    }
110}
111
112#[cfg(target_pointer_width = "64")]
113impl From<u64> for PhysAddr {
114    #[inline(always)]
115    fn from(value: u64) -> Self {
116        Self(value as _)
117    }
118}
119
120#[cfg(target_pointer_width = "32")]
121impl From<u32> for PhysAddr {
122    #[inline(always)]
123    fn from(value: u32) -> Self {
124        Self(value as _)
125    }
126}
127
128#[derive(thiserror::Error, Clone, PartialEq, Eq)]
129pub enum PagingError {
130    #[error("Memory allocation failed")]
131    NoMemory,
132    #[error("Address alignment error: {details}")]
133    AlignmentError { details: &'static str },
134    #[error(
135        "Mapping conflict: virtual address {vaddr:#x} already mapped to physical address {existing_paddr:#x}"
136    )]
137    MappingConflict {
138        vaddr: VirtAddr,
139        existing_paddr: PhysAddr,
140    },
141    #[error("Address overflow detected: {details}")]
142    AddressOverflow { details: &'static str },
143    #[error("Invalid mapping size: {details}")]
144    InvalidSize { details: &'static str },
145    #[error("Page table hierarchy error: {details}")]
146    HierarchyError { details: &'static str },
147    #[error("Invalid address range: {details}")]
148    InvalidRange { details: &'static str },
149    #[error("Address not mapped")]
150    NotMapped,
151}
152
153impl core::fmt::LowerHex for VirtAddr {
154    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
155        write!(f, "{:#x}", self.raw())
156    }
157}
158
159impl core::fmt::LowerHex for PhysAddr {
160    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
161        write!(f, "{:#x}", self.raw())
162    }
163}
164
165impl PagingError {
166    pub fn alignment_error(msg: &'static str) -> Self {
167        Self::AlignmentError { details: msg }
168    }
169
170    pub fn mapping_conflict(vaddr: VirtAddr, existing_paddr: PhysAddr) -> Self {
171        Self::MappingConflict {
172            vaddr,
173            existing_paddr,
174        }
175    }
176
177    pub fn address_overflow(msg: &'static str) -> Self {
178        Self::AddressOverflow { details: msg }
179    }
180
181    pub fn invalid_size(msg: &'static str) -> Self {
182        Self::InvalidSize { details: msg }
183    }
184
185    pub fn hierarchy_error(msg: &'static str) -> Self {
186        Self::HierarchyError { details: msg }
187    }
188
189    pub fn invalid_range(msg: &'static str) -> Self {
190        Self::InvalidRange { details: msg }
191    }
192
193    pub fn not_mapped() -> Self {
194        Self::NotMapped
195    }
196}
197
198impl core::fmt::Debug for PagingError {
199    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
200        match self {
201            Self::NoMemory => write!(f, "NoMemory"),
202            Self::AlignmentError { details } => write!(f, "AlignmentError: {details}"),
203            Self::MappingConflict {
204                vaddr,
205                existing_paddr,
206            } => {
207                write!(
208                    f,
209                    "MappingConflict: vaddr={:#x}, existing_paddr={:#x}",
210                    vaddr.raw(),
211                    existing_paddr.raw()
212                )
213            }
214            Self::AddressOverflow { details } => write!(f, "AddressOverflow: {details}"),
215            Self::InvalidSize { details } => write!(f, "InvalidSize: {details}"),
216            Self::HierarchyError { details } => write!(f, "HierarchyError: {details}"),
217            Self::InvalidRange { details } => write!(f, "InvalidRange: {details}"),
218            Self::NotMapped => write!(f, "NotMapped"),
219        }
220    }
221}
222
223bitflags::bitflags! {
224    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
225    pub struct AccessFlags: usize {
226        const READ = 1;
227        const WRITE = 1<<2;
228        const EXECUTE = 1<<3;
229        const LOWER = 1<<4;
230    }
231}
232
233#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)]
234pub enum MemAttributes {
235    #[default]
236    Normal,
237    PerCpu,
238    Device,
239    Uncached,
240}
241
242#[derive(Clone, Copy, Debug, PartialEq, Eq)]
243pub struct MemConfig {
244    pub access: AccessFlags,
245    pub attrs: MemAttributes,
246}
247
248impl core::fmt::Display for MemConfig {
249    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
250        write!(
251            f,
252            "{}{}{}{}|{:?}",
253            if self.access.contains(AccessFlags::READ) {
254                "R"
255            } else {
256                "-"
257            },
258            if self.access.contains(AccessFlags::WRITE) {
259                "W"
260            } else {
261                "-"
262            },
263            if self.access.contains(AccessFlags::EXECUTE) {
264                "X"
265            } else {
266                "-"
267            },
268            if self.access.contains(AccessFlags::LOWER) {
269                "L"
270            } else {
271                "-"
272            },
273            self.attrs
274        )
275    }
276}
277
278#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
279pub struct PteConfig {
280    pub paddr: PhysAddr,
281    pub valid: bool,
282    pub read: bool,
283    pub writable: bool,
284    pub executable: bool,
285    pub lower: bool,
286    pub dirty: bool,
287    pub global: bool,
288    pub is_dir: bool,
289    pub huge: bool,
290    pub mem_attr: MemAttributes,
291}