From 40f5d9a05f95d31a263b3e7418c91e83b18cfd29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Fri, 16 Jan 2026 19:09:40 +0100 Subject: [PATCH 1/2] build(deps): upgrade x86_64 to 0.16 --- Cargo.lock | 22 +++++++++++++---- Cargo.toml | 2 +- src/arch/x86_64/kernel/core_local.rs | 4 +++- src/arch/x86_64/kernel/processor.rs | 8 +++++-- src/arch/x86_64/mm/paging.rs | 35 +++++++++++++++++----------- src/mm/virtualmem.rs | 2 +- src/scheduler/mod.rs | 6 +++-- 7 files changed, 53 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93b1a23759..e5bbeee2f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -724,7 +724,7 @@ checksum = "6b3851f0f5ba054c215f5d3d9f1b60727db9e7dcfe80712485875de01ba299d9" dependencies = [ "align-address 0.4.0", "smallvec", - "x86_64", + "x86_64 0.15.5", ] [[package]] @@ -945,7 +945,7 @@ dependencies = [ "uhyve-interface", "virtio-spec", "volatile 0.6.1", - "x86_64", + "x86_64 0.16.0-rc.0", "zerocopy", "zeroize", ] @@ -1199,7 +1199,7 @@ checksum = "a33ce19da78c437cf69f8c3265a77ca61e08395678b7b9eac42039add3f4f4fb" dependencies = [ "align-address 0.4.0", "cfg-if", - "x86_64", + "x86_64 0.15.5", ] [[package]] @@ -1913,7 +1913,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93950c9f0fb7d6d36ae73ac4326be946b81816f8559bf10a01087064e2dd4509" dependencies = [ "raw-cpuid", - "x86_64", + "x86_64 0.15.5", ] [[package]] @@ -1942,7 +1942,7 @@ dependencies = [ "hermit-abi", "memory_addresses 0.4.0", "num_enum", - "x86_64", + "x86_64 0.15.5", ] [[package]] @@ -2357,6 +2357,18 @@ dependencies = [ "volatile 0.4.6", ] +[[package]] +name = "x86_64" +version = "0.16.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11c3c6a22235681979011629276e06d94bed726762bcc9b870f08f56a20c8e50" +dependencies = [ + "bit_field", + "bitflags 2.13.1", + "const_fn", + "volatile 0.4.6", +] + [[package]] name = "xattr" version = "1.6.1" diff --git a/Cargo.toml b/Cargo.toml index 47756e31a6..566edcecc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -416,7 +416,7 @@ free-list = { version = "0.3", features = ["x86_64"] } memory_addresses = { version = "0.4", default-features = false, features = ["x86_64", "conv-x86_64"] } raw-cpuid = "11" uart_16550 = { version = "0.8", features = ["embedded-io"] } -x86_64 = { version = "0.15", default-features = false, features = ["instructions", "abi_x86_interrupt"] } +x86_64 = { version = "0.16.0-rc.0", default-features = false, features = ["instructions", "abi_x86_interrupt"] } [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64-cpu = "11" diff --git a/src/arch/x86_64/kernel/core_local.rs b/src/arch/x86_64/kernel/core_local.rs index 000b07ca26..fdedf779bc 100644 --- a/src/arch/x86_64/kernel/core_local.rs +++ b/src/arch/x86_64/kernel/core_local.rs @@ -72,7 +72,9 @@ impl CoreLocal { }; this.this = ptr::from_ref(this); - GsBase::write(VirtAddr::from_ptr(this)); + unsafe { + GsBase::write(VirtAddr::from_ptr(this)); + } } #[inline] diff --git a/src/arch/x86_64/kernel/processor.rs b/src/arch/x86_64/kernel/processor.rs index 9eb6c7c8b6..e9faf4fd1c 100644 --- a/src/arch/x86_64/kernel/processor.rs +++ b/src/arch/x86_64/kernel/processor.rs @@ -1136,7 +1136,9 @@ pub fn writefs(fs: usize) { FS::write_base(base); } } else { - FsBase::write(base); + unsafe { + FsBase::write(base); + } } } @@ -1148,7 +1150,9 @@ pub fn writegs(gs: usize) { GS::write_base(base); } } else { - GsBase::write(base); + unsafe { + GsBase::write(base); + } } } diff --git a/src/arch/x86_64/mm/paging.rs b/src/arch/x86_64/mm/paging.rs index f041cfd826..02b15d9de0 100644 --- a/src/arch/x86_64/mm/paging.rs +++ b/src/arch/x86_64/mm/paging.rs @@ -27,7 +27,7 @@ unsafe impl FrameAllocator for FrameAlloc { let range = FrameAlloc::allocate(layout).ok()?; let phys_addr = PhysAddr::from(range.start()); - Some(PhysFrame::from_start_address(phys_addr.into()).unwrap()) + Some(PhysFrame::from_start_address(x86_64::PhysAddr::new(phys_addr.as_u64())).unwrap()) } } @@ -111,7 +111,7 @@ pub unsafe fn identity_mapped_page_table() -> OffsetPageTable<'static> { ptr::with_exposed_provenance_mut::(level_4_table_addr.try_into().unwrap()); unsafe { let level_4_table = level_4_table_ptr.as_mut().unwrap(); - OffsetPageTable::new(level_4_table, x86_64::addr::VirtAddr::new(0x0)) + OffsetPageTable::from_phys_offset(level_4_table, x86_64::addr::VirtAddr::new(0x0)) } } @@ -135,7 +135,7 @@ pub fn is_recursive() -> bool { /// Translate a virtual memory address to a physical one. pub fn virtual_to_physical(virtual_address: VirtAddr) -> Option { - let addr = x86_64::VirtAddr::from(virtual_address); + let addr = x86_64::VirtAddr::new(virtual_address.as_u64()); let translate_result = unsafe { identity_mapped_page_table() }.translate(addr); @@ -167,13 +167,14 @@ pub fn map( for<'a> OffsetPageTable<'a>: Mapper, { let pages = { - let start = Page::::containing_address(virtual_address.into()); + let start = Page::::containing_address(x86_64::VirtAddr::new(virtual_address.as_u64())); let end = start + count as u64; Page::range(start, end) }; let frames = { - let start = PhysFrame::::containing_address(physical_address.into()); + let start = + PhysFrame::::containing_address(x86_64::PhysAddr::new(physical_address.as_u64())); let end = start + count as u64; PhysFrame::range(start, end) }; @@ -193,10 +194,10 @@ pub fn map( S: PageSize + fmt::Debug, { let mut unmapped = false; - for (page, frame) in pages.zip(frames) { + for (page, frame) in pages.into_iter().zip(frames) { // TODO: Require explicit unmaps let unmap = mapper.unmap(page); - if let Ok((_frame, flush)) = unmap { + if let Ok((_frame, _flags, flush)) = unmap { unmapped = true; flush.flush(); debug!("Had to unmap page {page:?} before mapping."); @@ -248,7 +249,8 @@ where S: PageSize + fmt::Debug, for<'a> OffsetPageTable<'a>: Mapper, { - let frame = PhysFrame::::from_start_address(phys_addr.into()).unwrap(); + let frame = + PhysFrame::::from_start_address(x86_64::PhysAddr::new(phys_addr.as_u64())).unwrap(); let flags = PageTableEntryFlags::PRESENT | PageTableEntryFlags::WRITABLE | PageTableEntryFlags::NO_EXECUTE; @@ -260,7 +262,7 @@ where Err(MapToError::PageAlreadyMapped(current_frame)) => assert_eq!(current_frame, frame), Err(MapToError::ParentEntryHugePage) => { let page_table = unsafe { identity_mapped_page_table() }; - let virt_addr = VirtAddr::new(frame.start_address().as_u64()).into(); + let virt_addr = x86_64::VirtAddr::new(frame.start_address().as_u64()); let phys_addr = frame.start_address(); assert_eq!(page_table.translate_addr(virt_addr), Some(phys_addr)); } @@ -275,14 +277,14 @@ where { trace!("Unmapping virtual address {virtual_address:p} ({count} pages)"); - let first_page = Page::::containing_address(virtual_address.into()); + let first_page = Page::::containing_address(x86_64::VirtAddr::new(virtual_address.as_u64())); let last_page = first_page + count as u64; let range = Page::range(first_page, last_page); for page in range { let unmap_result = unsafe { identity_mapped_page_table() }.unmap(page); match unmap_result { - Ok((_frame, flush)) => flush.flush(), + Ok((_frame, _flags, flush)) => flush.flush(), // FIXME: Some sentinel pages around stacks are supposed to be unmapped. // We should handle this case there instead of here. Err(UnmapError::PageNotMapped) => { @@ -411,7 +413,12 @@ pub fn create_new_root_page_table() -> usize { let entry: u64 = unsafe { let (frame, _flags) = Cr3::read(); - map::(virtaddr, frame.start_address().into(), 1, flags); + map::( + virtaddr, + PhysAddr::new(frame.start_address().as_u64()), + 1, + flags, + ); let entry: &u64 = &*virtaddr.as_ptr(); *entry @@ -449,7 +456,7 @@ pub unsafe fn log_page_tables() { } let page_table = unsafe { identity_mapped_page_table() }; - trace!("Page tables:\n{}", page_table.display()); + trace!("Page tables:\n{}", OffsetPageTableExt::display(&page_table)); } pub mod mapped_page_range_display { @@ -1037,7 +1044,7 @@ mod walker { ) -> Result<&'b PageTable, PageTableWalkError> { let page_table_ptr = self .page_table_frame_mapping - .frame_to_pointer(entry.frame()?); + .frame_to_pointer(entry.frame(false)?); let page_table: &PageTable = unsafe { &*page_table_ptr }; Ok(page_table) diff --git a/src/mm/virtualmem.rs b/src/mm/virtualmem.rs index 807c6f3a6e..5d21188641 100644 --- a/src/mm/virtualmem.rs +++ b/src/mm/virtualmem.rs @@ -84,7 +84,7 @@ pub fn kernel_heap_end() -> VirtAddr { }; let addr = u64::from(p4_index) << 39; - assert_eq!(VirtAddr::new_truncate(addr).p4_index(), p4_index); + assert_eq!(x86_64::VirtAddr::new_truncate(addr).p4_index(), p4_index); VirtAddr::new_truncate(addr - 1) } diff --git a/src/scheduler/mod.rs b/src/scheduler/mod.rs index eb252c3b63..5a0460b945 100644 --- a/src/scheduler/mod.rs +++ b/src/scheduler/mod.rs @@ -621,18 +621,20 @@ impl PerCoreScheduler { #[cfg(target_arch = "x86_64")] pub fn set_current_kernel_stack(&self) { + use x86_64::VirtAddr; + let current_task_borrowed = self.current_task.borrow(); let tss = unsafe { &mut *CoreLocal::get().tss.get() }; let rsp = current_task_borrowed.stacks.get_kernel_stack() + current_task_borrowed.stacks.get_kernel_stack_size() as u64 - TaskStacks::MARKER_SIZE as u64; - tss.privilege_stack_table[0] = rsp.into(); + tss.privilege_stack_table[0] = VirtAddr::new(rsp.as_u64()); CoreLocal::get().kernel_stack.set(rsp.as_mut_ptr()); let ist_start = current_task_borrowed.stacks.get_interrupt_stack() + current_task_borrowed.stacks.get_interrupt_stack_size() as u64 - TaskStacks::MARKER_SIZE as u64; - tss.interrupt_stack_table[0] = ist_start.into(); + tss.interrupt_stack_table[0] = VirtAddr::new(ist_start.as_u64()); } pub fn set_current_task_priority(&mut self, prio: Priority) { From 841b9c196692b8140e4761db47f62a0a2cf9393f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Fri, 16 Jan 2026 19:12:43 +0100 Subject: [PATCH 2/2] refactor(x86_64/paging): migrate to upstream page table formatting --- src/arch/x86_64/mm/paging.rs | 633 +---------------------------------- 1 file changed, 1 insertion(+), 632 deletions(-) diff --git a/src/arch/x86_64/mm/paging.rs b/src/arch/x86_64/mm/paging.rs index 02b15d9de0..f081983fb2 100644 --- a/src/arch/x86_64/mm/paging.rs +++ b/src/arch/x86_64/mm/paging.rs @@ -449,641 +449,10 @@ pub fn create_new_root_page_table() -> usize { pub unsafe fn log_page_tables() { use log::Level; - use self::mapped_page_range_display::OffsetPageTableExt; - if !log_enabled!(Level::Trace) { return; } let page_table = unsafe { identity_mapped_page_table() }; - trace!("Page tables:\n{}", OffsetPageTableExt::display(&page_table)); -} - -pub mod mapped_page_range_display { - use core::fmt::{self, Write}; - - use x86_64::structures::paging::mapper::PageTableFrameMapping; - use x86_64::structures::paging::{MappedPageTable, OffsetPageTable, PageSize}; - - use super::mapped_page_table_iter::{ - self, MappedPageRangeInclusive, MappedPageRangeInclusiveItem, - MappedPageTableRangeInclusiveIter, - }; - use super::offset_page_table::PhysOffset; - - #[expect(dead_code)] - pub trait MappedPageTableExt { - fn display(&self) -> MappedPageTableDisplay<'_, &P>; - } - - impl MappedPageTableExt

