mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26:48 +00:00
add vmo and vmar tests; forbid clone vmo
This commit is contained in:
parent
984a8259b2
commit
4645986337
1
src/Cargo.lock
generated
1
src/Cargo.lock
generated
@ -316,6 +316,7 @@ dependencies = [
|
|||||||
"ascii",
|
"ascii",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"controlled",
|
"controlled",
|
||||||
|
"cpio-decoder",
|
||||||
"intrusive-collections",
|
"intrusive-collections",
|
||||||
"jinux-block",
|
"jinux-block",
|
||||||
"jinux-frame",
|
"jinux-frame",
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use super::{DirentWriterContext, Inode, InodeMode, InodeType, Metadata, PageCacheManager};
|
use super::{DirentWriterContext, Inode, InodeMode, InodeType, Metadata, PageCacheManager};
|
||||||
use crate::rights::Rights;
|
use crate::rights::Rights;
|
||||||
use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions};
|
use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions};
|
||||||
@ -22,7 +21,7 @@ struct Inner {
|
|||||||
impl Vnode {
|
impl Vnode {
|
||||||
pub fn new(inode: Arc<dyn Inode>) -> Result<Self> {
|
pub fn new(inode: Arc<dyn Inode>) -> Result<Self> {
|
||||||
let page_cache_manager = Arc::new(PageCacheManager::new(&Arc::downgrade(&inode)));
|
let page_cache_manager = Arc::new(PageCacheManager::new(&Arc::downgrade(&inode)));
|
||||||
let page_cache = VmoOptions::<Rights>::new(inode.len())
|
let page_cache = VmoOptions::<Rights>::new(inode.metadata().size)
|
||||||
.flags(VmoFlags::RESIZABLE)
|
.flags(VmoFlags::RESIZABLE)
|
||||||
.pager(page_cache_manager.clone())
|
.pager(page_cache_manager.clone())
|
||||||
.alloc()?;
|
.alloc()?;
|
||||||
|
@ -131,3 +131,86 @@ impl<R> VmarChildOptions<R> {
|
|||||||
Ok(child_vmar)
|
Ok(child_vmar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use crate::vm::page_fault_handler::PageFaultHandler;
|
||||||
|
use crate::vm::perms::VmPerms;
|
||||||
|
use crate::vm::vmo::VmoRightsOp;
|
||||||
|
use crate::{
|
||||||
|
rights::Full,
|
||||||
|
vm::{vmar::ROOT_VMAR_HIGHEST_ADDR, vmo::VmoOptions},
|
||||||
|
};
|
||||||
|
use jinux_frame::vm::VmIo;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn root_vmar() {
|
||||||
|
let vmar = Vmar::<Full>::new_root().unwrap();
|
||||||
|
assert!(vmar.size() == ROOT_VMAR_HIGHEST_ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn child_vmar() {
|
||||||
|
let root_vmar = Vmar::<Full>::new_root().unwrap();
|
||||||
|
let root_vmar_dup = root_vmar.dup().unwrap();
|
||||||
|
let child_vmar = VmarChildOptions::new(root_vmar_dup, 10 * PAGE_SIZE)
|
||||||
|
.alloc()
|
||||||
|
.unwrap();
|
||||||
|
assert!(child_vmar.size() == 10 * PAGE_SIZE);
|
||||||
|
let root_vmar_dup = root_vmar.dup().unwrap();
|
||||||
|
let second_child = VmarChildOptions::new(root_vmar_dup, 9 * PAGE_SIZE)
|
||||||
|
.alloc()
|
||||||
|
.unwrap();
|
||||||
|
let root_vmar_dup = root_vmar.dup().unwrap();
|
||||||
|
assert!(VmarChildOptions::new(root_vmar_dup, 9 * PAGE_SIZE)
|
||||||
|
.offset(11 * PAGE_SIZE)
|
||||||
|
.alloc()
|
||||||
|
.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn map_vmo() {
|
||||||
|
let root_vmar = Vmar::<Full>::new_root().unwrap();
|
||||||
|
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap().to_dyn();
|
||||||
|
let perms = VmPerms::READ | VmPerms::WRITE;
|
||||||
|
let map_offset = 0x1000_0000;
|
||||||
|
let vmo_dup = vmo.dup().unwrap();
|
||||||
|
root_vmar
|
||||||
|
.new_map(vmo_dup, perms)
|
||||||
|
.unwrap()
|
||||||
|
.offset(map_offset)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
root_vmar.write_val(map_offset, &100u8).unwrap();
|
||||||
|
assert!(root_vmar.read_val::<u8>(map_offset).unwrap() == 100);
|
||||||
|
let another_map_offset = 0x1100_0000;
|
||||||
|
let vmo_dup = vmo.dup().unwrap();
|
||||||
|
root_vmar
|
||||||
|
.new_map(vmo_dup, perms)
|
||||||
|
.unwrap()
|
||||||
|
.offset(another_map_offset)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
assert!(root_vmar.read_val::<u8>(another_map_offset).unwrap() == 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn handle_page_fault() {
|
||||||
|
const OFFSET: usize = 0x1000_0000;
|
||||||
|
let root_vmar = Vmar::<Full>::new_root().unwrap();
|
||||||
|
// the page is not mapped by a vmo
|
||||||
|
assert!(root_vmar.handle_page_fault(OFFSET, true, true).is_err());
|
||||||
|
// the page is mapped READ
|
||||||
|
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap().to_dyn();
|
||||||
|
let perms = VmPerms::READ;
|
||||||
|
let vmo_dup = vmo.dup().unwrap();
|
||||||
|
root_vmar
|
||||||
|
.new_map(vmo_dup, perms)
|
||||||
|
.unwrap()
|
||||||
|
.offset(OFFSET)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
root_vmar.handle_page_fault(OFFSET, true, false).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -244,7 +244,7 @@ impl VmMapping {
|
|||||||
map_size,
|
map_size,
|
||||||
map_to_addr,
|
map_to_addr,
|
||||||
} = self;
|
} = self;
|
||||||
let parent_vmo = vmo.clone();
|
let parent_vmo = vmo.dup().unwrap();
|
||||||
let vmo_size = parent_vmo.size();
|
let vmo_size = parent_vmo.size();
|
||||||
let child_vmo = VmoChildOptions::new_cow(parent_vmo, 0..vmo_size).alloc()?;
|
let child_vmo = VmoChildOptions::new_cow(parent_vmo, 0..vmo_size).alloc()?;
|
||||||
let parent_vmar = new_parent.upgrade().unwrap();
|
let parent_vmar = new_parent.upgrade().unwrap();
|
||||||
|
@ -149,12 +149,6 @@ impl Vmo<Rights> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Vmo<Rights> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
Self(self.0.clone(), self.1.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VmIo for Vmo<Rights> {
|
impl VmIo for Vmo<Rights> {
|
||||||
fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> jinux_frame::Result<()> {
|
fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> jinux_frame::Result<()> {
|
||||||
self.check_rights(Rights::READ)?;
|
self.check_rights(Rights::READ)?;
|
||||||
|
@ -522,3 +522,99 @@ impl VmoChildType for VmoSliceChild {}
|
|||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct VmoCowChild;
|
pub struct VmoCowChild;
|
||||||
impl VmoChildType for VmoCowChild {}
|
impl VmoChildType for VmoCowChild {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use crate::rights::Full;
|
||||||
|
use jinux_frame::vm::VmIo;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn alloc_vmo() {
|
||||||
|
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap();
|
||||||
|
assert!(vmo.size() == PAGE_SIZE);
|
||||||
|
// the vmo is zeroed once allocated
|
||||||
|
assert!(vmo.read_val::<usize>(0).unwrap() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
/// FIXME: alloc continuous frames is not supported now
|
||||||
|
fn alloc_continuous_vmo() {
|
||||||
|
let vmo = VmoOptions::<Full>::new(10 * PAGE_SIZE)
|
||||||
|
.flags(VmoFlags::CONTIGUOUS)
|
||||||
|
.alloc()
|
||||||
|
.unwrap();
|
||||||
|
assert!(vmo.size() == 10 * PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn write_and_read() {
|
||||||
|
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap();
|
||||||
|
let val = 42u8;
|
||||||
|
// write val
|
||||||
|
vmo.write_val(111, &val).unwrap();
|
||||||
|
let read_val: u8 = vmo.read_val(111).unwrap();
|
||||||
|
assert!(val == read_val);
|
||||||
|
// bit endian
|
||||||
|
vmo.write_bytes(222, &[0x12, 0x34, 0x56, 0x78]).unwrap();
|
||||||
|
let read_val: u32 = vmo.read_val(222).unwrap();
|
||||||
|
assert!(read_val == 0x78563412)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn slice_child() {
|
||||||
|
let parent = VmoOptions::<Full>::new(2 * PAGE_SIZE).alloc().unwrap();
|
||||||
|
let parent_dup = parent.dup().unwrap();
|
||||||
|
let slice_child = VmoChildOptions::new_slice(parent_dup, 0..PAGE_SIZE)
|
||||||
|
.alloc()
|
||||||
|
.unwrap();
|
||||||
|
// write parent, read child
|
||||||
|
parent.write_val(1, &42u8).unwrap();
|
||||||
|
assert!(slice_child.read_val::<u8>(1).unwrap() == 42);
|
||||||
|
// write child, read parent
|
||||||
|
slice_child.write_val(99, &0x1234u32).unwrap();
|
||||||
|
assert!(parent.read_val::<u32>(99).unwrap() == 0x1234);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cow_child() {
|
||||||
|
let parent = VmoOptions::<Full>::new(2 * PAGE_SIZE).alloc().unwrap();
|
||||||
|
let parent_dup = parent.dup().unwrap();
|
||||||
|
let cow_child = VmoChildOptions::new_cow(parent_dup, 0..10 * PAGE_SIZE)
|
||||||
|
.alloc()
|
||||||
|
.unwrap();
|
||||||
|
// write parent, read child
|
||||||
|
parent.write_val(1, &42u8).unwrap();
|
||||||
|
assert!(cow_child.read_val::<u8>(1).unwrap() == 42);
|
||||||
|
// write child to trigger copy on write, read child and parent
|
||||||
|
cow_child.write_val(99, &0x1234u32).unwrap();
|
||||||
|
assert!(cow_child.read_val::<u32>(99).unwrap() == 0x1234);
|
||||||
|
assert!(cow_child.read_val::<u32>(1).unwrap() == 42);
|
||||||
|
assert!(parent.read_val::<u32>(99).unwrap() == 0);
|
||||||
|
assert!(parent.read_val::<u32>(1).unwrap() == 42);
|
||||||
|
// write parent on already-copied page
|
||||||
|
parent.write_val(10, &123u8).unwrap();
|
||||||
|
assert!(parent.read_val::<u32>(10).unwrap() == 123);
|
||||||
|
assert!(cow_child.read_val::<u32>(10).unwrap() == 0);
|
||||||
|
// write parent on not-copied page
|
||||||
|
parent.write_val(PAGE_SIZE + 10, &12345u32).unwrap();
|
||||||
|
assert!(parent.read_val::<u32>(PAGE_SIZE + 10).unwrap() == 12345);
|
||||||
|
assert!(cow_child.read_val::<u32>(PAGE_SIZE + 10).unwrap() == 12345);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn resize() {
|
||||||
|
let vmo = VmoOptions::<Full>::new(PAGE_SIZE)
|
||||||
|
.flags(VmoFlags::RESIZABLE)
|
||||||
|
.alloc()
|
||||||
|
.unwrap();
|
||||||
|
vmo.write_val(10, &42u8).unwrap();
|
||||||
|
vmo.resize(2 * PAGE_SIZE).unwrap();
|
||||||
|
assert!(vmo.size() == 2 * PAGE_SIZE);
|
||||||
|
assert!(vmo.read_val::<u8>(10).unwrap() == 42);
|
||||||
|
vmo.write_val(PAGE_SIZE + 20, &123u8).unwrap();
|
||||||
|
vmo.resize(PAGE_SIZE).unwrap();
|
||||||
|
assert!(vmo.read_val::<u8>(10).unwrap() == 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user