mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Special treat VM Space clearing
This commit is contained in:
parent
fda05e9e23
commit
c34706603a
@ -339,8 +339,7 @@ impl Vmar_ {
|
||||
}
|
||||
|
||||
fn clear_vm_space(&self) {
|
||||
let mut cursor = self.vm_space.cursor_mut(&(0..ROOT_VMAR_CAP_ADDR)).unwrap();
|
||||
cursor.unmap(ROOT_VMAR_CAP_ADDR);
|
||||
self.vm_space.clear().unwrap();
|
||||
}
|
||||
|
||||
pub fn destroy(&self, range: Range<usize>) -> Result<()> {
|
||||
|
@ -76,10 +76,7 @@ use super::{
|
||||
use crate::{
|
||||
mm::{
|
||||
kspace::should_map_as_tracked,
|
||||
page::{
|
||||
meta::{MapTrackingStatus, PageTablePageMeta},
|
||||
DynPage, Page,
|
||||
},
|
||||
page::{meta::MapTrackingStatus, DynPage},
|
||||
Paddr, PageProperty, Vaddr,
|
||||
},
|
||||
task::{disable_preempt, DisabledPreemptGuard},
|
||||
@ -593,8 +590,11 @@ where
|
||||
continue;
|
||||
}
|
||||
|
||||
// Go down if not applicable.
|
||||
if cur_va % page_size::<C>(cur_level) != 0 || cur_va + page_size::<C>(cur_level) > end {
|
||||
// Go down if not applicable or if the entry points to a child page table.
|
||||
if cur_entry.is_node()
|
||||
|| cur_va % page_size::<C>(cur_level) != 0
|
||||
|| cur_va + page_size::<C>(cur_level) > end
|
||||
{
|
||||
let child = cur_entry.to_owned();
|
||||
match child {
|
||||
Child::PageTable(pt) => {
|
||||
@ -645,10 +645,7 @@ where
|
||||
prop,
|
||||
}
|
||||
}
|
||||
Child::PageTable(node) => PageTableItem::PageTableNode {
|
||||
page: Page::<PageTablePageMeta<E, C>>::from(node).into(),
|
||||
},
|
||||
Child::None => unreachable!(),
|
||||
Child::PageTable(_) | Child::None => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,26 @@ impl PageTable<UserMode> {
|
||||
self.root.activate();
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear the page table.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that:
|
||||
/// 1. No other cursors are accessing the page table.
|
||||
/// 2. No other CPUs activates the page table.
|
||||
pub(in crate::mm) unsafe fn clear(&self) {
|
||||
let mut root_node = self.root.clone_shallow().lock();
|
||||
const NR_PTES_PER_NODE: usize = nr_subpage_per_huge::<PagingConsts>();
|
||||
for i in 0..NR_PTES_PER_NODE / 2 {
|
||||
let root_entry = root_node.entry(i);
|
||||
if !root_entry.is_none() {
|
||||
let old = root_entry.replace(Child::None);
|
||||
// Since no others are accessing the old child, dropping it is fine.
|
||||
drop(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PageTable<KernelMode> {
|
||||
|
@ -12,7 +12,9 @@
|
||||
use core::{ops::Range, sync::atomic::Ordering};
|
||||
|
||||
use crate::{
|
||||
arch::mm::{current_page_table_paddr, PageTableEntry, PagingConsts},
|
||||
arch::mm::{
|
||||
current_page_table_paddr, tlb_flush_all_excluding_global, PageTableEntry, PagingConsts,
|
||||
},
|
||||
cpu::{AtomicCpuSet, CpuExceptionInfo, CpuSet, PinCurrentCpu},
|
||||
cpu_local_cell,
|
||||
mm::{
|
||||
@ -64,6 +66,35 @@ impl VmSpace {
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the user space mappings in the page table.
|
||||
///
|
||||
/// This method returns error if the page table is activated on any other
|
||||
/// CPUs or there are any cursors alive.
|
||||
pub fn clear(&self) -> core::result::Result<(), VmSpaceClearError> {
|
||||
let preempt_guard = disable_preempt();
|
||||
let _guard = self
|
||||
.activation_lock
|
||||
.try_write()
|
||||
.ok_or(VmSpaceClearError::CursorsAlive)?;
|
||||
|
||||
let cpus = self.cpus.load();
|
||||
let cpu = preempt_guard.current_cpu();
|
||||
let cpus_set_is_empty = cpus.is_empty();
|
||||
let cpus_set_is_single_self = cpus.count() == 1 && cpus.contains(cpu);
|
||||
|
||||
if cpus_set_is_empty || cpus_set_is_single_self {
|
||||
// SAFETY: We have ensured that the page table is not activated on
|
||||
// other CPUs and no cursors are alive.
|
||||
unsafe { self.pt.clear() };
|
||||
if cpus_set_is_single_self {
|
||||
tlb_flush_all_excluding_global();
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(VmSpaceClearError::PageTableActivated(cpus))
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an immutable cursor in the virtual address range.
|
||||
///
|
||||
/// The cursor behaves like a lock guard, exclusively owning a sub-tree of
|
||||
@ -195,6 +226,17 @@ impl Default for VmSpace {
|
||||
}
|
||||
}
|
||||
|
||||
/// An error that may occur when doing [`VmSpace::clear`].
|
||||
#[derive(Debug)]
|
||||
pub enum VmSpaceClearError {
|
||||
/// The page table is activated on other CPUs.
|
||||
///
|
||||
/// The activated CPUs detected are contained in the error.
|
||||
PageTableActivated(CpuSet),
|
||||
/// There are still cursors alive.
|
||||
CursorsAlive,
|
||||
}
|
||||
|
||||
/// The cursor for querying over the VM space without modifying it.
|
||||
///
|
||||
/// It exclusively owns a sub-tree of the page table, preventing others from
|
||||
|
Loading…
x
Reference in New Issue
Block a user