for MappedPageTable<'_, P> { - fn display(&self) -> MappedPageTableDisplay<'_, &P> { - MappedPageTableDisplay { - inner: mapped_page_table_iter::mapped_page_table_range_iter(self), - } - } - } - - pub trait OffsetPageTableExt { - fn display(&self) -> MappedPageTableDisplay<'_, PhysOffset>; - } - - impl OffsetPageTableExt for OffsetPageTable<'_> { - fn display(&self) -> MappedPageTableDisplay<'_, PhysOffset> { - MappedPageTableDisplay { - inner: mapped_page_table_iter::offset_page_table_range_iter(self), - } - } - } - - pub struct MappedPageTableDisplay<'a, P: PageTableFrameMapping + Clone> { - inner: MappedPageTableRangeInclusiveIter<'a, P>, - } - - impl fmt::Display for MappedPageTableDisplay<'_, P> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut has_fields = false; - - for mapped_page_range in self.inner.clone() { - if has_fields { - f.write_char('\n')?; - } - write!(f, "{}", mapped_page_range.display())?; - - has_fields = true; - } - - Ok(()) - } - } - - pub trait MappedPageRangeInclusiveItemExt { - fn display(&self) -> MappedPageRangeInclusiveItemDisplay<'_>; - } - - impl MappedPageRangeInclusiveItemExt for MappedPageRangeInclusiveItem { - fn display(&self) -> MappedPageRangeInclusiveItemDisplay<'_> { - MappedPageRangeInclusiveItemDisplay { inner: self } - } - } - - pub struct MappedPageRangeInclusiveItemDisplay<'a> { - inner: &'a MappedPageRangeInclusiveItem, - } - - impl fmt::Display for MappedPageRangeInclusiveItemDisplay<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.inner { - MappedPageRangeInclusiveItem::Size4KiB(range) => range.display().fmt(f), - MappedPageRangeInclusiveItem::Size2MiB(range) => range.display().fmt(f), - MappedPageRangeInclusiveItem::Size1GiB(range) => range.display().fmt(f), - } - } - } - - pub trait MappedPageRangeInclusiveExt { - fn display(&self) -> MappedPageRangeInclusiveDisplay<'_, S>; - } - - impl MappedPageRangeInclusiveExt for MappedPageRangeInclusive { - fn display(&self) -> MappedPageRangeInclusiveDisplay<'_, S> { - MappedPageRangeInclusiveDisplay { inner: self } - } - } - - pub struct MappedPageRangeInclusiveDisplay<'a, S: PageSize> { - inner: &'a MappedPageRangeInclusive, - } - - impl fmt::Display for MappedPageRangeInclusiveDisplay<'_, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let size = S::DEBUG_STR; - let len = self.inner.page_range.len(); - let page_start = self.inner.page_range.start.start_address(); - let page_end = self.inner.page_range.end.start_address(); - let frame_start = self.inner.frame_range.start.start_address(); - let frame_end = self.inner.frame_range.end.start_address(); - let flags = self.inner.flags; - let format_phys = if page_start.as_u64() == frame_start.as_u64() { - assert_eq!(page_end.as_u64(), frame_end.as_u64()); - format_args!("{:>39}", "identity mapped") - } else { - format_args!("{frame_start:18p}..={frame_end:18p}") - }; - write!( - f, - "size: {size}, len: {len:5}, virt: {page_start:18p}..={page_end:18p}, phys: {format_phys}, flags: {flags:?}" - ) - } - } -} - -pub mod mapped_page_table_iter { - //! TODO: try to upstream this to [`x86_64`]. - - use core::fmt; - use core::ops::{Add, AddAssign, Sub, SubAssign}; - - use x86_64::structures::paging::frame::PhysFrameRangeInclusive; - use x86_64::structures::paging::mapper::PageTableFrameMapping; - use x86_64::structures::paging::page::{AddressNotAligned, PageRangeInclusive}; - use x86_64::structures::paging::{ - MappedPageTable, OffsetPageTable, Page, PageSize, PageTable, PageTableFlags, - PageTableIndex, PhysFrame, Size1GiB, Size2MiB, Size4KiB, - }; - - use super::offset_page_table::PhysOffset; - use super::walker::{PageTableWalkError, PageTableWalker}; - - #[derive(Debug)] - pub struct MappedPageRangeInclusive { - pub page_range: PageRangeInclusive, - pub frame_range: PhysFrameRangeInclusive, - pub flags: PageTableFlags, - } - - impl TryFrom<(MappedPage, MappedPage)> for MappedPageRangeInclusive { - type Error = TryFromMappedPageError; - - fn try_from((start, end): (MappedPage, MappedPage)) -> Result { - if start.flags != end.flags { - return Err(TryFromMappedPageError); - } - - Ok(Self { - page_range: PageRangeInclusive { - start: start.page, - end: end.page, - }, - frame_range: PhysFrameRangeInclusive { - start: start.frame, - end: end.frame, - }, - flags: start.flags, - }) - } - } - - #[derive(Debug)] - pub enum MappedPageRangeInclusiveItem { - Size4KiB(MappedPageRangeInclusive), - Size2MiB(MappedPageRangeInclusive), - Size1GiB(MappedPageRangeInclusive), - } - - impl TryFrom<(MappedPageItem, MappedPageItem)> for MappedPageRangeInclusiveItem { - type Error = TryFromMappedPageError; - - fn try_from((start, end): (MappedPageItem, MappedPageItem)) -> Result { - match (start, end) { - (MappedPageItem::Size4KiB(start), MappedPageItem::Size4KiB(end)) => { - let range = MappedPageRangeInclusive::try_from((start, end))?; - Ok(Self::Size4KiB(range)) - } - (MappedPageItem::Size2MiB(start), MappedPageItem::Size2MiB(end)) => { - let range = MappedPageRangeInclusive::try_from((start, end))?; - Ok(Self::Size2MiB(range)) - } - (MappedPageItem::Size1GiB(start), MappedPageItem::Size1GiB(end)) => { - let range = MappedPageRangeInclusive::try_from((start, end))?; - Ok(Self::Size1GiB(range)) - } - (_, _) => Err(TryFromMappedPageError), - } - } - } - - #[derive(PartialEq, Eq, Clone, Debug)] - pub struct TryFromMappedPageError; - - impl fmt::Display for TryFromMappedPageError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("provided mapped pages were not compatible") - } - } - - #[derive(Clone)] - pub struct MappedPageTableRangeInclusiveIter<'a, P: PageTableFrameMapping> { - inner: MappedPageTableIter<'a, P>, - start: Option, - end: Option, - } - - pub fn mapped_page_table_range_iter<'a, P: PageTableFrameMapping>( - page_table: &'a MappedPageTable<'a, P>, - ) -> MappedPageTableRangeInclusiveIter<'a, &'a P> { - MappedPageTableRangeInclusiveIter { - inner: mapped_page_table_iter(page_table), - start: None, - end: None, - } - } - - pub fn offset_page_table_range_iter<'a>( - page_table: &'a OffsetPageTable<'a>, - ) -> MappedPageTableRangeInclusiveIter<'a, PhysOffset> { - MappedPageTableRangeInclusiveIter { - inner: offset_page_table_iter(page_table), - start: None, - end: None, - } - } - - impl Iterator for MappedPageTableRangeInclusiveIter<'_, P> { - type Item = MappedPageRangeInclusiveItem; - - fn next(&mut self) -> Option { - if self.start.is_none() { - self.start = self.inner.next(); - self.end = self.start; - } - - let Some(start) = &mut self.start else { - return None; - }; - let end = self.end.as_mut().unwrap(); - - for mapped_page in self.inner.by_ref() { - if mapped_page == *end + 1 { - *end = mapped_page; - continue; - } - - let range = MappedPageRangeInclusiveItem::try_from((*start, *end)).unwrap(); - *start = mapped_page; - *end = mapped_page; - return Some(range); - } - - let range = MappedPageRangeInclusiveItem::try_from((*start, *end)).unwrap(); - self.start = None; - self.end = None; - Some(range) - } - } - - #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] - pub struct MappedPage { - pub page: Page, - pub frame: PhysFrame, - pub flags: PageTableFlags, - } - - impl Add for MappedPage { - type Output = Self; - - fn add(self, rhs: u64) -> Self::Output { - Self { - page: self.page + rhs, - frame: self.frame + rhs, - flags: self.flags, - } - } - } - - impl Sub for MappedPage { - type Output = Self; - - fn sub(self, rhs: u64) -> Self::Output { - Self { - page: self.page - rhs, - frame: self.frame - rhs, - flags: self.flags, - } - } - } - - #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] - pub enum MappedPageItem { - Size4KiB(MappedPage), - Size2MiB(MappedPage), - Size1GiB(MappedPage), - } - - impl Add for MappedPageItem { - type Output = Self; - - fn add(self, rhs: u64) -> Self::Output { - match self { - Self::Size4KiB(mapped_page) => Self::Size4KiB(mapped_page + rhs), - Self::Size2MiB(mapped_page) => Self::Size2MiB(mapped_page + rhs), - Self::Size1GiB(mapped_page) => Self::Size1GiB(mapped_page + rhs), - } - } - } - - impl AddAssign for MappedPageItem { - fn add_assign(&mut self, rhs: u64) { - *self = *self + rhs; - } - } - - impl Sub for MappedPageItem { - type Output = Self; - - fn sub(self, rhs: u64) -> Self::Output { - match self { - Self::Size4KiB(mapped_page) => Self::Size4KiB(mapped_page - rhs), - Self::Size2MiB(mapped_page) => Self::Size2MiB(mapped_page - rhs), - Self::Size1GiB(mapped_page) => Self::Size1GiB(mapped_page - rhs), - } - } - } - - impl SubAssign for MappedPageItem { - fn sub_assign(&mut self, rhs: u64) { - *self = *self - rhs; - } - } - - #[derive(Clone)] - pub struct MappedPageTableIter<'a, P: PageTableFrameMapping> { - page_table_walker: PageTableWalker

, - level_4_table: &'a PageTable, - p4_index: u16, - p3_index: u16, - p2_index: u16, - p1_index: u16, - } - - pub fn mapped_page_table_iter<'a, P: PageTableFrameMapping>( - page_table: &'a MappedPageTable<'a, P>, - ) -> MappedPageTableIter<'a, &'a P> { - MappedPageTableIter { - page_table_walker: unsafe { - PageTableWalker::new(page_table.page_table_frame_mapping()) - }, - level_4_table: page_table.level_4_table(), - p4_index: 0, - p3_index: 0, - p2_index: 0, - p1_index: 0, - } - } - - pub fn offset_page_table_iter<'a>( - page_table: &'a OffsetPageTable<'a>, - ) -> MappedPageTableIter<'a, PhysOffset> { - MappedPageTableIter { - page_table_walker: unsafe { - PageTableWalker::new(PhysOffset { - offset: page_table.phys_offset(), - }) - }, - level_4_table: page_table.level_4_table(), - p4_index: 0, - p3_index: 0, - p2_index: 0, - p1_index: 0, - } - } - - impl MappedPageTableIter<'_, P> { - fn p4_index(&self) -> Option { - if self.p4_index >= 512 { - return None; - } - - Some(PageTableIndex::new(self.p4_index)) - } - - fn p3_index(&self) -> Option { - if self.p3_index >= 512 { - return None; - } - - Some(PageTableIndex::new(self.p3_index)) - } - - fn p2_index(&self) -> Option { - if self.p2_index >= 512 { - return None; - } - - Some(PageTableIndex::new(self.p2_index)) - } - - fn p1_index(&self) -> Option { - if self.p1_index >= 512 { - return None; - } - - Some(PageTableIndex::new(self.p1_index)) - } - - fn increment_p4_index(&mut self) -> Option<()> { - if self.p4_index >= 511 { - self.p4_index += 1; - return None; - } - - self.p4_index += 1; - self.p3_index = 0; - self.p2_index = 0; - self.p1_index = 0; - Some(()) - } - - fn increment_p3_index(&mut self) -> Option<()> { - if self.p3_index == 511 { - self.increment_p4_index()?; - return None; - } - - self.p3_index += 1; - self.p2_index = 0; - self.p1_index = 0; - Some(()) - } - - fn increment_p2_index(&mut self) -> Option<()> { - if self.p2_index == 511 { - self.increment_p3_index()?; - return None; - } - - self.p2_index += 1; - self.p1_index = 0; - Some(()) - } - - fn increment_p1_index(&mut self) -> Option<()> { - if self.p1_index == 511 { - self.increment_p2_index()?; - return None; - } - - self.p1_index += 1; - Some(()) - } - - fn next_forward(&mut self) -> Option { - let p4 = self.level_4_table; - - let p3 = loop { - match self.page_table_walker.next_table(&p4[self.p4_index()?]) { - Ok(page_table) => break page_table, - Err(PageTableWalkError::NotMapped) => self.increment_p4_index()?, - Err(PageTableWalkError::MappedToHugePage) => { - panic!("level 4 entry has huge page bit set") - } - } - }; - - let p2 = loop { - match self.page_table_walker.next_table(&p3[self.p3_index()?]) { - Ok(page_table) => break page_table, - Err(PageTableWalkError::NotMapped) => self.increment_p3_index()?, - Err(PageTableWalkError::MappedToHugePage) => { - let page = - Page::from_page_table_indices_1gib(self.p4_index()?, self.p3_index()?); - let entry = &p3[self.p3_index()?]; - let frame = PhysFrame::containing_address(entry.addr()); - let flags = entry.flags(); - let mapped_page = - MappedPageItem::Size1GiB(MappedPage { page, frame, flags }); - - self.increment_p3_index(); - return Some(mapped_page); - } - } - }; - - let p1 = loop { - match self.page_table_walker.next_table(&p2[self.p2_index()?]) { - Ok(page_table) => break page_table, - Err(PageTableWalkError::NotMapped) => self.increment_p2_index()?, - Err(PageTableWalkError::MappedToHugePage) => { - let page = Page::from_page_table_indices_2mib( - self.p4_index()?, - self.p3_index()?, - self.p2_index()?, - ); - let entry = &p2[self.p2_index()?]; - let frame = PhysFrame::containing_address(entry.addr()); - let flags = entry.flags(); - let mapped_page = - MappedPageItem::Size2MiB(MappedPage { page, frame, flags }); - - self.increment_p2_index(); - return Some(mapped_page); - } - } - }; - - loop { - let p1_entry = &p1[self.p1_index()?]; - - if p1_entry.is_unused() { - self.increment_p1_index()?; - continue; - } - - let frame = match PhysFrame::from_start_address(p1_entry.addr()) { - Ok(frame) => frame, - Err(AddressNotAligned) => { - warn!("Invalid frame address: {:p}", p1_entry.addr()); - self.increment_p1_index()?; - continue; - } - }; - - let page = Page::from_page_table_indices( - self.p4_index()?, - self.p3_index()?, - self.p2_index()?, - self.p1_index()?, - ); - let flags = p1_entry.flags(); - let mapped_page = MappedPageItem::Size4KiB(MappedPage { page, frame, flags }); - - self.increment_p1_index(); - return Some(mapped_page); - } - } - } - - impl Iterator for MappedPageTableIter<'_, P> { - type Item = MappedPageItem; - - fn next(&mut self) -> Option { - self.next_forward().or_else(|| self.next_forward()) - } - } -} - -mod walker { - //! Taken from [`x86_64`] - - use x86_64::structures::paging::PageTable; - use x86_64::structures::paging::mapper::PageTableFrameMapping; - use x86_64::structures::paging::page_table::{FrameError, PageTableEntry}; - - #[derive(Clone, Debug)] - pub(super) struct PageTableWalker { - page_table_frame_mapping: P, - } - - impl PageTableWalker

{ - #[inline] - pub unsafe fn new(page_table_frame_mapping: P) -> Self { - Self { - page_table_frame_mapping, - } - } - - /// Internal helper function to get a reference to the page table of the next level. - /// - /// Returns `PageTableWalkError::NotMapped` if the entry is unused. Returns - /// `PageTableWalkError::MappedToHugePage` if the `HUGE_PAGE` flag is set - /// in the passed entry. - #[inline] - pub(super) fn next_table<'b>( - &self, - entry: &'b PageTableEntry, - ) -> Result<&'b PageTable, PageTableWalkError> { - let page_table_ptr = self - .page_table_frame_mapping - .frame_to_pointer(entry.frame(false)?); - let page_table: &PageTable = unsafe { &*page_table_ptr }; - - Ok(page_table) - } - } - - #[derive(Debug)] - pub(super) enum PageTableWalkError { - NotMapped, - MappedToHugePage, - } - - impl From for PageTableWalkError { - #[inline] - fn from(err: FrameError) -> Self { - match err { - FrameError::HugeFrame => PageTableWalkError::MappedToHugePage, - FrameError::FrameNotPresent => PageTableWalkError::NotMapped, - } - } - } -} - -mod offset_page_table { - //! Taken from [`x86_64`] - - use x86_64::VirtAddr; - use x86_64::structures::paging::mapper::PageTableFrameMapping; - use x86_64::structures::paging::{PageTable, PhysFrame}; - - #[derive(Clone, Debug)] - pub struct PhysOffset { - pub offset: VirtAddr, - } - - unsafe impl PageTableFrameMapping for PhysOffset { - fn frame_to_pointer(&self, frame: PhysFrame) -> *mut PageTable { - let virt = self.offset + frame.start_address().as_u64(); - virt.as_mut_ptr() - } - } + trace!("Page tables:\n{:#}", page_table.display()); }