Rename fork_vmar to fork_from

This commit is contained in:
Jianfeng Jiang
2023-09-05 11:33:21 +08:00
committed by Tate, Hongliang Tian
parent d9fcb486c0
commit baeaa9b4d3
9 changed files with 125 additions and 125 deletions

View File

@ -340,7 +340,7 @@ fn clone_vm(parent_process_vm: &ProcessVm, clone_flags: CloneFlags) -> Result<Pr
if clone_flags.contains(CloneFlags::CLONE_VM) {
Ok(parent_process_vm.clone())
} else {
let root_vmar = parent_process_vm.root_vmar().fork_vmar()?;
let root_vmar = Vmar::<Full>::fork_from(parent_process_vm.root_vmar())?;
let user_heap = parent_process_vm.user_heap().clone();
Ok(ProcessVm::new(user_heap, root_vmar))
}

View File

@ -134,9 +134,7 @@ impl<'a> ProcessBuilder<'a> {
sig_dispositions,
} = self;
let process_vm = process_vm
.or_else(|| Some(ProcessVm::alloc().unwrap()))
.unwrap();
let process_vm = process_vm.or_else(|| Some(ProcessVm::alloc())).unwrap();
let process_group_ref = process_group
.as_ref()

View File

@ -6,7 +6,6 @@
pub mod user_heap;
use crate::prelude::*;
use jinux_rights::Full;
use user_heap::UserHeap;
@ -55,14 +54,14 @@ impl Clone for ProcessVm {
}
impl ProcessVm {
pub fn alloc() -> Result<Self> {
let root_vmar = Vmar::<Full>::new_root()?;
pub fn alloc() -> Self {
let root_vmar = Vmar::<Full>::new_root();
let user_heap = UserHeap::new();
user_heap.init(&root_vmar);
Ok(ProcessVm {
ProcessVm {
user_heap,
root_vmar,
})
}
}
pub fn new(user_heap: UserHeap, root_vmar: Vmar<Full>) -> Self {

View File

@ -44,8 +44,7 @@ impl KernelThreadExt for Thread {
};
let tid = allocate_tid();
let thread = Arc::new_cyclic(|thread_ref| {
let weal_thread = thread_ref.clone();
let task = Task::new(thread_fn, weal_thread, None).unwrap();
let task = Task::new(thread_fn, thread_ref.clone(), None).unwrap();
let status = ThreadStatus::Init;
let kernel_thread = KernelThread;
Thread::new(tid, task, kernel_thread, status)

View File

@ -12,11 +12,10 @@ use super::{
impl Vmar<Rights> {
/// Creates a root VMAR.
pub fn new_root() -> Result<Self> {
let inner = Arc::new(Vmar_::new_root()?);
pub fn new_root() -> Self {
let inner = Vmar_::new_root();
let rights = Rights::all();
let new_self = Self(inner, rights);
Ok(new_self)
Self(inner, rights)
}
/// Maps the given VMO into the VMAR through a set of VMAR mapping options.
@ -143,10 +142,16 @@ impl Vmar<Rights> {
Ok(Vmar(self.0.clone(), self.1))
}
/// Given a map size, returns the possible map address without doing actual allocation.
pub fn hint_map_addr(&self, map_size: usize) -> Result<Vaddr> {
self.check_rights(Rights::READ)?;
self.0.hint_map_addr(map_size)
/// Creates a new root VMAR whose content is inherited from another
/// using copy-on-write (COW) technique.
///
/// # Access rights
///
/// The method requires the Read right.
pub fn fork_from(vmar: &Vmar) -> Result<Self> {
vmar.check_rights(Rights::READ)?;
let vmar_ = vmar.0.new_cow_root()?;
Ok(Vmar(vmar_, Rights::all()))
}
}

View File

@ -14,7 +14,7 @@ use alloc::sync::Weak;
use alloc::vec::Vec;
use core::ops::Range;
use jinux_frame::vm::VmSpace;
use jinux_rights::{Dup, Exec, Full, Read, Rights, Signal, TRightSet, TRights, Write};
use jinux_rights::Rights;
use self::vm_mapping::VmMapping;
@ -112,14 +112,47 @@ struct VmarInner {
free_regions: BTreeMap<Vaddr, FreeRegion>,
}
impl VmarInner {
const fn new() -> Self {
Self {
is_destroyed: false,
child_vmar_s: BTreeMap::new(),
vm_mappings: BTreeMap::new(),
free_regions: BTreeMap::new(),
}
}
}
// FIXME: How to set the correct root vmar range?
// We should not include addr 0 here(is this right?), since the 0 addr means the null pointer.
// We should include addr 0x0040_0000, since non-pie executables typically are put on 0x0040_0000.
pub const ROOT_VMAR_LOWEST_ADDR: Vaddr = 0x0010_0000;
pub const ROOT_VMAR_HIGHEST_ADDR: Vaddr = 0x1000_0000_0000;
const ROOT_VMAR_LOWEST_ADDR: Vaddr = 0x0010_0000;
const ROOT_VMAR_HIGHEST_ADDR: Vaddr = 0x1000_0000_0000;
impl Vmar_ {
pub fn new_root() -> Result<Self> {
fn new(
inner: VmarInner,
vm_space: VmSpace,
base: usize,
size: usize,
parent: Option<&Arc<Vmar_>>,
) -> Arc<Self> {
let parent = if let Some(parent) = parent {
Arc::downgrade(parent)
} else {
Weak::new()
};
Arc::new(Vmar_ {
inner: Mutex::new(inner),
base,
size,
vm_space,
parent,
})
}
pub fn new_root() -> Arc<Self> {
let mut free_regions = BTreeMap::new();
let root_region = FreeRegion::new(ROOT_VMAR_LOWEST_ADDR..ROOT_VMAR_HIGHEST_ADDR);
free_regions.insert(root_region.start(), root_region);
@ -129,14 +162,7 @@ impl Vmar_ {
vm_mappings: BTreeMap::new(),
free_regions,
};
let vmar_ = Vmar_ {
inner: Mutex::new(vmar_inner),
vm_space: VmSpace::new(),
base: 0,
size: ROOT_VMAR_HIGHEST_ADDR,
parent: Weak::new(),
};
Ok(vmar_)
Vmar_::new(vmar_inner, VmSpace::new(), 0, ROOT_VMAR_HIGHEST_ADDR, None)
}
fn is_root_vmar(&self) -> bool {
@ -445,13 +471,13 @@ impl Vmar_ {
vm_mappings: BTreeMap::new(),
free_regions: child_regions,
};
let child_vmar_ = Arc::new(Vmar_ {
inner: Mutex::new(child_vmar_inner),
base: child_vmar_offset,
size: child_vmar_size,
vm_space: self.vm_space.clone(),
parent: Arc::downgrade(self),
});
let child_vmar_ = Vmar_::new(
child_vmar_inner,
self.vm_space.clone(),
child_vmar_offset,
child_vmar_size,
Some(self),
);
self.inner
.lock()
.child_vmar_s
@ -591,16 +617,6 @@ impl Vmar_ {
}
}
fn hint_map_addr(&self, size: usize) -> Result<Vaddr> {
let inner = self.inner.lock();
for (free_region_base, free_region) in &inner.free_regions {
if free_region.size() >= size {
return Ok(*free_region_base);
}
}
return_errno_with_message!(Errno::ENOMEM, "cannot find a suitale free region");
}
fn trim_existing_mappings(&self, trim_range: Range<usize>) -> Result<()> {
let mut inner = self.inner.lock();
let mut mappings_to_remove = BTreeSet::new();
@ -622,35 +638,28 @@ impl Vmar_ {
Ok(())
}
/// fork vmar for child process
pub fn fork_vmar_(&self, parent: Weak<Vmar_>) -> Result<Arc<Self>> {
// create an empty vmar at first
let is_destroyed = false;
let child_vmar_s = BTreeMap::new();
let mapped_vmos = BTreeMap::new();
let free_regions = BTreeMap::new();
let vmar_inner = VmarInner {
is_destroyed,
child_vmar_s,
vm_mappings: mapped_vmos,
free_regions,
};
// If this is a root vmar, we create a new vmspace
// Otherwise, we clone the vm space from parent.
let vm_space = if let Some(parent) = parent.upgrade() {
parent.vm_space().clone()
} else {
VmSpace::new()
};
let vmar_ = Vmar_ {
inner: Mutex::new(vmar_inner),
base: self.base,
size: self.size,
vm_space,
parent,
pub(super) fn new_cow_root(self: &Arc<Self>) -> Result<Arc<Self>> {
if self.parent.upgrade().is_some() {
return_errno_with_message!(Errno::EINVAL, "can only dup cow vmar for root vmar");
}
self.new_cow(None)
}
/// Create a new vmar by creating cow child for all mapped vmos
fn new_cow(&self, parent: Option<&Arc<Vmar_>>) -> Result<Arc<Self>> {
let new_vmar_ = {
let vmar_inner = VmarInner::new();
// If this is a root vmar, we create a new vmspace,
// Otherwise, we clone the vm space from parent.
let vm_space = if let Some(parent) = parent {
parent.vm_space().clone()
} else {
VmSpace::new()
};
Vmar_::new(vmar_inner, vm_space, self.base, self.size, parent)
};
let new_vmar_ = Arc::new(vmar_);
let inner = self.inner.lock();
// clone free regions
for (free_region_base, free_region) in &inner.free_regions {
@ -663,30 +672,28 @@ impl Vmar_ {
// clone child vmars
for (child_vmar_base, child_vmar_) in &inner.child_vmar_s {
let parent_of_forked_child = Arc::downgrade(&new_vmar_);
let forked_child_vmar = child_vmar_.fork_vmar_(parent_of_forked_child)?;
let new_child_vmar = child_vmar_.new_cow(Some(&new_vmar_))?;
new_vmar_
.inner
.lock()
.child_vmar_s
.insert(*child_vmar_base, forked_child_vmar);
.insert(*child_vmar_base, new_child_vmar);
}
// clone vm mappings
for (vm_mapping_base, vm_mapping) in &inner.vm_mappings {
let parent_of_forked_mapping = Arc::downgrade(&new_vmar_);
let forked_mapping = Arc::new(vm_mapping.fork_mapping(parent_of_forked_mapping)?);
let new_mapping = Arc::new(vm_mapping.new_cow(&new_vmar_)?);
new_vmar_
.inner
.lock()
.vm_mappings
.insert(*vm_mapping_base, forked_mapping);
.insert(*vm_mapping_base, new_mapping);
}
Ok(new_vmar_)
}
/// get mapped vmo at given offset
pub fn get_vm_mapping(&self, offset: Vaddr) -> Result<Arc<VmMapping>> {
fn get_vm_mapping(&self, offset: Vaddr) -> Result<Arc<VmMapping>> {
for (vm_mapping_base, vm_mapping) in &self.inner.lock().vm_mappings {
if *vm_mapping_base <= offset && offset < *vm_mapping_base + vm_mapping.map_size() {
return Ok(vm_mapping.clone());
@ -709,17 +716,6 @@ impl<R> Vmar<R> {
self.0.size
}
/// Fork a vmar for child process
pub fn fork_vmar(&self) -> Result<Vmar<Full>> {
let rights = Rights::all();
self.check_rights(rights)?;
let vmar_ = self.0.fork_vmar_(Weak::new())?;
Ok(Vmar(
vmar_,
TRightSet(<TRights![Dup, Read, Write, Exec, Signal]>::new()),
))
}
/// get a mapped vmo
pub fn get_vm_mapping(&self, offset: Vaddr) -> Result<Arc<VmMapping>> {
let rights = Rights::all();

View File

@ -144,13 +144,13 @@ mod test {
#[test]
fn root_vmar() {
let vmar = Vmar::<Full>::new_root().unwrap();
let vmar = Vmar::<Full>::new_root();
assert!(vmar.size() == ROOT_VMAR_HIGHEST_ADDR);
}
#[test]
fn child_vmar() {
let root_vmar = Vmar::<Full>::new_root().unwrap();
let root_vmar = Vmar::<Full>::new_root();
let root_vmar_dup = root_vmar.dup().unwrap();
let child_vmar = VmarChildOptions::new(root_vmar_dup, 10 * PAGE_SIZE)
.alloc()
@ -169,7 +169,7 @@ mod test {
#[test]
fn map_vmo() {
let root_vmar = Vmar::<Full>::new_root().unwrap();
let root_vmar = Vmar::<Full>::new_root();
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap().to_dyn();
let perms = VmPerms::READ | VmPerms::WRITE;
let map_offset = 0x1000_0000;
@ -196,7 +196,7 @@ mod test {
#[test]
fn handle_page_fault() {
const OFFSET: usize = 0x1000_0000;
let root_vmar = Vmar::<Full>::new_root().unwrap();
let root_vmar = Vmar::<Full>::new_root();
// the page is not mapped by a vmo
assert!(root_vmar.handle_page_fault(OFFSET, true, true).is_err());
// the page is mapped READ

View File

@ -2,7 +2,7 @@ use core::ops::Range;
use crate::prelude::*;
use jinux_frame::vm::VmIo;
use jinux_rights::{Dup, Read, Rights, TRightSet, TRights};
use jinux_rights::{Dup, Rights, TRightSet, TRights};
use jinux_rights_proc::require;
use crate::vm::{page_fault_handler::PageFaultHandler, vmo::Vmo};
@ -17,11 +17,10 @@ impl<R: TRights> Vmar<TRightSet<R>> {
/// # Access rights
///
/// A root VMAR is initially given full access rights.
pub fn new_root() -> Result<Self> {
let inner = Arc::new(Vmar_::new_root()?);
pub fn new_root() -> Self {
let inner = Vmar_::new_root();
let rights = R::new();
let new_self = Self(inner, TRightSet(rights));
Ok(new_self)
Self(inner, TRightSet(rights))
}
/// Maps the given VMO into the VMAR through a set of VMAR mapping options.
@ -150,10 +149,16 @@ impl<R: TRights> Vmar<TRightSet<R>> {
Ok(Vmar(self.0.clone(), self.1))
}
/// Given a map size, returns the possible map address without doing actual allocation.
#[require(R > Read)]
pub fn hint_map_addr(&self, map_size: usize) -> Result<Vaddr> {
self.0.hint_map_addr(map_size)
/// Creates a new root VMAR whose content is inherited from another
/// using copy-on-write (COW) technique.
///
/// # Access rights
///
/// The method requires the Read right.
pub fn fork_from<R1>(vmar: &Vmar<R1>) -> Result<Self> {
vmar.check_rights(Rights::READ)?;
let vmar_ = vmar.0.new_cow_root()?;
Ok(Vmar(vmar_, TRightSet(R::new())))
}
/// Strict the access rights.

View File

@ -101,6 +101,7 @@ impl VmMapping {
mapped_pages: BTreeSet::new(),
page_perms,
};
Ok(Self {
inner: Mutex::new(vm_mapping_inner),
parent: Arc::downgrade(&parent_vmar),
@ -233,18 +234,30 @@ impl VmMapping {
self.inner.lock().protect(vm_space, perms, range)
}
pub(super) fn fork_mapping(&self, new_parent: Weak<Vmar_>) -> Result<VmMapping> {
pub(super) fn new_cow(&self, new_parent: &Arc<Vmar_>) -> Result<VmMapping> {
let VmMapping { inner, vmo, .. } = self;
let child_vmo = {
let parent_vmo = vmo.dup().unwrap();
let vmo_size = parent_vmo.size();
VmoChildOptions::new_cow(parent_vmo, 0..vmo_size).alloc()?
};
let inner = self.inner.lock().fork_mapping(child_vmo.size())?;
let new_inner = {
let inner = self.inner.lock();
VmMappingInner {
vmo_offset: inner.vmo_offset,
map_size: inner.map_size,
map_to_addr: inner.map_to_addr,
is_destroyed: inner.is_destroyed,
mapped_pages: BTreeSet::new(),
page_perms: inner.page_perms.clone(),
}
};
Ok(VmMapping {
inner: Mutex::new(inner),
parent: new_parent,
inner: Mutex::new(new_inner),
parent: Arc::downgrade(new_parent),
vmo: child_vmo,
})
}
@ -412,21 +425,6 @@ impl VmMappingInner {
Ok(())
}
fn fork_mapping(&self, vmo_size: usize) -> Result<VmMappingInner> {
debug!(
"fork vmo, parent size = 0x{:x}, map_to_addr = 0x{:x}",
vmo_size, self.map_to_addr
);
Ok(VmMappingInner {
is_destroyed: self.is_destroyed,
mapped_pages: BTreeSet::new(),
page_perms: self.page_perms.clone(),
vmo_offset: self.vmo_offset,
map_size: self.map_size,
map_to_addr: self.map_to_addr,
})
}
/// trim the mapping from left to a new address.
fn trim_left(&mut self, vm_space: &VmSpace, vaddr: Vaddr) -> Result<Vaddr> {
trace!(