1use crate::structures::paging::{
2 mapper::*,
3 page::AddressNotAligned,
4 page_table::{FrameError, PageTable, PageTableEntry, PageTableLevel},
5};
6
7#[derive(Debug)]
15pub struct MappedPageTable<'a, P: PageTableFrameMapping> {
16 page_table_walker: PageTableWalker<P>,
17 level_4_table: &'a mut PageTable,
18}
19
20impl<'a, P: PageTableFrameMapping> MappedPageTable<'a, P> {
21 #[inline]
31 pub unsafe fn new(level_4_table: &'a mut PageTable, page_table_frame_mapping: P) -> Self {
32 Self {
33 level_4_table,
34 page_table_walker: unsafe { PageTableWalker::new(page_table_frame_mapping) },
35 }
36 }
37
38 pub fn level_4_table(&self) -> &PageTable {
40 self.level_4_table
41 }
42
43 pub fn level_4_table_mut(&mut self) -> &mut PageTable {
45 self.level_4_table
46 }
47
48 pub fn page_table_frame_mapping(&self) -> &P {
50 &self.page_table_walker.page_table_frame_mapping
51 }
52}
53
54impl<P: PageTableFrameMapping> Mapper<Size1GiB> for MappedPageTable<'_, P> {
55 #[inline]
56 unsafe fn map_to_with_table_flags<A>(
57 &mut self,
58 page: Page<Size1GiB>,
59 frame: PhysFrame<Size1GiB>,
60 flags: PageTableFlags,
61 parent_table_flags: PageTableFlags,
62 allocator: &mut A,
63 ) -> Result<MapperFlush<Size1GiB>, MapToError<Size1GiB>>
64 where
65 A: FrameAllocator<Size4KiB> + ?Sized,
66 {
67 let p4 = &mut self.level_4_table;
68 let p3 = self.page_table_walker.create_next_table(
69 &mut p4[page.p4_index()],
70 parent_table_flags,
71 allocator,
72 )?;
73
74 if !p3[page.p3_index()].is_unused() {
75 return Err(MapToError::PageAlreadyMapped(frame));
76 }
77 p3[page.p3_index()].set_addr(frame.start_address(), flags | PageTableFlags::HUGE_PAGE);
78
79 Ok(MapperFlush::new(page))
80 }
81
82 fn unmap(
83 &mut self,
84 page: Page<Size1GiB>,
85 ) -> Result<(PhysFrame<Size1GiB>, MapperFlush<Size1GiB>), UnmapError> {
86 let p4 = &mut self.level_4_table;
87 let p3 = self
88 .page_table_walker
89 .next_table_mut(&mut p4[page.p4_index()])?;
90
91 let p3_entry = &mut p3[page.p3_index()];
92 let flags = p3_entry.flags();
93
94 if !flags.contains(PageTableFlags::PRESENT) {
95 return Err(UnmapError::PageNotMapped);
96 }
97 if !flags.contains(PageTableFlags::HUGE_PAGE) {
98 return Err(UnmapError::ParentEntryHugePage);
99 }
100
101 let frame = PhysFrame::from_start_address(p3_entry.addr())
102 .map_err(|AddressNotAligned| UnmapError::InvalidFrameAddress(p3_entry.addr()))?;
103
104 p3_entry.set_unused();
105 Ok((frame, MapperFlush::new(page)))
106 }
107
108 unsafe fn update_flags(
109 &mut self,
110 page: Page<Size1GiB>,
111 flags: PageTableFlags,
112 ) -> Result<MapperFlush<Size1GiB>, FlagUpdateError> {
113 let p4 = &mut self.level_4_table;
114 let p3 = self
115 .page_table_walker
116 .next_table_mut(&mut p4[page.p4_index()])?;
117
118 if p3[page.p3_index()].is_unused() {
119 return Err(FlagUpdateError::PageNotMapped);
120 }
121 p3[page.p3_index()].set_flags(flags | PageTableFlags::HUGE_PAGE);
122
123 Ok(MapperFlush::new(page))
124 }
125
126 unsafe fn set_flags_p4_entry(
127 &mut self,
128 page: Page<Size1GiB>,
129 flags: PageTableFlags,
130 ) -> Result<MapperFlushAll, FlagUpdateError> {
131 let p4 = &mut self.level_4_table;
132 let p4_entry = &mut p4[page.p4_index()];
133
134 if p4_entry.is_unused() {
135 return Err(FlagUpdateError::PageNotMapped);
136 }
137
138 p4_entry.set_flags(flags);
139
140 Ok(MapperFlushAll::new())
141 }
142
143 unsafe fn set_flags_p3_entry(
144 &mut self,
145 _page: Page<Size1GiB>,
146 _flags: PageTableFlags,
147 ) -> Result<MapperFlushAll, FlagUpdateError> {
148 Err(FlagUpdateError::ParentEntryHugePage)
149 }
150
151 unsafe fn set_flags_p2_entry(
152 &mut self,
153 _page: Page<Size1GiB>,
154 _flags: PageTableFlags,
155 ) -> Result<MapperFlushAll, FlagUpdateError> {
156 Err(FlagUpdateError::ParentEntryHugePage)
157 }
158
159 fn translate_page(&self, page: Page<Size1GiB>) -> Result<PhysFrame<Size1GiB>, TranslateError> {
160 let p4 = &self.level_4_table;
161 let p3 = self.page_table_walker.next_table(&p4[page.p4_index()])?;
162
163 let p3_entry = &p3[page.p3_index()];
164
165 if p3_entry.is_unused() {
166 return Err(TranslateError::PageNotMapped);
167 }
168
169 PhysFrame::from_start_address(p3_entry.addr())
170 .map_err(|AddressNotAligned| TranslateError::InvalidFrameAddress(p3_entry.addr()))
171 }
172}
173
174impl<P: PageTableFrameMapping> Mapper<Size2MiB> for MappedPageTable<'_, P> {
175 #[inline]
176 unsafe fn map_to_with_table_flags<A>(
177 &mut self,
178 page: Page<Size2MiB>,
179 frame: PhysFrame<Size2MiB>,
180 flags: PageTableFlags,
181 parent_table_flags: PageTableFlags,
182 allocator: &mut A,
183 ) -> Result<MapperFlush<Size2MiB>, MapToError<Size2MiB>>
184 where
185 A: FrameAllocator<Size4KiB> + ?Sized,
186 {
187 let p4 = &mut self.level_4_table;
188 let p3 = self.page_table_walker.create_next_table(
189 &mut p4[page.p4_index()],
190 parent_table_flags,
191 allocator,
192 )?;
193 let p2 = self.page_table_walker.create_next_table(
194 &mut p3[page.p3_index()],
195 parent_table_flags,
196 allocator,
197 )?;
198
199 if !p2[page.p2_index()].is_unused() {
200 return Err(MapToError::PageAlreadyMapped(frame));
201 }
202 p2[page.p2_index()].set_addr(frame.start_address(), flags | PageTableFlags::HUGE_PAGE);
203
204 Ok(MapperFlush::new(page))
205 }
206
207 fn unmap(
208 &mut self,
209 page: Page<Size2MiB>,
210 ) -> Result<(PhysFrame<Size2MiB>, MapperFlush<Size2MiB>), UnmapError> {
211 let p4 = &mut self.level_4_table;
212 let p3 = self
213 .page_table_walker
214 .next_table_mut(&mut p4[page.p4_index()])?;
215 let p2 = self
216 .page_table_walker
217 .next_table_mut(&mut p3[page.p3_index()])?;
218
219 let p2_entry = &mut p2[page.p2_index()];
220 let flags = p2_entry.flags();
221
222 if !flags.contains(PageTableFlags::PRESENT) {
223 return Err(UnmapError::PageNotMapped);
224 }
225 if !flags.contains(PageTableFlags::HUGE_PAGE) {
226 return Err(UnmapError::ParentEntryHugePage);
227 }
228
229 let frame = PhysFrame::from_start_address(p2_entry.addr())
230 .map_err(|AddressNotAligned| UnmapError::InvalidFrameAddress(p2_entry.addr()))?;
231
232 p2_entry.set_unused();
233 Ok((frame, MapperFlush::new(page)))
234 }
235
236 unsafe fn update_flags(
237 &mut self,
238 page: Page<Size2MiB>,
239 flags: PageTableFlags,
240 ) -> Result<MapperFlush<Size2MiB>, FlagUpdateError> {
241 let p4 = &mut self.level_4_table;
242 let p3 = self
243 .page_table_walker
244 .next_table_mut(&mut p4[page.p4_index()])?;
245 let p2 = self
246 .page_table_walker
247 .next_table_mut(&mut p3[page.p3_index()])?;
248
249 if p2[page.p2_index()].is_unused() {
250 return Err(FlagUpdateError::PageNotMapped);
251 }
252
253 p2[page.p2_index()].set_flags(flags | PageTableFlags::HUGE_PAGE);
254
255 Ok(MapperFlush::new(page))
256 }
257
258 unsafe fn set_flags_p4_entry(
259 &mut self,
260 page: Page<Size2MiB>,
261 flags: PageTableFlags,
262 ) -> Result<MapperFlushAll, FlagUpdateError> {
263 let p4 = &mut self.level_4_table;
264 let p4_entry = &mut p4[page.p4_index()];
265
266 if p4_entry.is_unused() {
267 return Err(FlagUpdateError::PageNotMapped);
268 }
269
270 p4_entry.set_flags(flags);
271
272 Ok(MapperFlushAll::new())
273 }
274
275 unsafe fn set_flags_p3_entry(
276 &mut self,
277 page: Page<Size2MiB>,
278 flags: PageTableFlags,
279 ) -> Result<MapperFlushAll, FlagUpdateError> {
280 let p4 = &mut self.level_4_table;
281 let p3 = self
282 .page_table_walker
283 .next_table_mut(&mut p4[page.p4_index()])?;
284 let p3_entry = &mut p3[page.p3_index()];
285
286 if p3_entry.is_unused() {
287 return Err(FlagUpdateError::PageNotMapped);
288 }
289
290 p3_entry.set_flags(flags);
291
292 Ok(MapperFlushAll::new())
293 }
294
295 unsafe fn set_flags_p2_entry(
296 &mut self,
297 _page: Page<Size2MiB>,
298 _flags: PageTableFlags,
299 ) -> Result<MapperFlushAll, FlagUpdateError> {
300 Err(FlagUpdateError::ParentEntryHugePage)
301 }
302
303 fn translate_page(&self, page: Page<Size2MiB>) -> Result<PhysFrame<Size2MiB>, TranslateError> {
304 let p4 = &self.level_4_table;
305 let p3 = self.page_table_walker.next_table(&p4[page.p4_index()])?;
306 let p2 = self.page_table_walker.next_table(&p3[page.p3_index()])?;
307
308 let p2_entry = &p2[page.p2_index()];
309
310 if p2_entry.is_unused() {
311 return Err(TranslateError::PageNotMapped);
312 }
313
314 PhysFrame::from_start_address(p2_entry.addr())
315 .map_err(|AddressNotAligned| TranslateError::InvalidFrameAddress(p2_entry.addr()))
316 }
317}
318
319impl<P: PageTableFrameMapping> Mapper<Size4KiB> for MappedPageTable<'_, P> {
320 #[inline]
321 unsafe fn map_to_with_table_flags<A>(
322 &mut self,
323 page: Page<Size4KiB>,
324 frame: PhysFrame<Size4KiB>,
325 flags: PageTableFlags,
326 parent_table_flags: PageTableFlags,
327 allocator: &mut A,
328 ) -> Result<MapperFlush<Size4KiB>, MapToError<Size4KiB>>
329 where
330 A: FrameAllocator<Size4KiB> + ?Sized,
331 {
332 let p4 = &mut self.level_4_table;
333 let p3 = self.page_table_walker.create_next_table(
334 &mut p4[page.p4_index()],
335 parent_table_flags,
336 allocator,
337 )?;
338 let p2 = self.page_table_walker.create_next_table(
339 &mut p3[page.p3_index()],
340 parent_table_flags,
341 allocator,
342 )?;
343 let p1 = self.page_table_walker.create_next_table(
344 &mut p2[page.p2_index()],
345 parent_table_flags,
346 allocator,
347 )?;
348
349 if !p1[page.p1_index()].is_unused() {
350 return Err(MapToError::PageAlreadyMapped(frame));
351 }
352 p1[page.p1_index()].set_frame(frame, flags);
353
354 Ok(MapperFlush::new(page))
355 }
356
357 fn unmap(
358 &mut self,
359 page: Page<Size4KiB>,
360 ) -> Result<(PhysFrame<Size4KiB>, MapperFlush<Size4KiB>), UnmapError> {
361 let p4 = &mut self.level_4_table;
362 let p3 = self
363 .page_table_walker
364 .next_table_mut(&mut p4[page.p4_index()])?;
365 let p2 = self
366 .page_table_walker
367 .next_table_mut(&mut p3[page.p3_index()])?;
368 let p1 = self
369 .page_table_walker
370 .next_table_mut(&mut p2[page.p2_index()])?;
371
372 let p1_entry = &mut p1[page.p1_index()];
373
374 let frame = p1_entry.frame().map_err(|err| match err {
375 FrameError::FrameNotPresent => UnmapError::PageNotMapped,
376 FrameError::HugeFrame => UnmapError::ParentEntryHugePage,
377 })?;
378
379 p1_entry.set_unused();
380 Ok((frame, MapperFlush::new(page)))
381 }
382
383 unsafe fn update_flags(
384 &mut self,
385 page: Page<Size4KiB>,
386 flags: PageTableFlags,
387 ) -> Result<MapperFlush<Size4KiB>, FlagUpdateError> {
388 let p4 = &mut self.level_4_table;
389 let p3 = self
390 .page_table_walker
391 .next_table_mut(&mut p4[page.p4_index()])?;
392 let p2 = self
393 .page_table_walker
394 .next_table_mut(&mut p3[page.p3_index()])?;
395 let p1 = self
396 .page_table_walker
397 .next_table_mut(&mut p2[page.p2_index()])?;
398
399 if p1[page.p1_index()].is_unused() {
400 return Err(FlagUpdateError::PageNotMapped);
401 }
402
403 p1[page.p1_index()].set_flags(flags);
404
405 Ok(MapperFlush::new(page))
406 }
407
408 unsafe fn set_flags_p4_entry(
409 &mut self,
410 page: Page<Size4KiB>,
411 flags: PageTableFlags,
412 ) -> Result<MapperFlushAll, FlagUpdateError> {
413 let p4 = &mut self.level_4_table;
414 let p4_entry = &mut p4[page.p4_index()];
415
416 if p4_entry.is_unused() {
417 return Err(FlagUpdateError::PageNotMapped);
418 }
419
420 p4_entry.set_flags(flags);
421
422 Ok(MapperFlushAll::new())
423 }
424
425 unsafe fn set_flags_p3_entry(
426 &mut self,
427 page: Page<Size4KiB>,
428 flags: PageTableFlags,
429 ) -> Result<MapperFlushAll, FlagUpdateError> {
430 let p4 = &mut self.level_4_table;
431 let p3 = self
432 .page_table_walker
433 .next_table_mut(&mut p4[page.p4_index()])?;
434 let p3_entry = &mut p3[page.p3_index()];
435
436 if p3_entry.is_unused() {
437 return Err(FlagUpdateError::PageNotMapped);
438 }
439
440 p3_entry.set_flags(flags);
441
442 Ok(MapperFlushAll::new())
443 }
444
445 unsafe fn set_flags_p2_entry(
446 &mut self,
447 page: Page<Size4KiB>,
448 flags: PageTableFlags,
449 ) -> Result<MapperFlushAll, FlagUpdateError> {
450 let p4 = &mut self.level_4_table;
451 let p3 = self
452 .page_table_walker
453 .next_table_mut(&mut p4[page.p4_index()])?;
454 let p2 = self
455 .page_table_walker
456 .next_table_mut(&mut p3[page.p3_index()])?;
457 let p2_entry = &mut p2[page.p2_index()];
458
459 if p2_entry.is_unused() {
460 return Err(FlagUpdateError::PageNotMapped);
461 }
462
463 p2_entry.set_flags(flags);
464
465 Ok(MapperFlushAll::new())
466 }
467
468 fn translate_page(&self, page: Page<Size4KiB>) -> Result<PhysFrame<Size4KiB>, TranslateError> {
469 let p4 = &self.level_4_table;
470 let p3 = self.page_table_walker.next_table(&p4[page.p4_index()])?;
471 let p2 = self.page_table_walker.next_table(&p3[page.p3_index()])?;
472 let p1 = self.page_table_walker.next_table(&p2[page.p2_index()])?;
473
474 let p1_entry = &p1[page.p1_index()];
475
476 if p1_entry.is_unused() {
477 return Err(TranslateError::PageNotMapped);
478 }
479
480 PhysFrame::from_start_address(p1_entry.addr())
481 .map_err(|AddressNotAligned| TranslateError::InvalidFrameAddress(p1_entry.addr()))
482 }
483}
484
485impl<P: PageTableFrameMapping> Translate for MappedPageTable<'_, P> {
486 #[allow(clippy::inconsistent_digit_grouping)]
487 fn translate(&self, addr: VirtAddr) -> TranslateResult {
488 let p4 = &self.level_4_table;
489 let p3 = match self.page_table_walker.next_table(&p4[addr.p4_index()]) {
490 Ok(page_table) => page_table,
491 Err(PageTableWalkError::NotMapped) => return TranslateResult::NotMapped,
492 Err(PageTableWalkError::MappedToHugePage) => {
493 panic!("level 4 entry has huge page bit set")
494 }
495 };
496 let p2 = match self.page_table_walker.next_table(&p3[addr.p3_index()]) {
497 Ok(page_table) => page_table,
498 Err(PageTableWalkError::NotMapped) => return TranslateResult::NotMapped,
499 Err(PageTableWalkError::MappedToHugePage) => {
500 let entry = &p3[addr.p3_index()];
501 let frame = PhysFrame::containing_address(entry.addr());
502 #[allow(clippy::unusual_byte_groupings)]
503 let offset = addr.as_u64() & 0o_777_777_7777;
504 let flags = entry.flags();
505 return TranslateResult::Mapped {
506 frame: MappedFrame::Size1GiB(frame),
507 offset,
508 flags,
509 };
510 }
511 };
512 let p1 = match self.page_table_walker.next_table(&p2[addr.p2_index()]) {
513 Ok(page_table) => page_table,
514 Err(PageTableWalkError::NotMapped) => return TranslateResult::NotMapped,
515 Err(PageTableWalkError::MappedToHugePage) => {
516 let entry = &p2[addr.p2_index()];
517 let frame = PhysFrame::containing_address(entry.addr());
518 #[allow(clippy::unusual_byte_groupings)]
519 let offset = addr.as_u64() & 0o_777_7777;
520 let flags = entry.flags();
521 return TranslateResult::Mapped {
522 frame: MappedFrame::Size2MiB(frame),
523 offset,
524 flags,
525 };
526 }
527 };
528
529 let p1_entry = &p1[addr.p1_index()];
530
531 if p1_entry.is_unused() {
532 return TranslateResult::NotMapped;
533 }
534
535 let frame = match PhysFrame::from_start_address(p1_entry.addr()) {
536 Ok(frame) => frame,
537 Err(AddressNotAligned) => return TranslateResult::InvalidFrameAddress(p1_entry.addr()),
538 };
539 let offset = u64::from(addr.page_offset());
540 let flags = p1_entry.flags();
541 TranslateResult::Mapped {
542 frame: MappedFrame::Size4KiB(frame),
543 offset,
544 flags,
545 }
546 }
547}
548
549impl<P: PageTableFrameMapping> CleanUp for MappedPageTable<'_, P> {
550 #[inline]
551 unsafe fn clean_up<D>(&mut self, frame_deallocator: &mut D)
552 where
553 D: FrameDeallocator<Size4KiB>,
554 {
555 unsafe {
556 self.clean_up_addr_range(
557 PageRangeInclusive {
558 start: Page::from_start_address(VirtAddr::new(0)).unwrap(),
559 end: Page::from_start_address(VirtAddr::new(0xffff_ffff_ffff_f000)).unwrap(),
560 },
561 frame_deallocator,
562 )
563 }
564 }
565
566 unsafe fn clean_up_addr_range<D>(
567 &mut self,
568 range: PageRangeInclusive,
569 frame_deallocator: &mut D,
570 ) where
571 D: FrameDeallocator<Size4KiB>,
572 {
573 unsafe fn clean_up<P: PageTableFrameMapping>(
574 page_table: &mut PageTable,
575 page_table_walker: &PageTableWalker<P>,
576 level: PageTableLevel,
577 range: PageRangeInclusive,
578 frame_deallocator: &mut impl FrameDeallocator<Size4KiB>,
579 ) -> bool {
580 if range.is_empty() {
581 return false;
582 }
583
584 let table_addr = range
585 .start
586 .start_address()
587 .align_down(level.table_address_space_alignment());
588
589 let start = range.start.page_table_index(level);
590 let end = range.end.page_table_index(level);
591
592 if let Some(next_level) = level.next_lower_level() {
593 let offset_per_entry = level.entry_address_space_alignment();
594 for (i, entry) in page_table
595 .iter_mut()
596 .enumerate()
597 .take(usize::from(end) + 1)
598 .skip(usize::from(start))
599 {
600 if let Ok(page_table) = page_table_walker.next_table_mut(entry) {
601 let start = VirtAddr::forward_checked_impl(
602 table_addr,
603 (offset_per_entry as usize) * i,
604 )
605 .unwrap();
606 let end = start + (offset_per_entry - 1);
607 let start = Page::<Size4KiB>::containing_address(start);
608 let start = start.max(range.start);
609 let end = Page::<Size4KiB>::containing_address(end);
610 let end = end.min(range.end);
611 unsafe {
612 if clean_up(
613 page_table,
614 page_table_walker,
615 next_level,
616 Page::range_inclusive(start, end),
617 frame_deallocator,
618 ) {
619 let frame = entry.frame().unwrap();
620 entry.set_unused();
621 frame_deallocator.deallocate_frame(frame);
622 }
623 }
624 }
625 }
626 }
627
628 page_table.iter().all(PageTableEntry::is_unused)
629 }
630
631 unsafe {
632 clean_up(
633 self.level_4_table,
634 &self.page_table_walker,
635 PageTableLevel::Four,
636 range,
637 frame_deallocator,
638 );
639 }
640 }
641}
642
643#[derive(Debug)]
644struct PageTableWalker<P: PageTableFrameMapping> {
645 page_table_frame_mapping: P,
646}
647
648impl<P: PageTableFrameMapping> PageTableWalker<P> {
649 #[inline]
650 pub unsafe fn new(page_table_frame_mapping: P) -> Self {
651 Self {
652 page_table_frame_mapping,
653 }
654 }
655
656 #[inline]
662 fn next_table<'b>(
663 &self,
664 entry: &'b PageTableEntry,
665 ) -> Result<&'b PageTable, PageTableWalkError> {
666 let page_table_ptr = self
667 .page_table_frame_mapping
668 .frame_to_pointer(entry.frame()?);
669 let page_table: &PageTable = unsafe { &*page_table_ptr };
670
671 Ok(page_table)
672 }
673
674 #[inline]
680 fn next_table_mut<'b>(
681 &self,
682 entry: &'b mut PageTableEntry,
683 ) -> Result<&'b mut PageTable, PageTableWalkError> {
684 let page_table_ptr = self
685 .page_table_frame_mapping
686 .frame_to_pointer(entry.frame()?);
687 let page_table: &mut PageTable = unsafe { &mut *page_table_ptr };
688
689 Ok(page_table)
690 }
691
692 fn create_next_table<'b, A>(
702 &self,
703 entry: &'b mut PageTableEntry,
704 insert_flags: PageTableFlags,
705 allocator: &mut A,
706 ) -> Result<&'b mut PageTable, PageTableCreateError>
707 where
708 A: FrameAllocator<Size4KiB> + ?Sized,
709 {
710 let created;
711
712 if entry.is_unused() {
713 if let Some(frame) = allocator.allocate_frame() {
714 entry.set_frame(frame, insert_flags);
715 created = true;
716 } else {
717 return Err(PageTableCreateError::FrameAllocationFailed);
718 }
719 } else {
720 if !insert_flags.is_empty() && !entry.flags().contains(insert_flags) {
721 entry.set_flags(entry.flags() | insert_flags);
722 }
723 created = false;
724 }
725
726 let page_table = match self.next_table_mut(entry) {
727 Err(PageTableWalkError::MappedToHugePage) => {
728 return Err(PageTableCreateError::MappedToHugePage);
729 }
730 Err(PageTableWalkError::NotMapped) => panic!("entry should be mapped at this point"),
731 Ok(page_table) => page_table,
732 };
733
734 if created {
735 page_table.zero();
736 }
737 Ok(page_table)
738 }
739}
740
741#[derive(Debug)]
742enum PageTableWalkError {
743 NotMapped,
744 MappedToHugePage,
745}
746
747#[derive(Debug)]
748enum PageTableCreateError {
749 MappedToHugePage,
750 FrameAllocationFailed,
751}
752
753impl From<PageTableCreateError> for MapToError<Size4KiB> {
754 #[inline]
755 fn from(err: PageTableCreateError) -> Self {
756 match err {
757 PageTableCreateError::MappedToHugePage => MapToError::ParentEntryHugePage,
758 PageTableCreateError::FrameAllocationFailed => MapToError::FrameAllocationFailed,
759 }
760 }
761}
762
763impl From<PageTableCreateError> for MapToError<Size2MiB> {
764 #[inline]
765 fn from(err: PageTableCreateError) -> Self {
766 match err {
767 PageTableCreateError::MappedToHugePage => MapToError::ParentEntryHugePage,
768 PageTableCreateError::FrameAllocationFailed => MapToError::FrameAllocationFailed,
769 }
770 }
771}
772
773impl From<PageTableCreateError> for MapToError<Size1GiB> {
774 #[inline]
775 fn from(err: PageTableCreateError) -> Self {
776 match err {
777 PageTableCreateError::MappedToHugePage => MapToError::ParentEntryHugePage,
778 PageTableCreateError::FrameAllocationFailed => MapToError::FrameAllocationFailed,
779 }
780 }
781}
782
783impl From<FrameError> for PageTableWalkError {
784 #[inline]
785 fn from(err: FrameError) -> Self {
786 match err {
787 FrameError::HugeFrame => PageTableWalkError::MappedToHugePage,
788 FrameError::FrameNotPresent => PageTableWalkError::NotMapped,
789 }
790 }
791}
792
793impl From<PageTableWalkError> for UnmapError {
794 #[inline]
795 fn from(err: PageTableWalkError) -> Self {
796 match err {
797 PageTableWalkError::MappedToHugePage => UnmapError::ParentEntryHugePage,
798 PageTableWalkError::NotMapped => UnmapError::PageNotMapped,
799 }
800 }
801}
802
803impl From<PageTableWalkError> for FlagUpdateError {
804 #[inline]
805 fn from(err: PageTableWalkError) -> Self {
806 match err {
807 PageTableWalkError::MappedToHugePage => FlagUpdateError::ParentEntryHugePage,
808 PageTableWalkError::NotMapped => FlagUpdateError::PageNotMapped,
809 }
810 }
811}
812
813impl From<PageTableWalkError> for TranslateError {
814 #[inline]
815 fn from(err: PageTableWalkError) -> Self {
816 match err {
817 PageTableWalkError::MappedToHugePage => TranslateError::ParentEntryHugePage,
818 PageTableWalkError::NotMapped => TranslateError::PageNotMapped,
819 }
820 }
821}
822
823pub unsafe trait PageTableFrameMapping {
833 fn frame_to_pointer(&self, frame: PhysFrame) -> *mut PageTable;
835}
836
837unsafe impl<P: PageTableFrameMapping + ?Sized> PageTableFrameMapping for &P {
838 #[inline]
839 fn frame_to_pointer(&self, frame: PhysFrame) -> *mut PageTable {
840 (**self).frame_to_pointer(frame)
841 }
842}