mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26: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) {
|
fn clear_vm_space(&self) {
|
||||||
let mut cursor = self.vm_space.cursor_mut(&(0..ROOT_VMAR_CAP_ADDR)).unwrap();
|
self.vm_space.clear().unwrap();
|
||||||
cursor.unmap(ROOT_VMAR_CAP_ADDR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(&self, range: Range<usize>) -> Result<()> {
|
pub fn destroy(&self, range: Range<usize>) -> Result<()> {
|
||||||
|
@ -76,10 +76,7 @@ use super::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
mm::{
|
mm::{
|
||||||
kspace::should_map_as_tracked,
|
kspace::should_map_as_tracked,
|
||||||
page::{
|
page::{meta::MapTrackingStatus, DynPage},
|
||||||
meta::{MapTrackingStatus, PageTablePageMeta},
|
|
||||||
DynPage, Page,
|
|
||||||
},
|
|
||||||
Paddr, PageProperty, Vaddr,
|
Paddr, PageProperty, Vaddr,
|
||||||
},
|
},
|
||||||
task::{disable_preempt, DisabledPreemptGuard},
|
task::{disable_preempt, DisabledPreemptGuard},
|
||||||
@ -593,8 +590,11 @@ where
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go down if not applicable.
|
// Go down if not applicable or if the entry points to a child page table.
|
||||||
if cur_va % page_size::<C>(cur_level) != 0 || cur_va + page_size::<C>(cur_level) > end {
|
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();
|
let child = cur_entry.to_owned();
|
||||||
match child {
|
match child {
|
||||||
Child::PageTable(pt) => {
|
Child::PageTable(pt) => {
|
||||||
@ -645,10 +645,7 @@ where
|
|||||||
prop,
|
prop,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Child::PageTable(node) => PageTableItem::PageTableNode {
|
Child::PageTable(_) | Child::None => unreachable!(),
|
||||||
page: Page::<PageTablePageMeta<E, C>>::from(node).into(),
|
|
||||||
},
|
|
||||||
Child::None => unreachable!(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +92,26 @@ impl PageTable<UserMode> {
|
|||||||
self.root.activate();
|
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> {
|
impl PageTable<KernelMode> {
|
||||||
|
@ -12,7 +12,9 @@
|
|||||||
use core::{ops::Range, sync::atomic::Ordering};
|
use core::{ops::Range, sync::atomic::Ordering};
|
||||||
|
|
||||||
use crate::{
|
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::{AtomicCpuSet, CpuExceptionInfo, CpuSet, PinCurrentCpu},
|
||||||
cpu_local_cell,
|
cpu_local_cell,
|
||||||
mm::{
|
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.
|
/// Gets an immutable cursor in the virtual address range.
|
||||||
///
|
///
|
||||||
/// The cursor behaves like a lock guard, exclusively owning a sub-tree of
|
/// 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.
|
/// The cursor for querying over the VM space without modifying it.
|
||||||
///
|
///
|
||||||
/// It exclusively owns a sub-tree of the page table, preventing others from
|
/// It exclusively owns a sub-tree of the page table, preventing others from
|
||||||
|
Loading…
x
Reference in New Issue
Block a user