-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
83: Add a new `OffsetPageTable` mapper type r=phil-opp a=phil-opp The type wraps a `MappedPageTable` instance with a simpler interface. It uses a simple phys-to-virt offset instead of being generic over a phys-to-virt closure, which makes it easier to e.g. store the type in a `static`. TODO: - [x] Make `phys_offset` a `VirtAddr` instead of an `u64` Fixes #81 Co-authored-by: Philipp Oppermann <dev@phil-opp.com>
- Loading branch information
Showing
5 changed files
with
196 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
#![cfg(target_arch = "x86_64")] | ||
|
||
use crate::structures::paging::{frame::PhysFrame, mapper::*, page_table::PageTable}; | ||
|
||
/// A Mapper implementation that requires that the complete physically memory is mapped at some | ||
/// offset in the virtual address space. | ||
#[derive(Debug)] | ||
pub struct OffsetPageTable<'a> { | ||
inner: MappedPageTable<'a, PhysOffset>, | ||
} | ||
|
||
impl<'a> OffsetPageTable<'a> { | ||
/// Creates a new `OffsetPageTable` 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. | ||
/// | ||
/// This function is unsafe because the caller must guarantee that the passed `phys_offset` | ||
/// is correct. Also, the passed `level_4_table` must point to the level 4 page table | ||
/// of a valid page table hierarchy. Otherwise this function might break memory safety, e.g. | ||
/// by writing to an illegal memory location. | ||
pub unsafe fn new(level_4_table: &'a mut PageTable, phys_offset: VirtAddr) -> Self { | ||
let phys_offset = PhysOffset { | ||
offset: phys_offset, | ||
}; | ||
Self { | ||
inner: MappedPageTable::new(level_4_table, phys_offset), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
struct PhysOffset { | ||
offset: VirtAddr, | ||
} | ||
|
||
impl PhysToVirt for PhysOffset { | ||
fn phys_to_virt(&self, frame: PhysFrame) -> *mut PageTable { | ||
let phys = frame.start_address().as_u64(); | ||
let virt = self.offset + phys; | ||
virt.as_mut_ptr() | ||
} | ||
} | ||
|
||
// delegate all trait implementations to inner | ||
|
||
impl<'a> Mapper<Size1GiB> for OffsetPageTable<'a> { | ||
unsafe fn map_to<A>( | ||
&mut self, | ||
page: Page<Size1GiB>, | ||
frame: PhysFrame<Size1GiB>, | ||
flags: PageTableFlags, | ||
allocator: &mut A, | ||
) -> Result<MapperFlush<Size1GiB>, MapToError> | ||
where | ||
A: FrameAllocator<Size4KiB>, | ||
{ | ||
self.inner.map_to(page, frame, flags, allocator) | ||
} | ||
|
||
fn unmap( | ||
&mut self, | ||
page: Page<Size1GiB>, | ||
) -> Result<(PhysFrame<Size1GiB>, MapperFlush<Size1GiB>), UnmapError> { | ||
self.inner.unmap(page) | ||
} | ||
|
||
fn update_flags( | ||
&mut self, | ||
page: Page<Size1GiB>, | ||
flags: PageTableFlags, | ||
) -> Result<MapperFlush<Size1GiB>, FlagUpdateError> { | ||
self.inner.update_flags(page, flags) | ||
} | ||
|
||
fn translate_page(&self, page: Page<Size1GiB>) -> Result<PhysFrame<Size1GiB>, TranslateError> { | ||
self.inner.translate_page(page) | ||
} | ||
} | ||
|
||
impl<'a> Mapper<Size2MiB> for OffsetPageTable<'a> { | ||
unsafe fn map_to<A>( | ||
&mut self, | ||
page: Page<Size2MiB>, | ||
frame: PhysFrame<Size2MiB>, | ||
flags: PageTableFlags, | ||
allocator: &mut A, | ||
) -> Result<MapperFlush<Size2MiB>, MapToError> | ||
where | ||
A: FrameAllocator<Size4KiB>, | ||
{ | ||
self.inner.map_to(page, frame, flags, allocator) | ||
} | ||
|
||
fn unmap( | ||
&mut self, | ||
page: Page<Size2MiB>, | ||
) -> Result<(PhysFrame<Size2MiB>, MapperFlush<Size2MiB>), UnmapError> { | ||
self.inner.unmap(page) | ||
} | ||
|
||
fn update_flags( | ||
&mut self, | ||
page: Page<Size2MiB>, | ||
flags: PageTableFlags, | ||
) -> Result<MapperFlush<Size2MiB>, FlagUpdateError> { | ||
self.inner.update_flags(page, flags) | ||
} | ||
|
||
fn translate_page(&self, page: Page<Size2MiB>) -> Result<PhysFrame<Size2MiB>, TranslateError> { | ||
self.inner.translate_page(page) | ||
} | ||
} | ||
|
||
impl<'a> Mapper<Size4KiB> for OffsetPageTable<'a> { | ||
unsafe fn map_to<A>( | ||
&mut self, | ||
page: Page<Size4KiB>, | ||
frame: PhysFrame<Size4KiB>, | ||
flags: PageTableFlags, | ||
allocator: &mut A, | ||
) -> Result<MapperFlush<Size4KiB>, MapToError> | ||
where | ||
A: FrameAllocator<Size4KiB>, | ||
{ | ||
self.inner.map_to(page, frame, flags, allocator) | ||
} | ||
|
||
fn unmap( | ||
&mut self, | ||
page: Page<Size4KiB>, | ||
) -> Result<(PhysFrame<Size4KiB>, MapperFlush<Size4KiB>), UnmapError> { | ||
self.inner.unmap(page) | ||
} | ||
|
||
fn update_flags( | ||
&mut self, | ||
page: Page<Size4KiB>, | ||
flags: PageTableFlags, | ||
) -> Result<MapperFlush<Size4KiB>, FlagUpdateError> { | ||
self.inner.update_flags(page, flags) | ||
} | ||
|
||
fn translate_page(&self, page: Page<Size4KiB>) -> Result<PhysFrame<Size4KiB>, TranslateError> { | ||
self.inner.translate_page(page) | ||
} | ||
} | ||
|
||
impl<'a> MapperAllSizes for OffsetPageTable<'a> { | ||
fn translate(&self, addr: VirtAddr) -> TranslateResult { | ||
self.inner.translate(addr) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters