From 0c8756feb347044654c8da27de2888f7d1f7b879 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 20 Aug 2019 10:03:57 +0200 Subject: [PATCH 1/2] Add new UnsafePhysFrame type and use it in Mapper::map_to --- src/structures/paging/frame_alloc.rs | 39 +++++++++++++++++-- .../paging/mapper/mapped_page_table.rs | 25 ++++++------ src/structures/paging/mapper/mod.rs | 17 +++----- .../paging/mapper/offset_page_table.rs | 12 +++--- .../paging/mapper/recursive_page_table.rs | 22 +++++------ 5 files changed, 73 insertions(+), 42 deletions(-) diff --git a/src/structures/paging/frame_alloc.rs b/src/structures/paging/frame_alloc.rs index 6e80f15fe..0f946caf2 100644 --- a/src/structures/paging/frame_alloc.rs +++ b/src/structures/paging/frame_alloc.rs @@ -1,6 +1,7 @@ //! Traits for abstracting away frame allocation and deallocation. -use crate::structures::paging::{PageSize, PhysFrame}; +use crate::structures::paging::{PageSize, PhysFrame, Size4KiB}; +use core::ops::{Deref, DerefMut}; /// A trait for types that can allocate a frame of memory. /// @@ -8,11 +9,43 @@ use crate::structures::paging::{PageSize, PhysFrame}; /// the `allocate_frame` method returns only unique unused frames. pub unsafe trait FrameAllocator { /// Allocate a frame of the appropriate size and return it if possible. - fn allocate_frame(&mut self) -> Option>; + fn allocate_frame(&mut self) -> Option>; } /// A trait for types that can deallocate a frame of memory. pub trait FrameDeallocator { /// Deallocate the given frame of memory. - fn deallocate_frame(&mut self, frame: PhysFrame); + fn deallocate_frame(&mut self, frame: UnusedPhysFrame); +} + +/// Represents a physical frame that is not used for any mapping. +#[derive(Debug)] +pub struct UnusedPhysFrame(PhysFrame); + +impl UnusedPhysFrame { + /// Creates a new UnusedPhysFrame from the given frame. + /// + /// This method is unsafe because the caller must guarantee + /// that the given frame is unused. + pub unsafe fn new(frame: PhysFrame) -> Self { + Self(frame) + } + + pub fn frame(self) -> PhysFrame { + self.0 + } +} + +impl Deref for UnusedPhysFrame { + type Target = PhysFrame; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for UnusedPhysFrame { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } } diff --git a/src/structures/paging/mapper/mapped_page_table.rs b/src/structures/paging/mapper/mapped_page_table.rs index a6e2d9dbd..d40968db3 100644 --- a/src/structures/paging/mapper/mapped_page_table.rs +++ b/src/structures/paging/mapper/mapped_page_table.rs @@ -39,7 +39,7 @@ impl<'a, P: PhysToVirt> MappedPageTable<'a, P> { fn map_to_1gib( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -64,7 +64,7 @@ impl<'a, P: PhysToVirt> MappedPageTable<'a, P> { fn map_to_2mib( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -92,7 +92,7 @@ impl<'a, P: PhysToVirt> MappedPageTable<'a, P> { fn map_to_4kib( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -113,17 +113,17 @@ impl<'a, P: PhysToVirt> MappedPageTable<'a, P> { if !p1[page.p1_index()].is_unused() { return Err(MapToError::PageAlreadyMapped); } - p1[page.p1_index()].set_frame(frame, flags); + p1[page.p1_index()].set_frame(frame.frame(), flags); Ok(MapperFlush::new(page)) } } impl<'a, P: PhysToVirt> Mapper for MappedPageTable<'a, P> { - unsafe fn map_to( + fn map_to( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -193,10 +193,10 @@ impl<'a, P: PhysToVirt> Mapper for MappedPageTable<'a, P> { } impl<'a, P: PhysToVirt> Mapper for MappedPageTable<'a, P> { - unsafe fn map_to( + fn map_to( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -274,10 +274,10 @@ impl<'a, P: PhysToVirt> Mapper for MappedPageTable<'a, P> { } impl<'a, P: PhysToVirt> Mapper for MappedPageTable<'a, P> { - unsafe fn map_to( + fn map_to( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -460,7 +460,10 @@ impl PageTableWalker

