Skip to content

Commit 2836e54

Browse files
authored
Merge pull request #576 from mkroening/offset_page_table
feat(mapper): make `OffsetPageTable` a type alias
2 parents 6326f4b + b7b3d04 commit 2836e54

File tree

4 files changed

+44
-279
lines changed

4 files changed

+44
-279
lines changed

Changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
- [add `Mapper::clear` to clear any page table entry regardless of the present flag](https://github.com/rust-osdev/x86_64/pull/484)
66
- [`Mapper::unmap` now also returns the flags of the page ](https://github.com/rust-osdev/x86_64/pull/484)
7+
- [make `OffsetPageTable` a type alias](https://github.com/rust-osdev/x86_64/pull/576)
8+
- To migrate, replace `OffsetPageTable::new` with `OffsetPageTable::from_phys_offset` or `MappedPageTable::from_phys_offset`.
9+
- `OffsetPageTable`'s `PageTableFrameMapping` implementation is now public as `PhysOffset`.
710

811
# 0.15.4 – 2025-11-24
912

src/structures/paging/mapper/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
pub use self::mapped_page_table::{MappedPageTable, PageTableFrameMapping};
44
#[cfg(target_pointer_width = "64")]
5-
pub use self::offset_page_table::OffsetPageTable;
5+
pub use self::offset_page_table::{OffsetPageTable, PhysOffset};
66
#[cfg(all(feature = "instructions", target_arch = "x86_64"))]
77
pub use self::recursive_page_table::{InvalidPageTable, RecursivePageTable};
88

Lines changed: 37 additions & 275 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
#![cfg(target_pointer_width = "64")]
22

3-
use crate::structures::paging::{mapper::*, page_table::PageTable};
3+
use crate::structures::paging::{mapper::*, PageTable};
44

55
/// A Mapper implementation that requires that the complete physical memory is mapped at some
66
/// offset in the virtual address space.
7-
#[derive(Debug)]
8-
pub struct OffsetPageTable<'a> {
9-
inner: MappedPageTable<'a, PhysOffset>,
10-
}
7+
pub type OffsetPageTable<'a> = MappedPageTable<'a, PhysOffset>;
118

129
impl<'a> OffsetPageTable<'a> {
1310
/// Creates a new `OffsetPageTable` that uses the given offset for converting virtual
@@ -26,291 +23,56 @@ impl<'a> OffsetPageTable<'a> {
2623
/// of a valid page table hierarchy. Otherwise this function might break memory safety, e.g.
2724
/// by writing to an illegal memory location.
2825
#[inline]
29-
pub unsafe fn new(level_4_table: &'a mut PageTable, phys_offset: VirtAddr) -> Self {
30-
let phys_offset = PhysOffset {
31-
offset: phys_offset,
32-
};
33-
Self {
34-
inner: unsafe { MappedPageTable::new(level_4_table, phys_offset) },
35-
}
36-
}
37-
38-
/// Returns an immutable reference to the wrapped level 4 `PageTable` instance.
39-
pub fn level_4_table(&self) -> &PageTable {
40-
self.inner.level_4_table()
41-
}
42-
43-
/// Returns a mutable reference to the wrapped level 4 `PageTable` instance.
44-
pub fn level_4_table_mut(&mut self) -> &mut PageTable {
45-
self.inner.level_4_table_mut()
26+
pub unsafe fn from_phys_offset(
27+
level_4_table: &'a mut PageTable,
28+
phys_offset: VirtAddr,
29+
) -> Self {
30+
let phys_offset = unsafe { PhysOffset::new(phys_offset) };
31+
unsafe { MappedPageTable::new(level_4_table, phys_offset) }
4632
}
4733

4834
/// Returns the offset used for converting virtual to physical addresses.
4935
pub fn phys_offset(&self) -> VirtAddr {
50-
self.inner.page_table_frame_mapping().offset
36+
self.page_table_frame_mapping().phys_offset()
5137
}
5238
}
5339

40+
/// A [`PageTableFrameMapping`] implementation that requires that the complete physical memory is mapped at some
41+
/// offset in the virtual address space.
5442
#[derive(Debug)]
55-
struct PhysOffset {
56-
offset: VirtAddr,
57-
}
58-
59-
unsafe impl PageTableFrameMapping for PhysOffset {
60-
fn frame_to_pointer(&self, frame: PhysFrame) -> *mut PageTable {
61-
let virt = self.offset + frame.start_address().as_u64();
62-
virt.as_mut_ptr()
63-
}
64-
}
65-
66-
// delegate all trait implementations to inner
67-
68-
impl Mapper<Size1GiB> for OffsetPageTable<'_> {
69-
#[inline]
70-
unsafe fn map_to_with_table_flags<A>(
71-
&mut self,
72-
page: Page<Size1GiB>,
73-
frame: PhysFrame<Size1GiB>,
74-
flags: PageTableFlags,
75-
parent_table_flags: PageTableFlags,
76-
allocator: &mut A,
77-
) -> Result<MapperFlush<Size1GiB>, MapToError<Size1GiB>>
78-
where
79-
A: FrameAllocator<Size4KiB> + ?Sized,
80-
{
81-
unsafe {
82-
self.inner
83-
.map_to_with_table_flags(page, frame, flags, parent_table_flags, allocator)
84-
}
85-
}
86-
87-
#[inline]
88-
fn unmap(
89-
&mut self,
90-
page: Page<Size1GiB>,
91-
) -> Result<(PhysFrame<Size1GiB>, PageTableFlags, MapperFlush<Size1GiB>), UnmapError> {
92-
self.inner.unmap(page)
93-
}
94-
95-
#[inline]
96-
fn clear(&mut self, page: Page<Size1GiB>) -> Result<UnmappedFrame<Size1GiB>, UnmapError> {
97-
self.inner.clear(page)
98-
}
99-
100-
#[inline]
101-
unsafe fn update_flags(
102-
&mut self,
103-
page: Page<Size1GiB>,
104-
flags: PageTableFlags,
105-
) -> Result<MapperFlush<Size1GiB>, FlagUpdateError> {
106-
unsafe { self.inner.update_flags(page, flags) }
107-
}
108-
109-
#[inline]
110-
unsafe fn set_flags_p4_entry(
111-
&mut self,
112-
page: Page<Size1GiB>,
113-
flags: PageTableFlags,
114-
) -> Result<MapperFlushAll, FlagUpdateError> {
115-
unsafe { self.inner.set_flags_p4_entry(page, flags) }
116-
}
117-
118-
#[inline]
119-
unsafe fn set_flags_p3_entry(
120-
&mut self,
121-
page: Page<Size1GiB>,
122-
flags: PageTableFlags,
123-
) -> Result<MapperFlushAll, FlagUpdateError> {
124-
unsafe { self.inner.set_flags_p3_entry(page, flags) }
125-
}
126-
127-
#[inline]
128-
unsafe fn set_flags_p2_entry(
129-
&mut self,
130-
page: Page<Size1GiB>,
131-
flags: PageTableFlags,
132-
) -> Result<MapperFlushAll, FlagUpdateError> {
133-
unsafe { self.inner.set_flags_p2_entry(page, flags) }
134-
}
135-
136-
#[inline]
137-
fn translate_page(&self, page: Page<Size1GiB>) -> Result<PhysFrame<Size1GiB>, TranslateError> {
138-
self.inner.translate_page(page)
139-
}
43+
pub struct PhysOffset {
44+
phys_offset: VirtAddr,
14045
}
14146

142-
impl Mapper<Size2MiB> for OffsetPageTable<'_> {
143-
#[inline]
144-
unsafe fn map_to_with_table_flags<A>(
145-
&mut self,
146-
page: Page<Size2MiB>,
147-
frame: PhysFrame<Size2MiB>,
148-
flags: PageTableFlags,
149-
parent_table_flags: PageTableFlags,
150-
allocator: &mut A,
151-
) -> Result<MapperFlush<Size2MiB>, MapToError<Size2MiB>>
152-
where
153-
A: FrameAllocator<Size4KiB> + ?Sized,
154-
{
155-
unsafe {
156-
self.inner
157-
.map_to_with_table_flags(page, frame, flags, parent_table_flags, allocator)
158-
}
159-
}
160-
161-
#[inline]
162-
fn unmap(
163-
&mut self,
164-
page: Page<Size2MiB>,
165-
) -> Result<(PhysFrame<Size2MiB>, PageTableFlags, MapperFlush<Size2MiB>), UnmapError> {
166-
self.inner.unmap(page)
167-
}
168-
169-
#[inline]
170-
fn clear(&mut self, page: Page<Size2MiB>) -> Result<UnmappedFrame<Size2MiB>, UnmapError> {
171-
self.inner.clear(page)
172-
}
173-
174-
#[inline]
175-
unsafe fn update_flags(
176-
&mut self,
177-
page: Page<Size2MiB>,
178-
flags: PageTableFlags,
179-
) -> Result<MapperFlush<Size2MiB>, FlagUpdateError> {
180-
unsafe { self.inner.update_flags(page, flags) }
181-
}
182-
183-
#[inline]
184-
unsafe fn set_flags_p4_entry(
185-
&mut self,
186-
page: Page<Size2MiB>,
187-
flags: PageTableFlags,
188-
) -> Result<MapperFlushAll, FlagUpdateError> {
189-
unsafe { self.inner.set_flags_p4_entry(page, flags) }
190-
}
191-
192-
#[inline]
193-
unsafe fn set_flags_p3_entry(
194-
&mut self,
195-
page: Page<Size2MiB>,
196-
flags: PageTableFlags,
197-
) -> Result<MapperFlushAll, FlagUpdateError> {
198-
unsafe { self.inner.set_flags_p3_entry(page, flags) }
199-
}
200-
201-
#[inline]
202-
unsafe fn set_flags_p2_entry(
203-
&mut self,
204-
page: Page<Size2MiB>,
205-
flags: PageTableFlags,
206-
) -> Result<MapperFlushAll, FlagUpdateError> {
207-
unsafe { self.inner.set_flags_p2_entry(page, flags) }
208-
}
209-
210-
#[inline]
211-
fn translate_page(&self, page: Page<Size2MiB>) -> Result<PhysFrame<Size2MiB>, TranslateError> {
212-
self.inner.translate_page(page)
213-
}
214-
}
215-
216-
impl Mapper<Size4KiB> for OffsetPageTable<'_> {
217-
#[inline]
218-
unsafe fn map_to_with_table_flags<A>(
219-
&mut self,
220-
page: Page<Size4KiB>,
221-
frame: PhysFrame<Size4KiB>,
222-
flags: PageTableFlags,
223-
parent_table_flags: PageTableFlags,
224-
allocator: &mut A,
225-
) -> Result<MapperFlush<Size4KiB>, MapToError<Size4KiB>>
226-
where
227-
A: FrameAllocator<Size4KiB> + ?Sized,
228-
{
229-
unsafe {
230-
self.inner
231-
.map_to_with_table_flags(page, frame, flags, parent_table_flags, allocator)
232-
}
233-
}
234-
235-
#[inline]
236-
fn unmap(
237-
&mut self,
238-
page: Page<Size4KiB>,
239-
) -> Result<(PhysFrame<Size4KiB>, PageTableFlags, MapperFlush<Size4KiB>), UnmapError> {
240-
self.inner.unmap(page)
241-
}
242-
243-
#[inline]
244-
fn clear(&mut self, page: Page<Size4KiB>) -> Result<UnmappedFrame<Size4KiB>, UnmapError> {
245-
self.inner.clear(page)
246-
}
247-
248-
#[inline]
249-
unsafe fn update_flags(
250-
&mut self,
251-
page: Page<Size4KiB>,
252-
flags: PageTableFlags,
253-
) -> Result<MapperFlush<Size4KiB>, FlagUpdateError> {
254-
unsafe { self.inner.update_flags(page, flags) }
255-
}
256-
257-
#[inline]
258-
unsafe fn set_flags_p4_entry(
259-
&mut self,
260-
page: Page<Size4KiB>,
261-
flags: PageTableFlags,
262-
) -> Result<MapperFlushAll, FlagUpdateError> {
263-
unsafe { self.inner.set_flags_p4_entry(page, flags) }
264-
}
265-
266-
#[inline]
267-
unsafe fn set_flags_p3_entry(
268-
&mut self,
269-
page: Page<Size4KiB>,
270-
flags: PageTableFlags,
271-
) -> Result<MapperFlushAll, FlagUpdateError> {
272-
unsafe { self.inner.set_flags_p3_entry(page, flags) }
273-
}
274-
275-
#[inline]
276-
unsafe fn set_flags_p2_entry(
277-
&mut self,
278-
page: Page<Size4KiB>,
279-
flags: PageTableFlags,
280-
) -> Result<MapperFlushAll, FlagUpdateError> {
281-
unsafe { self.inner.set_flags_p2_entry(page, flags) }
282-
}
283-
47+
impl PhysOffset {
48+
/// Creates a new `PhysOffset` that uses the given offset for converting virtual
49+
/// to physical addresses.
50+
///
51+
/// The complete physical memory must be mapped in the virtual address space starting at
52+
/// address `phys_offset`. This means that for example physical address `0x5000` can be
53+
/// accessed through virtual address `phys_offset + 0x5000`. This mapping is required because
54+
/// the mapper needs to access page tables, which are not mapped into the virtual address
55+
/// space by default.
56+
///
57+
/// ## Safety
58+
///
59+
/// This function is unsafe because the caller must guarantee that the passed `phys_offset`
60+
/// is correct. Otherwise this function might break memory safety, e.g. by writing to an
61+
/// illegal memory location.
28462
#[inline]
285-
fn translate_page(&self, page: Page<Size4KiB>) -> Result<PhysFrame<Size4KiB>, TranslateError> {
286-
self.inner.translate_page(page)
63+
pub unsafe fn new(phys_offset: VirtAddr) -> Self {
64+
Self { phys_offset }
28765
}
288-
}
28966

290-
impl Translate for OffsetPageTable<'_> {
291-
#[inline]
292-
fn translate(&self, addr: VirtAddr) -> TranslateResult {
293-
self.inner.translate(addr)
67+
/// Returns the offset used for converting virtual to physical addresses.
68+
pub fn phys_offset(&self) -> VirtAddr {
69+
self.phys_offset
29470
}
29571
}
29672

297-
impl CleanUp for OffsetPageTable<'_> {
298-
#[inline]
299-
unsafe fn clean_up<D>(&mut self, frame_deallocator: &mut D)
300-
where
301-
D: FrameDeallocator<Size4KiB>,
302-
{
303-
unsafe { self.inner.clean_up(frame_deallocator) }
304-
}
305-
306-
#[inline]
307-
unsafe fn clean_up_addr_range<D>(
308-
&mut self,
309-
range: PageRangeInclusive,
310-
frame_deallocator: &mut D,
311-
) where
312-
D: FrameDeallocator<Size4KiB>,
313-
{
314-
unsafe { self.inner.clean_up_addr_range(range, frame_deallocator) }
73+
unsafe impl PageTableFrameMapping for PhysOffset {
74+
fn frame_to_pointer(&self, frame: PhysFrame) -> *mut PageTable {
75+
let virt = self.phys_offset + frame.start_address().as_u64();
76+
virt.as_mut_ptr()
31577
}
31678
}

src/structures/paging/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ pub use self::frame::PhysFrame;
66
pub use self::frame_alloc::{FrameAllocator, FrameDeallocator};
77
#[doc(no_inline)]
88
pub use self::mapper::MappedPageTable;
9-
#[cfg(target_pointer_width = "64")]
10-
#[doc(no_inline)]
11-
pub use self::mapper::OffsetPageTable;
129
#[cfg(all(feature = "instructions", target_arch = "x86_64"))]
1310
#[doc(no_inline)]
1411
pub use self::mapper::RecursivePageTable;
1512
pub use self::mapper::{Mapper, Translate};
13+
#[cfg(target_pointer_width = "64")]
14+
#[doc(no_inline)]
15+
pub use self::mapper::{OffsetPageTable, PhysOffset};
1616
pub use self::page::{Page, PageSize, Size1GiB, Size2MiB, Size4KiB};
1717
pub use self::page_table::{PageOffset, PageTable, PageTableFlags, PageTableIndex};
1818

0 commit comments

Comments
 (0)