diff --git a/Changelog.md b/Changelog.md index 73005f07..187cc5d9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,9 @@ - [add `Mapper::clear` to clear any page table entry regardless of the present flag](https://github.com/rust-osdev/x86_64/pull/484) - [`Mapper::unmap` now also returns the flags of the page ](https://github.com/rust-osdev/x86_64/pull/484) +- [make `OffsetPageTable` a type alias](https://github.com/rust-osdev/x86_64/pull/576) + - To migrate, replace `OffsetPageTable::new` with `OffsetPageTable::from_phys_offset` or `MappedPageTable::from_phys_offset`. + - `OffsetPageTable`'s `PageTableFrameMapping` implementation is now public as `PhysOffset`. # 0.15.4 – 2025-11-24 diff --git a/src/structures/paging/mapper/mod.rs b/src/structures/paging/mapper/mod.rs index 1d4e7ebc..4064bc2d 100644 --- a/src/structures/paging/mapper/mod.rs +++ b/src/structures/paging/mapper/mod.rs @@ -2,7 +2,7 @@ pub use self::mapped_page_table::{MappedPageTable, PageTableFrameMapping}; #[cfg(target_pointer_width = "64")] -pub use self::offset_page_table::OffsetPageTable; +pub use self::offset_page_table::{OffsetPageTable, PhysOffset}; #[cfg(all(feature = "instructions", target_arch = "x86_64"))] pub use self::recursive_page_table::{InvalidPageTable, RecursivePageTable}; diff --git a/src/structures/paging/mapper/offset_page_table.rs b/src/structures/paging/mapper/offset_page_table.rs index efa867ec..bbb51461 100644 --- a/src/structures/paging/mapper/offset_page_table.rs +++ b/src/structures/paging/mapper/offset_page_table.rs @@ -1,13 +1,10 @@ #![cfg(target_pointer_width = "64")] -use crate::structures::paging::{mapper::*, page_table::PageTable}; +use crate::structures::paging::{mapper::*, PageTable}; /// A Mapper implementation that requires that the complete physical memory is mapped at some /// offset in the virtual address space. -#[derive(Debug)] -pub struct OffsetPageTable<'a> { - inner: MappedPageTable<'a, PhysOffset>, -} +pub type OffsetPageTable<'a> = MappedPageTable<'a, PhysOffset>; impl<'a> OffsetPageTable<'a> { /// Creates a new `OffsetPageTable` that uses the given offset for converting virtual @@ -26,291 +23,56 @@ impl<'a> OffsetPageTable<'a> { /// of a valid page table hierarchy. Otherwise this function might break memory safety, e.g. /// by writing to an illegal memory location. #[inline] - pub unsafe fn new(level_4_table: &'a mut PageTable, phys_offset: VirtAddr) -> Self { - let phys_offset = PhysOffset { - offset: phys_offset, - }; - Self { - inner: unsafe { MappedPageTable::new(level_4_table, phys_offset) }, - } - } - - /// Returns an immutable reference to the wrapped level 4 `PageTable` instance. - pub fn level_4_table(&self) -> &PageTable { - self.inner.level_4_table() - } - - /// Returns a mutable reference to the wrapped level 4 `PageTable` instance. - pub fn level_4_table_mut(&mut self) -> &mut PageTable { - self.inner.level_4_table_mut() + pub unsafe fn from_phys_offset( + level_4_table: &'a mut PageTable, + phys_offset: VirtAddr, + ) -> Self { + let phys_offset = unsafe { PhysOffset::new(phys_offset) }; + unsafe { MappedPageTable::new(level_4_table, phys_offset) } } /// Returns the offset used for converting virtual to physical addresses. pub fn phys_offset(&self) -> VirtAddr { - self.inner.page_table_frame_mapping().offset + self.page_table_frame_mapping().phys_offset() } } +/// A [`PageTableFrameMapping`] implementation that requires that the complete physical memory is mapped at some +/// offset in the virtual address space. #[derive(Debug)] -struct PhysOffset { - 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() - } -} - -// delegate all trait implementations to inner - -impl Mapper for OffsetPageTable<'_> { - #[inline] - unsafe fn map_to_with_table_flags( - &mut self, - page: Page, - frame: PhysFrame, - flags: PageTableFlags, - parent_table_flags: PageTableFlags, - allocator: &mut A, - ) -> Result, MapToError> - where - A: FrameAllocator + ?Sized, - { - unsafe { - self.inner - .map_to_with_table_flags(page, frame, flags, parent_table_flags, allocator) - } - } - - #[inline] - fn unmap( - &mut self, - page: Page, - ) -> Result<(PhysFrame, PageTableFlags, MapperFlush), UnmapError> { - self.inner.unmap(page) - } - - #[inline] - fn clear(&mut self, page: Page) -> Result, UnmapError> { - self.inner.clear(page) - } - - #[inline] - unsafe fn update_flags( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result, FlagUpdateError> { - unsafe { self.inner.update_flags(page, flags) } - } - - #[inline] - unsafe fn set_flags_p4_entry( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result { - unsafe { self.inner.set_flags_p4_entry(page, flags) } - } - - #[inline] - unsafe fn set_flags_p3_entry( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result { - unsafe { self.inner.set_flags_p3_entry(page, flags) } - } - - #[inline] - unsafe fn set_flags_p2_entry( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result { - unsafe { self.inner.set_flags_p2_entry(page, flags) } - } - - #[inline] - fn translate_page(&self, page: Page) -> Result, TranslateError> { - self.inner.translate_page(page) - } +pub struct PhysOffset { + phys_offset: VirtAddr, } -impl Mapper for OffsetPageTable<'_> { - #[inline] - unsafe fn map_to_with_table_flags( - &mut self, - page: Page, - frame: PhysFrame, - flags: PageTableFlags, - parent_table_flags: PageTableFlags, - allocator: &mut A, - ) -> Result, MapToError> - where - A: FrameAllocator + ?Sized, - { - unsafe { - self.inner - .map_to_with_table_flags(page, frame, flags, parent_table_flags, allocator) - } - } - - #[inline] - fn unmap( - &mut self, - page: Page, - ) -> Result<(PhysFrame, PageTableFlags, MapperFlush), UnmapError> { - self.inner.unmap(page) - } - - #[inline] - fn clear(&mut self, page: Page) -> Result, UnmapError> { - self.inner.clear(page) - } - - #[inline] - unsafe fn update_flags( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result, FlagUpdateError> { - unsafe { self.inner.update_flags(page, flags) } - } - - #[inline] - unsafe fn set_flags_p4_entry( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result { - unsafe { self.inner.set_flags_p4_entry(page, flags) } - } - - #[inline] - unsafe fn set_flags_p3_entry( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result { - unsafe { self.inner.set_flags_p3_entry(page, flags) } - } - - #[inline] - unsafe fn set_flags_p2_entry( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result { - unsafe { self.inner.set_flags_p2_entry(page, flags) } - } - - #[inline] - fn translate_page(&self, page: Page) -> Result, TranslateError> { - self.inner.translate_page(page) - } -} - -impl Mapper for OffsetPageTable<'_> { - #[inline] - unsafe fn map_to_with_table_flags( - &mut self, - page: Page, - frame: PhysFrame, - flags: PageTableFlags, - parent_table_flags: PageTableFlags, - allocator: &mut A, - ) -> Result, MapToError> - where - A: FrameAllocator + ?Sized, - { - unsafe { - self.inner - .map_to_with_table_flags(page, frame, flags, parent_table_flags, allocator) - } - } - - #[inline] - fn unmap( - &mut self, - page: Page, - ) -> Result<(PhysFrame, PageTableFlags, MapperFlush), UnmapError> { - self.inner.unmap(page) - } - - #[inline] - fn clear(&mut self, page: Page) -> Result, UnmapError> { - self.inner.clear(page) - } - - #[inline] - unsafe fn update_flags( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result, FlagUpdateError> { - unsafe { self.inner.update_flags(page, flags) } - } - - #[inline] - unsafe fn set_flags_p4_entry( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result { - unsafe { self.inner.set_flags_p4_entry(page, flags) } - } - - #[inline] - unsafe fn set_flags_p3_entry( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result { - unsafe { self.inner.set_flags_p3_entry(page, flags) } - } - - #[inline] - unsafe fn set_flags_p2_entry( - &mut self, - page: Page, - flags: PageTableFlags, - ) -> Result { - unsafe { self.inner.set_flags_p2_entry(page, flags) } - } - +impl PhysOffset { + /// Creates a new `PhysOffset` that uses the given offset for converting virtual + /// to physical addresses. + /// + /// The complete physical memory must be mapped in the virtual address space starting at + /// address `phys_offset`. This means that for example physical address `0x5000` can be + /// accessed through virtual address `phys_offset + 0x5000`. This mapping is required because + /// the mapper needs to access page tables, which are not mapped into the virtual address + /// space by default. + /// + /// ## Safety + /// + /// This function is unsafe because the caller must guarantee that the passed `phys_offset` + /// is correct. Otherwise this function might break memory safety, e.g. by writing to an + /// illegal memory location. #[inline] - fn translate_page(&self, page: Page) -> Result, TranslateError> { - self.inner.translate_page(page) + pub unsafe fn new(phys_offset: VirtAddr) -> Self { + Self { phys_offset } } -} -impl Translate for OffsetPageTable<'_> { - #[inline] - fn translate(&self, addr: VirtAddr) -> TranslateResult { - self.inner.translate(addr) + /// Returns the offset used for converting virtual to physical addresses. + pub fn phys_offset(&self) -> VirtAddr { + self.phys_offset } } -impl CleanUp for OffsetPageTable<'_> { - #[inline] - unsafe fn clean_up(&mut self, frame_deallocator: &mut D) - where - D: FrameDeallocator, - { - unsafe { self.inner.clean_up(frame_deallocator) } - } - - #[inline] - unsafe fn clean_up_addr_range( - &mut self, - range: PageRangeInclusive, - frame_deallocator: &mut D, - ) where - D: FrameDeallocator, - { - unsafe { self.inner.clean_up_addr_range(range, frame_deallocator) } +unsafe impl PageTableFrameMapping for PhysOffset { + fn frame_to_pointer(&self, frame: PhysFrame) -> *mut PageTable { + let virt = self.phys_offset + frame.start_address().as_u64(); + virt.as_mut_ptr() } } diff --git a/src/structures/paging/mod.rs b/src/structures/paging/mod.rs index 741f683c..600a7332 100644 --- a/src/structures/paging/mod.rs +++ b/src/structures/paging/mod.rs @@ -6,13 +6,13 @@ pub use self::frame::PhysFrame; pub use self::frame_alloc::{FrameAllocator, FrameDeallocator}; #[doc(no_inline)] pub use self::mapper::MappedPageTable; -#[cfg(target_pointer_width = "64")] -#[doc(no_inline)] -pub use self::mapper::OffsetPageTable; #[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[doc(no_inline)] pub use self::mapper::RecursivePageTable; pub use self::mapper::{Mapper, Translate}; +#[cfg(target_pointer_width = "64")] +#[doc(no_inline)] +pub use self::mapper::{OffsetPageTable, PhysOffset}; pub use self::page::{Page, PageSize, Size1GiB, Size2MiB, Size4KiB}; pub use self::page_table::{PageOffset, PageTable, PageTableFlags, PageTableIndex};