{ if entry.is_unused() { if let Some(frame) = allocator.allocate_frame() { - entry.set_frame(frame, PageTableFlags::PRESENT | PageTableFlags::WRITABLE); + entry.set_frame( + frame.frame(), + PageTableFlags::PRESENT | PageTableFlags::WRITABLE, + ); created = true; } else { return Err(PageTableCreateError::FrameAllocationFailed); diff --git a/src/structures/paging/mapper/mod.rs b/src/structures/paging/mapper/mod.rs index a581dc870..5315edb23 100644 --- a/src/structures/paging/mapper/mod.rs +++ b/src/structures/paging/mapper/mod.rs @@ -5,8 +5,9 @@ pub use self::mapped_page_table::{MappedPageTable, PhysToVirt}; pub use self::{offset_page_table::OffsetPageTable, recursive_page_table::RecursivePageTable}; use crate::structures::paging::{ - frame_alloc::FrameAllocator, page_table::PageTableFlags, Page, PageSize, PhysFrame, Size1GiB, - Size2MiB, Size4KiB, + frame_alloc::{FrameAllocator, UnusedPhysFrame}, + page_table::PageTableFlags, + Page, PageSize, PhysFrame, Size1GiB, Size2MiB, Size4KiB, }; use crate::{PhysAddr, VirtAddr}; @@ -81,13 +82,10 @@ pub trait Mapper { /// /// This function might need additional physical frames to create new page tables. These /// frames are allocated from the `allocator` argument. At most three frames are required. - /// - /// This function is unsafe because the caller must guarantee that passed `frame` is - /// unused, i.e. not used for any other mappings. - unsafe fn map_to( + fn map_to( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, frame_allocator: &mut A, ) -> Result, MapToError> @@ -113,12 +111,9 @@ pub trait Mapper { fn translate_page(&self, page: Page) -> Result, TranslateError>; /// Maps the given frame to the virtual page with the same address. - /// - /// This function is unsafe because the caller must guarantee that the passed `frame` is - /// unused, i.e. not used for any other mappings. unsafe fn identity_map( &mut self, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, frame_allocator: &mut A, ) -> Result, MapToError> diff --git a/src/structures/paging/mapper/offset_page_table.rs b/src/structures/paging/mapper/offset_page_table.rs index 506bb1905..397a98523 100644 --- a/src/structures/paging/mapper/offset_page_table.rs +++ b/src/structures/paging/mapper/offset_page_table.rs @@ -49,10 +49,10 @@ impl PhysToVirt for PhysOffset { // delegate all trait implementations to inner impl<'a> Mapper for OffsetPageTable<'a> { - unsafe fn map_to( + fn map_to( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -83,10 +83,10 @@ impl<'a> Mapper for OffsetPageTable<'a> { } impl<'a> Mapper for OffsetPageTable<'a> { - unsafe fn map_to( + fn map_to( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -117,10 +117,10 @@ impl<'a> Mapper for OffsetPageTable<'a> { } impl<'a> Mapper for OffsetPageTable<'a> { - unsafe fn map_to( + fn map_to( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> diff --git a/src/structures/paging/mapper/recursive_page_table.rs b/src/structures/paging/mapper/recursive_page_table.rs index ee05a2517..01e41bba1 100644 --- a/src/structures/paging/mapper/recursive_page_table.rs +++ b/src/structures/paging/mapper/recursive_page_table.rs @@ -110,7 +110,7 @@ impl<'a> RecursivePageTable<'a> { if entry.is_unused() { if let Some(frame) = allocator.allocate_frame() { - entry.set_frame(frame, Flags::PRESENT | Flags::WRITABLE); + entry.set_frame(frame.frame(), Flags::PRESENT | Flags::WRITABLE); created = true; } else { return Err(MapToError::FrameAllocationFailed); @@ -138,7 +138,7 @@ impl<'a> RecursivePageTable<'a> { fn map_to_1gib( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -164,7 +164,7 @@ impl<'a> RecursivePageTable<'a> { fn map_to_2mib( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -193,7 +193,7 @@ impl<'a> RecursivePageTable<'a> { fn map_to_4kib( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -214,17 +214,17 @@ impl<'a> RecursivePageTable<'a> { if !p1[page.p1_index()].is_unused() { return Err(MapToError::PageAlreadyMapped); } - p1[page.p1_index()].set_frame(frame, flags); + p1[page.p1_index()].set_frame(frame.frame(), flags); Ok(MapperFlush::new(page)) } } impl<'a> Mapper for RecursivePageTable<'a> { - unsafe fn map_to( + fn map_to( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -306,10 +306,10 @@ impl<'a> Mapper for RecursivePageTable<'a> { } impl<'a> Mapper for RecursivePageTable<'a> { - unsafe fn map_to( + fn map_to( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> @@ -411,10 +411,10 @@ impl<'a> Mapper for RecursivePageTable<'a> { } impl<'a> Mapper for RecursivePageTable<'a> { - unsafe fn map_to( + fn map_to( &mut self, page: Page, - frame: PhysFrame, + frame: UnusedPhysFrame, flags: PageTableFlags, allocator: &mut A, ) -> Result, MapToError> From b47bd00cd5ada80c77c91eb3cb32b9990f9e571b Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 10 Dec 2019 14:22:43 +0100 Subject: [PATCH 2/2] Update changelog for #89 --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 4ef379a33..bb72a0d70 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,5 @@ - **Breaking:** Replace `ux` dependency with custom wrapper structs ([#91](https://github.com/rust-osdev/x86_64/pull/91)) +- **Breaking:** Add new UnsafePhysFrame type and use it in Mapper::map_to ([#89](https://github.com/rust-osdev/x86_64/pull/89)) # 0.7.7