mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-23 01:13:23 +00:00
Sanitize the mutability of page table metadata
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
819e8dacd5
commit
862b64b786
@ -175,13 +175,6 @@ pub struct FrameMeta {
|
|||||||
|
|
||||||
impl Sealed for FrameMeta {}
|
impl Sealed for FrameMeta {}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct PageTablePageMetaInner {
|
|
||||||
pub level: PagingLevel,
|
|
||||||
pub nr_children: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The metadata of any kinds of page table pages.
|
/// The metadata of any kinds of page table pages.
|
||||||
/// Make sure the the generic parameters don't effect the memory layout.
|
/// Make sure the the generic parameters don't effect the memory layout.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -192,9 +185,12 @@ pub struct PageTablePageMeta<
|
|||||||
> where
|
> where
|
||||||
[(); C::NR_LEVELS as usize]:,
|
[(); C::NR_LEVELS as usize]:,
|
||||||
{
|
{
|
||||||
|
pub level: PagingLevel,
|
||||||
|
/// The lock for the page table page.
|
||||||
pub lock: AtomicU8,
|
pub lock: AtomicU8,
|
||||||
pub inner: UnsafeCell<PageTablePageMetaInner>,
|
/// The number of valid PTEs. It is mutable if the lock is held.
|
||||||
_phantom: PhantomData<(E, C)>,
|
pub nr_children: UnsafeCell<u16>,
|
||||||
|
_phantom: core::marker::PhantomData<(E, C)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: PageTableEntryTrait, C: PagingConstsTrait> PageTablePageMeta<E, C>
|
impl<E: PageTableEntryTrait, C: PagingConstsTrait> PageTablePageMeta<E, C>
|
||||||
@ -203,11 +199,9 @@ where
|
|||||||
{
|
{
|
||||||
pub fn new_locked(level: PagingLevel) -> Self {
|
pub fn new_locked(level: PagingLevel) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
level,
|
||||||
lock: AtomicU8::new(1),
|
lock: AtomicU8::new(1),
|
||||||
inner: UnsafeCell::new(PageTablePageMetaInner {
|
nr_children: UnsafeCell::new(0),
|
||||||
level,
|
|
||||||
nr_children: 0,
|
|
||||||
}),
|
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ use crate::{
|
|||||||
paddr_to_vaddr,
|
paddr_to_vaddr,
|
||||||
page::{
|
page::{
|
||||||
self,
|
self,
|
||||||
meta::{PageMeta, PageTablePageMeta, PageTablePageMetaInner, PageUsage},
|
meta::{PageMeta, PageTablePageMeta, PageUsage},
|
||||||
DynPage, Page,
|
DynPage, Page,
|
||||||
},
|
},
|
||||||
page_prop::PageProperty,
|
page_prop::PageProperty,
|
||||||
@ -462,8 +462,16 @@ where
|
|||||||
unsafe { self.as_ptr().add(idx).read() }
|
unsafe { self.as_ptr().add(idx).read() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_paddr(&self) -> Paddr {
|
/// The number of valid PTEs.
|
||||||
self.page.paddr()
|
pub(super) fn nr_children(&self) -> u16 {
|
||||||
|
// SAFETY: The lock is held so there is no mutable reference to it.
|
||||||
|
// It would be safe to read.
|
||||||
|
unsafe { *self.meta().nr_children.get() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nr_children_mut(&mut self) -> &mut u16 {
|
||||||
|
// SAFETY: The lock is held so we have an exclusive access.
|
||||||
|
unsafe { &mut *self.meta().nr_children.get() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces a page table entry at a given index.
|
/// Replaces a page table entry at a given index.
|
||||||
@ -504,13 +512,13 @@ where
|
|||||||
|
|
||||||
// Update the child count.
|
// Update the child count.
|
||||||
if pte.is_none() {
|
if pte.is_none() {
|
||||||
self.meta_mut().nr_children -= 1;
|
*self.nr_children_mut() -= 1;
|
||||||
}
|
}
|
||||||
} else if let Some(e) = pte {
|
} else if let Some(e) = pte {
|
||||||
// SAFETY: This is safe as described in the above branch.
|
// SAFETY: This is safe as described in the above branch.
|
||||||
unsafe { (self.as_ptr() as *mut E).add(idx).write(e) };
|
unsafe { (self.as_ptr() as *mut E).add(idx).write(e) };
|
||||||
|
|
||||||
self.meta_mut().nr_children += 1;
|
*self.nr_children_mut() += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,16 +526,12 @@ where
|
|||||||
paddr_to_vaddr(self.start_paddr()) as *const E
|
paddr_to_vaddr(self.start_paddr()) as *const E
|
||||||
}
|
}
|
||||||
|
|
||||||
fn meta(&self) -> &PageTablePageMetaInner {
|
fn start_paddr(&self) -> Paddr {
|
||||||
// SAFETY: We have exclusively locked the page, so we can derive an immutable reference
|
self.page.paddr()
|
||||||
// from an immutable reference to the lock guard.
|
|
||||||
unsafe { &*self.page.meta().inner.get() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn meta_mut(&mut self) -> &mut PageTablePageMetaInner {
|
fn meta(&self) -> &PageTablePageMeta<E, C> {
|
||||||
// SAFETY: We have exclusively locked the page, so we can derive a mutable reference from a
|
self.page.meta()
|
||||||
// mutable reference to the lock guard.
|
|
||||||
unsafe { &mut *self.page.meta().inner.get() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,9 +553,7 @@ where
|
|||||||
|
|
||||||
fn on_drop(page: &mut Page<Self>) {
|
fn on_drop(page: &mut Page<Self>) {
|
||||||
let paddr = page.paddr();
|
let paddr = page.paddr();
|
||||||
|
let level = page.meta().level;
|
||||||
let inner = unsafe { &mut *page.meta().inner.get() };
|
|
||||||
let level = inner.level;
|
|
||||||
|
|
||||||
// Drop the children.
|
// Drop the children.
|
||||||
for i in 0..nr_subpage_per_huge::<C>() {
|
for i in 0..nr_subpage_per_huge::<C>() {
|
||||||
|
Reference in New Issue
Block a user