x86_64/structures/paging/mapper/
offset_page_table.rs

1#![cfg(target_pointer_width = "64")]
2
3use crate::structures::paging::{mapper::*, page_table::PageTable};
4
5/// A Mapper implementation that requires that the complete physically memory is mapped at some
6/// offset in the virtual address space.
7#[derive(Debug)]
8pub struct OffsetPageTable<'a> {
9    inner: MappedPageTable<'a, PhysOffset>,
10}
11
12impl<'a> OffsetPageTable<'a> {
13    /// Creates a new `OffsetPageTable` that uses the given offset for converting virtual
14    /// to physical addresses.
15    ///
16    /// The complete physical memory must be mapped in the virtual address space starting at
17    /// address `phys_offset`. This means that for example physical address `0x5000` can be
18    /// accessed through virtual address `phys_offset + 0x5000`. This mapping is required because
19    /// the mapper needs to access page tables, which are not mapped into the virtual address
20    /// space by default.
21    ///
22    /// ## Safety
23    ///
24    /// This function is unsafe because the caller must guarantee that the passed `phys_offset`
25    /// is correct. Also, the passed `level_4_table` must point to the level 4 page table
26    /// of a valid page table hierarchy. Otherwise this function might break memory safety, e.g.
27    /// by writing to an illegal memory location.
28    #[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()
46    }
47
48    /// Returns the offset used for converting virtual to physical addresses.
49    pub fn phys_offset(&self) -> VirtAddr {
50        self.inner.page_table_frame_mapping().offset
51    }
52}
53
54#[derive(Debug)]
55struct PhysOffset {
56    offset: VirtAddr,
57}
58
59unsafe 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
68impl 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>, MapperFlush<Size1GiB>), UnmapError> {
92        self.inner.unmap(page)
93    }
94
95    #[inline]
96    unsafe fn update_flags(
97        &mut self,
98        page: Page<Size1GiB>,
99        flags: PageTableFlags,
100    ) -> Result<MapperFlush<Size1GiB>, FlagUpdateError> {
101        unsafe { self.inner.update_flags(page, flags) }
102    }
103
104    #[inline]
105    unsafe fn set_flags_p4_entry(
106        &mut self,
107        page: Page<Size1GiB>,
108        flags: PageTableFlags,
109    ) -> Result<MapperFlushAll, FlagUpdateError> {
110        unsafe { self.inner.set_flags_p4_entry(page, flags) }
111    }
112
113    #[inline]
114    unsafe fn set_flags_p3_entry(
115        &mut self,
116        page: Page<Size1GiB>,
117        flags: PageTableFlags,
118    ) -> Result<MapperFlushAll, FlagUpdateError> {
119        unsafe { self.inner.set_flags_p3_entry(page, flags) }
120    }
121
122    #[inline]
123    unsafe fn set_flags_p2_entry(
124        &mut self,
125        page: Page<Size1GiB>,
126        flags: PageTableFlags,
127    ) -> Result<MapperFlushAll, FlagUpdateError> {
128        unsafe { self.inner.set_flags_p2_entry(page, flags) }
129    }
130
131    #[inline]
132    fn translate_page(&self, page: Page<Size1GiB>) -> Result<PhysFrame<Size1GiB>, TranslateError> {
133        self.inner.translate_page(page)
134    }
135}
136
137impl Mapper<Size2MiB> for OffsetPageTable<'_> {
138    #[inline]
139    unsafe fn map_to_with_table_flags<A>(
140        &mut self,
141        page: Page<Size2MiB>,
142        frame: PhysFrame<Size2MiB>,
143        flags: PageTableFlags,
144        parent_table_flags: PageTableFlags,
145        allocator: &mut A,
146    ) -> Result<MapperFlush<Size2MiB>, MapToError<Size2MiB>>
147    where
148        A: FrameAllocator<Size4KiB> + ?Sized,
149    {
150        unsafe {
151            self.inner
152                .map_to_with_table_flags(page, frame, flags, parent_table_flags, allocator)
153        }
154    }
155
156    #[inline]
157    fn unmap(
158        &mut self,
159        page: Page<Size2MiB>,
160    ) -> Result<(PhysFrame<Size2MiB>, MapperFlush<Size2MiB>), UnmapError> {
161        self.inner.unmap(page)
162    }
163
164    #[inline]
165    unsafe fn update_flags(
166        &mut self,
167        page: Page<Size2MiB>,
168        flags: PageTableFlags,
169    ) -> Result<MapperFlush<Size2MiB>, FlagUpdateError> {
170        unsafe { self.inner.update_flags(page, flags) }
171    }
172
173    #[inline]
174    unsafe fn set_flags_p4_entry(
175        &mut self,
176        page: Page<Size2MiB>,
177        flags: PageTableFlags,
178    ) -> Result<MapperFlushAll, FlagUpdateError> {
179        unsafe { self.inner.set_flags_p4_entry(page, flags) }
180    }
181
182    #[inline]
183    unsafe fn set_flags_p3_entry(
184        &mut self,
185        page: Page<Size2MiB>,
186        flags: PageTableFlags,
187    ) -> Result<MapperFlushAll, FlagUpdateError> {
188        unsafe { self.inner.set_flags_p3_entry(page, flags) }
189    }
190
191    #[inline]
192    unsafe fn set_flags_p2_entry(
193        &mut self,
194        page: Page<Size2MiB>,
195        flags: PageTableFlags,
196    ) -> Result<MapperFlushAll, FlagUpdateError> {
197        unsafe { self.inner.set_flags_p2_entry(page, flags) }
198    }
199
200    #[inline]
201    fn translate_page(&self, page: Page<Size2MiB>) -> Result<PhysFrame<Size2MiB>, TranslateError> {
202        self.inner.translate_page(page)
203    }
204}
205
206impl Mapper<Size4KiB> for OffsetPageTable<'_> {
207    #[inline]
208    unsafe fn map_to_with_table_flags<A>(
209        &mut self,
210        page: Page<Size4KiB>,
211        frame: PhysFrame<Size4KiB>,
212        flags: PageTableFlags,
213        parent_table_flags: PageTableFlags,
214        allocator: &mut A,
215    ) -> Result<MapperFlush<Size4KiB>, MapToError<Size4KiB>>
216    where
217        A: FrameAllocator<Size4KiB> + ?Sized,
218    {
219        unsafe {
220            self.inner
221                .map_to_with_table_flags(page, frame, flags, parent_table_flags, allocator)
222        }
223    }
224
225    #[inline]
226    fn unmap(
227        &mut self,
228        page: Page<Size4KiB>,
229    ) -> Result<(PhysFrame<Size4KiB>, MapperFlush<Size4KiB>), UnmapError> {
230        self.inner.unmap(page)
231    }
232
233    #[inline]
234    unsafe fn update_flags(
235        &mut self,
236        page: Page<Size4KiB>,
237        flags: PageTableFlags,
238    ) -> Result<MapperFlush<Size4KiB>, FlagUpdateError> {
239        unsafe { self.inner.update_flags(page, flags) }
240    }
241
242    #[inline]
243    unsafe fn set_flags_p4_entry(
244        &mut self,
245        page: Page<Size4KiB>,
246        flags: PageTableFlags,
247    ) -> Result<MapperFlushAll, FlagUpdateError> {
248        unsafe { self.inner.set_flags_p4_entry(page, flags) }
249    }
250
251    #[inline]
252    unsafe fn set_flags_p3_entry(
253        &mut self,
254        page: Page<Size4KiB>,
255        flags: PageTableFlags,
256    ) -> Result<MapperFlushAll, FlagUpdateError> {
257        unsafe { self.inner.set_flags_p3_entry(page, flags) }
258    }
259
260    #[inline]
261    unsafe fn set_flags_p2_entry(
262        &mut self,
263        page: Page<Size4KiB>,
264        flags: PageTableFlags,
265    ) -> Result<MapperFlushAll, FlagUpdateError> {
266        unsafe { self.inner.set_flags_p2_entry(page, flags) }
267    }
268
269    #[inline]
270    fn translate_page(&self, page: Page<Size4KiB>) -> Result<PhysFrame<Size4KiB>, TranslateError> {
271        self.inner.translate_page(page)
272    }
273}
274
275impl Translate for OffsetPageTable<'_> {
276    #[inline]
277    fn translate(&self, addr: VirtAddr) -> TranslateResult {
278        self.inner.translate(addr)
279    }
280}
281
282impl CleanUp for OffsetPageTable<'_> {
283    #[inline]
284    unsafe fn clean_up<D>(&mut self, frame_deallocator: &mut D)
285    where
286        D: FrameDeallocator<Size4KiB>,
287    {
288        unsafe { self.inner.clean_up(frame_deallocator) }
289    }
290
291    #[inline]
292    unsafe fn clean_up_addr_range<D>(
293        &mut self,
294        range: PageRangeInclusive,
295        frame_deallocator: &mut D,
296    ) where
297        D: FrameDeallocator<Size4KiB>,
298    {
299        unsafe { self.inner.clean_up_addr_range(range, frame_deallocator) }
300    }
301}