Skip to content

Commit 4a72bc6

Browse files
committed
Mapper: Add methods to set the flags of the level 4/3/2 page tables
1 parent 88f882f commit 4a72bc6

File tree

4 files changed

+442
-0
lines changed

4 files changed

+442
-0
lines changed

src/structures/paging/mapper/mapped_page_table.rs

+138
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,39 @@ impl<'a, P: PhysToVirt> Mapper<Size1GiB> for MappedPageTable<'a, P> {
197197
Ok(MapperFlush::new(page))
198198
}
199199

200+
unsafe fn set_flags_p4_entry(
201+
&mut self,
202+
page: Page<Size1GiB>,
203+
flags: PageTableFlags,
204+
) -> Result<MapperFlushAll, FlagUpdateError> {
205+
let p4 = &mut self.level_4_table;
206+
let p4_entry = &mut p4[page.p4_index()];
207+
208+
if p4_entry.is_unused() {
209+
return Err(FlagUpdateError::PageNotMapped);
210+
}
211+
212+
p4_entry.set_flags(flags);
213+
214+
Ok(MapperFlushAll::new())
215+
}
216+
217+
unsafe fn set_flags_p3_entry(
218+
&mut self,
219+
_page: Page<Size1GiB>,
220+
_flags: PageTableFlags,
221+
) -> Result<MapperFlushAll, FlagUpdateError> {
222+
Err(FlagUpdateError::ParentEntryHugePage)
223+
}
224+
225+
unsafe fn set_flags_p2_entry(
226+
&mut self,
227+
_page: Page<Size1GiB>,
228+
_flags: PageTableFlags,
229+
) -> Result<MapperFlushAll, FlagUpdateError> {
230+
Err(FlagUpdateError::ParentEntryHugePage)
231+
}
232+
200233
fn translate_page(&self, page: Page<Size1GiB>) -> Result<PhysFrame<Size1GiB>, TranslateError> {
201234
let p4 = &self.level_4_table;
202235
let p3 = self.page_table_walker.next_table(&p4[page.p4_index()])?;
@@ -279,6 +312,51 @@ impl<'a, P: PhysToVirt> Mapper<Size2MiB> for MappedPageTable<'a, P> {
279312
Ok(MapperFlush::new(page))
280313
}
281314

315+
unsafe fn set_flags_p4_entry(
316+
&mut self,
317+
page: Page<Size2MiB>,
318+
flags: PageTableFlags,
319+
) -> Result<MapperFlushAll, FlagUpdateError> {
320+
let p4 = &mut self.level_4_table;
321+
let p4_entry = &mut p4[page.p4_index()];
322+
323+
if p4_entry.is_unused() {
324+
return Err(FlagUpdateError::PageNotMapped);
325+
}
326+
327+
p4_entry.set_flags(flags);
328+
329+
Ok(MapperFlushAll::new())
330+
}
331+
332+
unsafe fn set_flags_p3_entry(
333+
&mut self,
334+
page: Page<Size2MiB>,
335+
flags: PageTableFlags,
336+
) -> Result<MapperFlushAll, FlagUpdateError> {
337+
let p4 = &mut self.level_4_table;
338+
let p3 = self
339+
.page_table_walker
340+
.next_table_mut(&mut p4[page.p4_index()])?;
341+
let p3_entry = &mut p3[page.p3_index()];
342+
343+
if p3_entry.is_unused() {
344+
return Err(FlagUpdateError::PageNotMapped);
345+
}
346+
347+
p3_entry.set_flags(flags);
348+
349+
Ok(MapperFlushAll::new())
350+
}
351+
352+
unsafe fn set_flags_p2_entry(
353+
&mut self,
354+
_page: Page<Size2MiB>,
355+
_flags: PageTableFlags,
356+
) -> Result<MapperFlushAll, FlagUpdateError> {
357+
Err(FlagUpdateError::ParentEntryHugePage)
358+
}
359+
282360
fn translate_page(&self, page: Page<Size2MiB>) -> Result<PhysFrame<Size2MiB>, TranslateError> {
283361
let p4 = &self.level_4_table;
284362
let p3 = self.page_table_walker.next_table(&p4[page.p4_index()])?;
@@ -362,6 +440,66 @@ impl<'a, P: PhysToVirt> Mapper<Size4KiB> for MappedPageTable<'a, P> {
362440
Ok(MapperFlush::new(page))
363441
}
364442

443+
unsafe fn set_flags_p4_entry(
444+
&mut self,
445+
page: Page<Size4KiB>,
446+
flags: PageTableFlags,
447+
) -> Result<MapperFlushAll, FlagUpdateError> {
448+
let p4 = &mut self.level_4_table;
449+
let p4_entry = &mut p4[page.p4_index()];
450+
451+
if p4_entry.is_unused() {
452+
return Err(FlagUpdateError::PageNotMapped);
453+
}
454+
455+
p4_entry.set_flags(flags);
456+
457+
Ok(MapperFlushAll::new())
458+
}
459+
460+
unsafe fn set_flags_p3_entry(
461+
&mut self,
462+
page: Page<Size4KiB>,
463+
flags: PageTableFlags,
464+
) -> Result<MapperFlushAll, FlagUpdateError> {
465+
let p4 = &mut self.level_4_table;
466+
let p3 = self
467+
.page_table_walker
468+
.next_table_mut(&mut p4[page.p4_index()])?;
469+
let p3_entry = &mut p3[page.p3_index()];
470+
471+
if p3_entry.is_unused() {
472+
return Err(FlagUpdateError::PageNotMapped);
473+
}
474+
475+
p3_entry.set_flags(flags);
476+
477+
Ok(MapperFlushAll::new())
478+
}
479+
480+
unsafe fn set_flags_p2_entry(
481+
&mut self,
482+
page: Page<Size4KiB>,
483+
flags: PageTableFlags,
484+
) -> Result<MapperFlushAll, FlagUpdateError> {
485+
let p4 = &mut self.level_4_table;
486+
let p3 = self
487+
.page_table_walker
488+
.next_table_mut(&mut p4[page.p4_index()])?;
489+
let p2 = self
490+
.page_table_walker
491+
.next_table_mut(&mut p3[page.p3_index()])?;
492+
let p2_entry = &mut p2[page.p2_index()];
493+
494+
if p2_entry.is_unused() {
495+
return Err(FlagUpdateError::PageNotMapped);
496+
}
497+
498+
p2_entry.set_flags(flags);
499+
500+
Ok(MapperFlushAll::new())
501+
}
502+
365503
fn translate_page(&self, page: Page<Size4KiB>) -> Result<PhysFrame<Size4KiB>, TranslateError> {
366504
let p4 = &self.level_4_table;
367505
let p3 = self.page_table_walker.next_table(&p4[page.p4_index()])?;

src/structures/paging/mapper/mod.rs

+73
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,51 @@ pub trait Mapper<S: PageSize> {
263263
flags: PageTableFlags,
264264
) -> Result<MapperFlush<S>, FlagUpdateError>;
265265

266+
/// Set the flags of an existing page level 4 table entry
267+
///
268+
/// ## Safety
269+
///
270+
/// This method is unsafe because changing the flags of a mapping
271+
/// might result in undefined behavior. For example, setting the
272+
/// `GLOBAL` and `WRITABLE` flags for a page might result in the corruption
273+
/// of values stored in that page from processes running in other address
274+
/// spaces.
275+
unsafe fn set_flags_p4_entry(
276+
&mut self,
277+
page: Page<S>,
278+
flags: PageTableFlags,
279+
) -> Result<MapperFlushAll, FlagUpdateError>;
280+
281+
/// Set the flags of an existing page table level 3 entry
282+
///
283+
/// ## Safety
284+
///
285+
/// This method is unsafe because changing the flags of a mapping
286+
/// might result in undefined behavior. For example, setting the
287+
/// `GLOBAL` and `WRITABLE` flags for a page might result in the corruption
288+
/// of values stored in that page from processes running in other address
289+
/// spaces.
290+
unsafe fn set_flags_p3_entry(
291+
&mut self,
292+
page: Page<S>,
293+
flags: PageTableFlags,
294+
) -> Result<MapperFlushAll, FlagUpdateError>;
295+
296+
/// Set the flags of an existing page table level 2 entry
297+
///
298+
/// ## Safety
299+
///
300+
/// This method is unsafe because changing the flags of a mapping
301+
/// might result in undefined behavior. For example, setting the
302+
/// `GLOBAL` and `WRITABLE` flags for a page might result in the corruption
303+
/// of values stored in that page from processes running in other address
304+
/// spaces.
305+
unsafe fn set_flags_p2_entry(
306+
&mut self,
307+
page: Page<S>,
308+
flags: PageTableFlags,
309+
) -> Result<MapperFlushAll, FlagUpdateError>;
310+
266311
/// Return the frame that the specified page is mapped to.
267312
///
268313
/// This function assumes that the page is mapped to a frame of size `S` and returns an
@@ -321,6 +366,34 @@ impl<S: PageSize> MapperFlush<S> {
321366
pub fn ignore(self) {}
322367
}
323368

369+
/// This type represents a change of a page table requiring a complete TLB flush
370+
///
371+
/// The old mapping might be still cached in the translation lookaside buffer (TLB), so it needs
372+
/// to be flushed from the TLB before it's accessed. This type is returned from a function that
373+
/// made the change to ensure that the TLB flush is not forgotten.
374+
#[derive(Debug)]
375+
#[must_use = "Page Table changes must be flushed or ignored."]
376+
pub struct MapperFlushAll(());
377+
378+
impl MapperFlushAll {
379+
/// Create a new flush promise
380+
#[inline]
381+
fn new() -> Self {
382+
MapperFlushAll(())
383+
}
384+
385+
/// Flush all pages from the TLB to ensure that the newest mapping is used.
386+
#[cfg(target_arch = "x86_64")]
387+
#[inline]
388+
pub fn flush_all(self) {
389+
crate::instructions::tlb::flush_all()
390+
}
391+
392+
/// Don't flush the TLB and silence the “must be used” warning.
393+
#[inline]
394+
pub fn ignore(self) {}
395+
}
396+
324397
/// This error is returned from `map_to` and similar methods.
325398
#[derive(Debug)]
326399
pub enum MapToError<S: PageSize> {

src/structures/paging/mapper/offset_page_table.rs

+81
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,33 @@ impl<'a> Mapper<Size1GiB> for OffsetPageTable<'a> {
8888
self.inner.update_flags(page, flags)
8989
}
9090

91+
#[inline]
92+
unsafe fn set_flags_p4_entry(
93+
&mut self,
94+
page: Page<Size1GiB>,
95+
flags: PageTableFlags,
96+
) -> Result<MapperFlushAll, FlagUpdateError> {
97+
self.inner.set_flags_p4_entry(page, flags)
98+
}
99+
100+
#[inline]
101+
unsafe fn set_flags_p3_entry(
102+
&mut self,
103+
page: Page<Size1GiB>,
104+
flags: PageTableFlags,
105+
) -> Result<MapperFlushAll, FlagUpdateError> {
106+
self.inner.set_flags_p3_entry(page, flags)
107+
}
108+
109+
#[inline]
110+
unsafe fn set_flags_p2_entry(
111+
&mut self,
112+
page: Page<Size1GiB>,
113+
flags: PageTableFlags,
114+
) -> Result<MapperFlushAll, FlagUpdateError> {
115+
self.inner.set_flags_p2_entry(page, flags)
116+
}
117+
91118
#[inline]
92119
fn translate_page(&self, page: Page<Size1GiB>) -> Result<PhysFrame<Size1GiB>, TranslateError> {
93120
self.inner.translate_page(page)
@@ -128,6 +155,33 @@ impl<'a> Mapper<Size2MiB> for OffsetPageTable<'a> {
128155
self.inner.update_flags(page, flags)
129156
}
130157

158+
#[inline]
159+
unsafe fn set_flags_p4_entry(
160+
&mut self,
161+
page: Page<Size2MiB>,
162+
flags: PageTableFlags,
163+
) -> Result<MapperFlushAll, FlagUpdateError> {
164+
self.inner.set_flags_p4_entry(page, flags)
165+
}
166+
167+
#[inline]
168+
unsafe fn set_flags_p3_entry(
169+
&mut self,
170+
page: Page<Size2MiB>,
171+
flags: PageTableFlags,
172+
) -> Result<MapperFlushAll, FlagUpdateError> {
173+
self.inner.set_flags_p3_entry(page, flags)
174+
}
175+
176+
#[inline]
177+
unsafe fn set_flags_p2_entry(
178+
&mut self,
179+
page: Page<Size2MiB>,
180+
flags: PageTableFlags,
181+
) -> Result<MapperFlushAll, FlagUpdateError> {
182+
self.inner.set_flags_p2_entry(page, flags)
183+
}
184+
131185
#[inline]
132186
fn translate_page(&self, page: Page<Size2MiB>) -> Result<PhysFrame<Size2MiB>, TranslateError> {
133187
self.inner.translate_page(page)
@@ -168,6 +222,33 @@ impl<'a> Mapper<Size4KiB> for OffsetPageTable<'a> {
168222
self.inner.update_flags(page, flags)
169223
}
170224

225+
#[inline]
226+
unsafe fn set_flags_p4_entry(
227+
&mut self,
228+
page: Page<Size4KiB>,
229+
flags: PageTableFlags,
230+
) -> Result<MapperFlushAll, FlagUpdateError> {
231+
self.inner.set_flags_p4_entry(page, flags)
232+
}
233+
234+
#[inline]
235+
unsafe fn set_flags_p3_entry(
236+
&mut self,
237+
page: Page<Size4KiB>,
238+
flags: PageTableFlags,
239+
) -> Result<MapperFlushAll, FlagUpdateError> {
240+
self.inner.set_flags_p3_entry(page, flags)
241+
}
242+
243+
#[inline]
244+
unsafe fn set_flags_p2_entry(
245+
&mut self,
246+
page: Page<Size4KiB>,
247+
flags: PageTableFlags,
248+
) -> Result<MapperFlushAll, FlagUpdateError> {
249+
self.inner.set_flags_p2_entry(page, flags)
250+
}
251+
171252
#[inline]
172253
fn translate_page(&self, page: Page<Size4KiB>) -> Result<PhysFrame<Size4KiB>, TranslateError> {
173254
self.inner.translate_page(page)

0 commit comments

Comments
 (0)