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}