Do some miscellaneous page table cleanups

This commit is contained in:
Ruihan Li
2025-06-19 12:46:28 +08:00
committed by Junyang Zhang
parent 11f9675f37
commit a1accf4304
6 changed files with 128 additions and 101 deletions

View File

@ -2,8 +2,6 @@
//! This module provides accessors to the page table entries in a node.
use core::mem::ManuallyDrop;
use super::{Child, ChildRef, PageTableEntryTrait, PageTableGuard, PageTableNode};
use crate::{
mm::{
@ -78,8 +76,8 @@ impl<'a, 'rcu, C: PageTableConfig> Entry<'a, 'rcu, C> {
// SAFETY:
// 1. The index is within the bounds.
// 2. We replace the PTE with a new one, which differs only in
// `PageProperty`, so the level still matches the current
// page table node.
// `PageProperty`, so it's in `C` and at the correct paging level.
// 3. The child is still owned by the page table node.
unsafe { self.node.write_pte(self.idx, self.pte) };
}
@ -117,7 +115,8 @@ impl<'a, 'rcu, C: PageTableConfig> Entry<'a, 'rcu, C> {
// SAFETY:
// 1. The index is within the bounds.
// 2. The new PTE is a valid child whose level matches the current page table node.
// 2. The new PTE is a child in `C` and at the correct paging level.
// 3. The ownership of the child is passed to the page table node.
unsafe { self.node.write_pte(self.idx, new_pte) };
self.pte = new_pte;
@ -138,28 +137,28 @@ impl<'a, 'rcu, C: PageTableConfig> Entry<'a, 'rcu, C> {
}
let level = self.node.level();
let new_page = PageTableNode::<C>::alloc(level - 1);
let new_page = RcuDrop::new(PageTableNode::<C>::alloc(level - 1));
let paddr = new_page.start_paddr();
let _ = ManuallyDrop::new(new_page.borrow().lock(guard));
// SAFETY: The page table won't be dropped before the RCU grace period
// ends, so it outlives `'rcu`.
let pt_ref = unsafe { PageTableNodeRef::borrow_paddr(paddr) };
// Lock before writing the PTE, so no one else can operate on it.
let pt_lock_guard = pt_ref.lock(guard);
// SAFETY:
// 1. The index is within the bounds.
// 2. The new PTE is a valid child whose level matches the current page table node.
// 2. The new PTE is a child in `C` and at the correct paging level.
// 3. The ownership of the child is passed to the page table node.
unsafe {
self.node.write_pte(
self.idx,
Child::PageTable(RcuDrop::new(new_page)).into_pte(),
)
self.node
.write_pte(self.idx, Child::PageTable(new_page).into_pte())
};
*self.node.nr_children_mut() += 1;
// SAFETY: The page table won't be dropped before the RCU grace period
// ends, so it outlives `'rcu`.
let pt_ref = unsafe { PageTableNodeRef::borrow_paddr(paddr) };
// SAFETY: The node is locked and there are no other guards.
Some(unsafe { pt_ref.make_guard_unchecked(guard) })
Some(pt_lock_guard)
}
/// Splits the entry to smaller pages if it maps to a huge page.
@ -183,8 +182,15 @@ impl<'a, 'rcu, C: PageTableConfig> Entry<'a, 'rcu, C> {
let pa = self.pte.paddr();
let prop = self.pte.prop();
let new_page = PageTableNode::<C>::alloc(level - 1);
let mut pt_lock_guard = new_page.borrow().lock(guard);
let new_page = RcuDrop::new(PageTableNode::<C>::alloc(level - 1));
let paddr = new_page.start_paddr();
// SAFETY: The page table won't be dropped before the RCU grace period
// ends, so it outlives `'rcu`.
let pt_ref = unsafe { PageTableNodeRef::borrow_paddr(paddr) };
// Lock before writing the PTE, so no one else can operate on it.
let mut pt_lock_guard = pt_ref.lock(guard);
for i in 0..nr_subpage_per_huge::<C>() {
let small_pa = pa + i * page_size::<C>(level - 1);
@ -193,24 +199,16 @@ impl<'a, 'rcu, C: PageTableConfig> Entry<'a, 'rcu, C> {
debug_assert!(old.is_none());
}
let paddr = new_page.start_paddr();
let _ = ManuallyDrop::new(pt_lock_guard);
// SAFETY:
// 1. The index is within the bounds.
// 2. The new PTE is a valid child whose level matches the current page table node.
// 2. The new PTE is a child in `C` and at the correct paging level.
// 3. The ownership of the child is passed to the page table node.
unsafe {
self.node.write_pte(
self.idx,
Child::PageTable(RcuDrop::new(new_page)).into_pte(),
)
self.node
.write_pte(self.idx, Child::PageTable(new_page).into_pte())
};
// SAFETY: The page table won't be dropped before the RCU grace period
// ends, so it outlives `'rcu`.
let pt_ref = unsafe { PageTableNodeRef::borrow_paddr(paddr) };
// SAFETY: The node is locked and there are no other guards.
Some(unsafe { pt_ref.make_guard_unchecked(guard) })
Some(pt_lock_guard)
}
/// Create a new entry at the node with guard.