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 \
136 {existing_paddr:#x}"
137 )]
138 MappingConflict {
139 vaddr: VirtAddr,
140 existing_paddr: PhysAddr,
141 },
142 #[error("Address overflow detected: {details}")]
143 AddressOverflow { details: &'static str },
144 #[error("Invalid mapping size: {details}")]
145 InvalidSize { details: &'static str },
146 #[error("Page table hierarchy error: {details}")]
147 HierarchyError { details: &'static str },
148 #[error("Invalid address range: {details}")]
149 InvalidRange { details: &'static str },
150 #[error("Address not mapped")]
151 NotMapped,
152}
153
154impl core::fmt::LowerHex for VirtAddr {
155 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
156 write!(f, "{:#x}", self.raw())
157 }
158}
159
160impl core::fmt::LowerHex for PhysAddr {
161 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
162 write!(f, "{:#x}", self.raw())
163 }
164}
165
166impl PagingError {
167 pub fn alignment_error(msg: &'static str) -> Self {
168 Self::AlignmentError { details: msg }
169 }
170
171 pub fn mapping_conflict(vaddr: VirtAddr, existing_paddr: PhysAddr) -> Self {
172 Self::MappingConflict {
173 vaddr,
174 existing_paddr,
175 }
176 }
177
178 pub fn address_overflow(msg: &'static str) -> Self {
179 Self::AddressOverflow { details: msg }
180 }
181
182 pub fn invalid_size(msg: &'static str) -> Self {
183 Self::InvalidSize { details: msg }
184 }
185
186 pub fn hierarchy_error(msg: &'static str) -> Self {
187 Self::HierarchyError { details: msg }
188 }
189
190 pub fn invalid_range(msg: &'static str) -> Self {
191 Self::InvalidRange { details: msg }
192 }
193
194 pub fn not_mapped() -> Self {
195 Self::NotMapped
196 }
197}
198
199impl core::fmt::Debug for PagingError {
200 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
201 match self {
202 Self::NoMemory => write!(f, "NoMemory"),
203 Self::AlignmentError { details } => write!(f, "AlignmentError: {details}"),
204 Self::MappingConflict {
205 vaddr,
206 existing_paddr,
207 } => {
208 write!(
209 f,
210 "MappingConflict: vaddr={:#x}, existing_paddr={:#x}",
211 vaddr.raw(),
212 existing_paddr.raw()
213 )
214 }
215 Self::AddressOverflow { details } => write!(f, "AddressOverflow: {details}"),
216 Self::InvalidSize { details } => write!(f, "InvalidSize: {details}"),
217 Self::HierarchyError { details } => write!(f, "HierarchyError: {details}"),
218 Self::InvalidRange { details } => write!(f, "InvalidRange: {details}"),
219 Self::NotMapped => write!(f, "NotMapped"),
220 }
221 }
222}
223
224bitflags::bitflags! {
225 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
226 pub struct AccessFlags: usize {
227 const READ = 1;
228 const WRITE = 1<<2;
229 const EXECUTE = 1<<3;
230 const LOWER = 1<<4;
231 }
232}
233
234#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)]
235pub enum MemAttributes {
236 #[default]
237 Normal,
238 PerCpu,
239 Device,
240 Uncached,
241}
242
243#[derive(Clone, Copy, Debug, PartialEq, Eq)]
244pub struct MemConfig {
245 pub access: AccessFlags,
246 pub attrs: MemAttributes,
247}
248
249impl core::fmt::Display for MemConfig {
250 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
251 write!(
252 f,
253 "{}{}{}{}|{:?}",
254 if self.access.contains(AccessFlags::READ) {
255 "R"
256 } else {
257 "-"
258 },
259 if self.access.contains(AccessFlags::WRITE) {
260 "W"
261 } else {
262 "-"
263 },
264 if self.access.contains(AccessFlags::EXECUTE) {
265 "X"
266 } else {
267 "-"
268 },
269 if self.access.contains(AccessFlags::LOWER) {
270 "L"
271 } else {
272 "-"
273 },
274 self.attrs
275 )
276 }
277}
278
279#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
280pub struct PteConfig {
281 pub paddr: PhysAddr,
282 pub valid: bool,
283 pub read: bool,
284 pub writable: bool,
285 pub executable: bool,
286 pub lower: bool,
287 pub dirty: bool,
288 pub global: bool,
289 pub is_dir: bool,
290 pub huge: bool,
291 pub mem_attr: MemAttributes,
292}