Add per-CPU counters and track RSS for each Vmar

This commit is contained in:
Wang Siyuan
2025-06-03 14:05:34 +00:00
committed by Ruihan Li
parent dfd3042276
commit 58e4f45bb1
10 changed files with 422 additions and 40 deletions

View File

@ -246,7 +246,8 @@ unsafe fn dfs_release_lock<'rcu, E: PageTableEntryTrait, C: PagingConstsTrait>(
}
}
/// Marks all the nodes in the sub-tree rooted at the node as stray.
/// Marks all the nodes in the sub-tree rooted at the node as stray, and
/// returns the num of pages mapped within the sub-tree.
///
/// This function must be called upon the node after the node is removed
/// from the parent page table.
@ -263,13 +264,15 @@ unsafe fn dfs_release_lock<'rcu, E: PageTableEntryTrait, C: PagingConstsTrait>(
pub(super) unsafe fn dfs_mark_stray_and_unlock<E: PageTableEntryTrait, C: PagingConstsTrait>(
rcu_guard: &dyn InAtomicMode,
mut sub_tree: PageTableGuard<E, C>,
) {
) -> usize {
*sub_tree.stray_mut() = true;
if sub_tree.level() == 1 {
return;
return sub_tree.nr_children() as usize;
}
let mut num_pages = 0;
for i in (0..nr_subpage_per_huge::<C>()).rev() {
let child = sub_tree.entry(i);
match child.to_ref() {
@ -278,11 +281,13 @@ pub(super) unsafe fn dfs_mark_stray_and_unlock<E: PageTableEntryTrait, C: Paging
let locked_pt = unsafe { pt.make_guard_unchecked(rcu_guard) };
// SAFETY: The caller ensures that all the nodes in the sub-tree are locked and all
// guards are forgotten.
unsafe { dfs_mark_stray_and_unlock(rcu_guard, locked_pt) };
num_pages += unsafe { dfs_mark_stray_and_unlock(rcu_guard, locked_pt) };
}
Child::None | Child::Frame(_, _) | Child::Untracked(_, _, _) | Child::PageTable(_) => {}
}
}
num_pages
}
fn dfs_get_idx_range<C: PagingConstsTrait>(

View File

@ -102,6 +102,7 @@ pub enum PageTableItem {
pt: Frame<dyn AnyFrameMeta>,
va: Vaddr,
len: usize,
num_pages: usize,
},
}
@ -600,12 +601,14 @@ impl<'rcu, M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait>
// SAFETY:
// - We checked that we are not unmapping shared kernel page table nodes.
// - We must have locked the entire sub-tree since the range is locked.
unsafe { locking::dfs_mark_stray_and_unlock(rcu_guard, locked_pt) };
let num_pages =
unsafe { locking::dfs_mark_stray_and_unlock(rcu_guard, locked_pt) };
PageTableItem::StrayPageTable {
pt: (*pt).clone().into(),
va: self.0.va,
len: page_size::<C>(self.0.level),
num_pages,
}
}
Child::None | Child::PageTableRef(_) => unreachable!(),
@ -705,7 +708,8 @@ impl<'rcu, M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait>
None
}
/// Copies the mapping from the given cursor to the current cursor.
/// Copies the mapping from the given cursor to the current cursor,
/// and returns the num of pages mapped by the current cursor.
///
/// All the mappings in the current cursor's range must be empty. The
/// function allows the source cursor to operate on the mapping before
@ -737,7 +741,7 @@ impl<'rcu, M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait>
src: &mut Self,
len: usize,
op: &mut impl FnMut(&mut PageProperty),
) {
) -> usize {
assert!(len % page_size::<C>(1) == 0);
let this_end = self.0.va + len;
assert!(this_end <= self.0.barrier_va.end);
@ -746,6 +750,7 @@ impl<'rcu, M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait>
let rcu_guard = self.0.rcu_guard;
let mut num_mapped: usize = 0;
while self.0.va < this_end && src.0.va < src_end {
let src_va = src.0.va;
let mut src_entry = src.0.cur_entry();
@ -789,9 +794,13 @@ impl<'rcu, M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait>
// This assertion is to ensure that they move by the same length.
debug_assert_eq!(mapped_page_size, page_size::<C>(src.0.level));
src.0.move_forward();
num_mapped += 1;
}
}
}
num_mapped
}
}

View File

@ -289,7 +289,8 @@ impl<'a> CursorMut<'a> {
}
}
/// Clear the mapping starting from the current slot.
/// Clears the mapping starting from the current slot,
/// and returns the number of unmapped pages.
///
/// This method will bring the cursor forward by `len` bytes in the virtual
/// address space after the modification.
@ -305,15 +306,16 @@ impl<'a> CursorMut<'a> {
/// # Panics
///
/// This method will panic if `len` is not page-aligned.
pub fn unmap(&mut self, len: usize) {
pub fn unmap(&mut self, len: usize) -> usize {
assert!(len % super::PAGE_SIZE == 0);
let end_va = self.virt_addr() + len;
let mut num_unmapped: usize = 0;
loop {
// SAFETY: It is safe to un-map memory in the userspace.
let result = unsafe { self.pt_cursor.take_next(end_va - self.virt_addr()) };
match result {
PageTableItem::Mapped { va, page, .. } => {
num_unmapped += 1;
self.flusher
.issue_tlb_flush_with(TlbFlushOp::Address(va), page);
}
@ -323,7 +325,13 @@ impl<'a> CursorMut<'a> {
PageTableItem::MappedUntracked { .. } => {
panic!("found untracked memory mapped into `VmSpace`");
}
PageTableItem::StrayPageTable { pt, va, len } => {
PageTableItem::StrayPageTable {
pt,
va,
len,
num_pages,
} => {
num_unmapped += num_pages;
self.flusher
.issue_tlb_flush_with(TlbFlushOp::Range(va..va + len), pt);
}
@ -331,6 +339,7 @@ impl<'a> CursorMut<'a> {
}
self.flusher.dispatch_tlb_flush();
num_unmapped
}
/// Applies the operation to the next slot of mapping within the range.
@ -365,7 +374,8 @@ impl<'a> CursorMut<'a> {
unsafe { self.pt_cursor.protect_next(len, &mut op) }
}
/// Copies the mapping from the given cursor to the current cursor.
/// Copies the mapping from the given cursor to the current cursor,
/// and returns the num of pages mapped by the current cursor.
///
/// All the mappings in the current cursor's range must be empty. The
/// function allows the source cursor to operate on the mapping before
@ -391,7 +401,7 @@ impl<'a> CursorMut<'a> {
src: &mut Self,
len: usize,
op: &mut impl FnMut(&mut PageProperty),
) {
) -> usize {
// SAFETY: Operations on user memory spaces are safe if it doesn't
// involve dropping any pages.
unsafe { self.pt_cursor.copy_from(&mut src.pt_cursor, len, op) }