1#![stable(feature = "kernel_core_api", since = "1.0.0")]
4
5#[cfg(feature = "full")]
6pub mod allocator;
7#[cfg(feature = "full")]
8pub mod heap;
9mod type_ops;
10#[cfg(feature = "full")]
11pub mod r#virtual;
12#[cfg(all(not(feature = "use_std"), feature = "full"))]
13pub mod mapping;
14#[cfg(feature = "full")]
15pub mod physical;
16
17#[derive(Debug, Copy, Clone, Eq, PartialEq)]
19#[stable(feature = "kernel_core_api", since = "1.0.0")]
20pub struct AllocError;
21
22const PAGE_SIZE: usize = 4096;
23const PAGE_MAP_OFFSET: usize = 0xffff_8000_0000_0000;
24
25#[stable(feature = "kernel_core_api", since = "1.0.0")]
27#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
28#[repr(transparent)]
29pub struct Frame {
30 base: PhysicalAddress<PAGE_SIZE>
31}
32
33#[stable(feature = "kernel_core_api", since = "1.0.0")]
35#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
36#[repr(transparent)]
37pub struct Page {
38 base: VirtualAddress<PAGE_SIZE>
39}
40
41#[stable(feature = "kernel_core_api", since = "1.0.0")]
44#[derive(Debug, Copy, Clone, Eq, Ord)]
45#[repr(transparent)]
46pub struct PhysicalAddress<const ALIGN: usize = 1> {
47 #[unstable(feature = "kernel_memory_addr_access", issue = "none")]
48 pub addr: usize
49}
50
51#[stable(feature = "kernel_core_api", since = "1.0.0")]
53#[derive(Debug, Copy, Clone, Eq, Ord)]
54#[repr(transparent)]
55pub struct VirtualAddress<const ALIGN: usize = 1> {
56 #[unstable(feature = "kernel_memory_addr_access", issue = "none")]
57 pub addr: usize
58}
59
60impl<const ALIGN: usize> PhysicalAddress<ALIGN> {
61 #[stable(feature = "kernel_core_api", since = "1.0.0")]
63 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
64 #[track_caller]
65 pub const fn new(addr: usize) -> Self {
66 let unaligned: PhysicalAddress = PhysicalAddress { addr };
67 let aligned = unaligned.align_down();
68
69 if aligned.addr != unaligned.addr { panic!("Address not aligned"); }
70
71 aligned
72 }
73
74 #[unstable(feature = "kernel_physical_page_offset", issue = "1")]
76 pub const fn to_virtual(self) -> VirtualAddress<ALIGN> {
77 VirtualAddress {
78 addr: self.addr + PAGE_MAP_OFFSET
79 }
80 }
81
82 #[stable(feature = "kernel_core_api", since = "1.0.0")]
86 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
87 pub const unsafe fn align_unchecked<const NEW_ALIGN: usize>(self) -> PhysicalAddress<NEW_ALIGN> {
88 PhysicalAddress {
89 .. self
90 }
91 }
92
93 #[stable(feature = "kernel_core_api", since = "1.0.0")]
95 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
96 pub const fn align_down<const NEW_ALIGN: usize>(self) -> PhysicalAddress<NEW_ALIGN> {
97 PhysicalAddress {
98 addr: self.addr & !(NEW_ALIGN - 1)
99 }
100 }
101
102 #[stable(feature = "kernel_core_api", since = "1.0.0")]
104 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
105 pub const fn align_up<const NEW_ALIGN: usize>(self) -> PhysicalAddress<NEW_ALIGN> {
106 let a: PhysicalAddress = PhysicalAddress {
108 addr: self.addr + NEW_ALIGN - 1
109 };
110 a.align_down()
111 }
112
113 #[unstable(feature = "kernel_address_alignment_runtime", issue = "none")]
115 pub const fn align_down_runtime(self, new_alignment: usize) -> PhysicalAddress<1> {
116 PhysicalAddress {
117 addr: self.addr & !(new_alignment - 1)
118 }
119 }
120
121 #[unstable(feature = "kernel_address_alignment_runtime", issue = "none")]
123 pub const fn align_up_runtime(self, new_alignment: usize) -> PhysicalAddress<1> {
124 let a: PhysicalAddress = PhysicalAddress {
125 addr: self.addr + new_alignment - 1
126 };
127 a.align_down_runtime(new_alignment)
128 }
129}
130
131impl Frame {
132 #[unstable(feature = "kernel_physical_page_offset", issue = "1")]
134 pub const fn to_page(&self) -> Page {
135 Page {
136 base: self.base.to_virtual()
137 }
138 }
139
140 #[unstable(feature = "kernel_frame_zero", issue = "none")]
142 pub const fn zero() -> Frame {
143 Frame::new(PhysicalAddress::new(0))
144 }
145
146 #[stable(feature = "kernel_core_api", since = "1.0.0")]
148 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
149 pub const fn new(base: PhysicalAddress<PAGE_SIZE>) -> Self {
150 Self { base }
151 }
152
153 #[stable(feature = "kernel_core_api", since = "1.0.0")]
155 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
156 pub const fn checked_sub(&self, rhs: usize) -> Option<Self> {
157 match self.base.addr.checked_sub(rhs * PAGE_SIZE) {
159 Some(addr) => Some(Self {
160 base: PhysicalAddress::new(addr)
161 }),
162 None => None
163 }
164 }
165
166 #[stable(feature = "kernel_core_api", since = "1.0.0")]
168 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
169 pub const fn start(&self) -> PhysicalAddress<PAGE_SIZE> {
170 self.base
171 }
172
173 #[stable(feature = "kernel_core_api", since = "1.0.0")]
175 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
176 pub const fn end(&self) -> PhysicalAddress<PAGE_SIZE> {
177 PhysicalAddress::<4096>::new(self.base.addr + PAGE_SIZE)
179 }
180}
181
182impl<const ALIGN: usize> VirtualAddress<ALIGN> {
183 #[stable(feature = "kernel_core_api", since = "1.0.0")]
185 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
186 #[track_caller]
187 pub const fn new(addr: usize) -> Self {
188 let unaligned: VirtualAddress = VirtualAddress { addr };
189 let aligned = unaligned.align_down();
190
191 if aligned.addr != unaligned.addr { panic!("Address not aligned"); }
192
193 aligned
194 }
195
196 #[stable(feature = "kernel_core_api", since = "1.0.0")]
198 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
199 pub const fn as_ptr(self) -> *mut u8 {
200 self.addr as _
201 }
202
203 #[stable(feature = "kernel_core_api", since = "1.0.0")]
207 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
208 pub const unsafe fn align_unchecked<const NEW_ALIGN: usize>(self) -> VirtualAddress<NEW_ALIGN> {
209 VirtualAddress {
210 .. self
211 }
212 }
213
214 #[stable(feature = "kernel_core_api", since = "1.0.0")]
216 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
217 pub const fn align_down<const NEW_ALIGN: usize>(self) -> VirtualAddress<NEW_ALIGN> {
218 VirtualAddress {
219 addr: self.addr & !(NEW_ALIGN - 1)
220 }
221 }
222
223 #[stable(feature = "kernel_core_api", since = "1.0.0")]
225 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
226 pub const fn align_up<const NEW_ALIGN: usize>(self) -> VirtualAddress<NEW_ALIGN> {
227 let a: VirtualAddress = VirtualAddress {
229 addr: self.addr + NEW_ALIGN - 1
230 };
231 a.align_down()
232 }
233
234 #[unstable(feature = "kernel_address_alignment_runtime", issue = "none")]
236 pub const fn align_down_runtime(self, new_alignment: usize) -> VirtualAddress<1> {
237 VirtualAddress {
238 addr: self.addr & !(new_alignment - 1)
239 }
240 }
241
242 #[unstable(feature = "kernel_address_alignment_runtime", issue = "none")]
244 pub const fn align_up_runtime(self, new_alignment: usize) -> VirtualAddress<1> {
245 let a: VirtualAddress = VirtualAddress {
246 addr: self.addr + new_alignment - 1
247 };
248 a.align_down_runtime(new_alignment)
249 }
250
251 #[track_caller]
252 #[unstable(feature = "kernel_address_alignment_runtime", issue = "none")]
253 pub const fn aligned<const N: usize>(self) -> VirtualAddress<N> {
254 VirtualAddress::new(self.addr)
255 }
256}
257
258impl Page {
259 #[stable(feature = "kernel_core_api", since = "1.0.0")]
261 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
262 pub const fn as_ptr(&self) -> *mut u8 {
263 self.base.as_ptr()
264 }
265
266 #[stable(feature = "kernel_core_api", since = "1.0.0")]
268 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
269 pub const fn new(base: VirtualAddress<PAGE_SIZE>) -> Self {
270 Self { base }
271 }
272
273 #[stable(feature = "kernel_core_api", since = "1.0.0")]
275 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
276 pub const fn start(&self) -> VirtualAddress<PAGE_SIZE> {
277 self.base
278 }
279
280 #[stable(feature = "kernel_core_api", since = "1.0.0")]
282 #[rustc_const_stable(feature = "kernel_core_api", since = "1.0.0")]
283 pub const fn end(&self) -> VirtualAddress<PAGE_SIZE> {
284 VirtualAddress::<4096>::new(self.base.addr + PAGE_SIZE)
286 }
287}
288
289#[stable(feature = "kernel_core_api", since = "1.0.0")]
290impl<T: ?Sized> From<*mut T> for VirtualAddress<1> {
291 fn from(value: *mut T) -> Self {
292 VirtualAddress { addr: value as *mut u8 as usize }
293 }
294}
295
296#[stable(feature = "kernel_core_api", since = "1.0.0")]
297impl<T: ?Sized> From<*const T> for VirtualAddress<1> {
298 fn from(value: *const T) -> Self {
299 VirtualAddress { addr: value as *const u8 as usize }
300 }
301}
302
303#[cfg(test)]
304mod tests {
305 use super::*;
306
307 #[test]
308 fn align_down() {
309 let unaligned: VirtualAddress = VirtualAddress { addr: 0x1567 };
310 let aligned = unaligned.align_down::<4096>();
311 assert_eq!(aligned.addr, 0x1000);
312
313 let unaligned: VirtualAddress = VirtualAddress { addr: 0x2000 };
314 let aligned = unaligned.align_down::<4096>();
315 assert_eq!(aligned.addr, 0x2000);
316
317 let unaligned: PhysicalAddress = PhysicalAddress { addr: 0x1567 };
318 let aligned = unaligned.align_down::<4096>();
319 assert_eq!(aligned.addr, 0x1000);
320
321 let unaligned: PhysicalAddress = PhysicalAddress { addr: 0x2000 };
322 let aligned = unaligned.align_down::<4096>();
323 assert_eq!(aligned.addr, 0x2000);
324 }
325
326 #[test]
327 fn align_up() {
328 let unaligned: VirtualAddress = VirtualAddress { addr: 0x1567 };
329 let aligned = unaligned.align_up::<4096>();
330 assert_eq!(aligned.addr, 0x2000);
331
332 let unaligned: VirtualAddress = VirtualAddress { addr: 0x2000 };
333 let aligned = unaligned.align_up::<4096>();
334 assert_eq!(aligned.addr, 0x2000);
335
336 let unaligned: PhysicalAddress = PhysicalAddress { addr: 0x1567 };
337 let aligned = unaligned.align_up::<4096>();
338 assert_eq!(aligned.addr, 0x2000);
339
340 let unaligned: PhysicalAddress = PhysicalAddress { addr: 0x2000 };
341 let aligned = unaligned.align_up::<4096>();
342 assert_eq!(aligned.addr, 0x2000);
343 }
344}