forked from rcore-os/zCore
buggy vmo.create_child, just use create_clone now
This commit is contained in:
parent
bd0ac9242e
commit
2e1785ad78
|
@ -132,6 +132,15 @@ pub fn pmem_write(paddr: PhysAddr, buf: &[u8]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Copy content of `src` frame to `target` frame
|
||||||
|
#[export_name = "hal_frame_copy"]
|
||||||
|
pub fn frame_copy(src: PhysAddr, target: PhysAddr) {
|
||||||
|
unsafe {
|
||||||
|
let buf = phys_to_virt(src) as *const u8;
|
||||||
|
buf.copy_to_nonoverlapping(phys_to_virt(target) as _, 4096);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Initialize the HAL.
|
/// Initialize the HAL.
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -150,6 +150,13 @@ pub fn pmem_write(_paddr: PhysAddr, _buf: &[u8]) {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Copy content of `src` frame to `target` frame
|
||||||
|
#[linkage = "weak"]
|
||||||
|
#[export_name = "hal_frame_copy"]
|
||||||
|
pub fn frame_copy(_src: PhysAddr, _target: PhysAddr) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
/// Output a char to console.
|
/// Output a char to console.
|
||||||
#[linkage = "weak"]
|
#[linkage = "weak"]
|
||||||
#[export_name = "hal_serial_write"]
|
#[export_name = "hal_serial_write"]
|
||||||
|
|
|
@ -152,11 +152,36 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
|
||||||
handles[K_ROOTJOB] = Handle::new(job, Rights::DEFAULT_JOB);
|
handles[K_ROOTJOB] = Handle::new(job, Rights::DEFAULT_JOB);
|
||||||
handles[K_ROOTRESOURCE] = Handle::new(resource, Rights::DEFAULT_RESOURCE);
|
handles[K_ROOTRESOURCE] = Handle::new(resource, Rights::DEFAULT_RESOURCE);
|
||||||
handles[K_ZBI] = Handle::new(zbi_vmo, Rights::DEFAULT_VMO);
|
handles[K_ZBI] = Handle::new(zbi_vmo, Rights::DEFAULT_VMO);
|
||||||
handles[K_FIRSTVDSO] = Handle::new(vdso_vmo, Rights::DEFAULT_VMO | Rights::EXECUTE);
|
handles[K_FIRSTVDSO] = Handle::new(vdso_vmo.clone(), Rights::DEFAULT_VMO | Rights::EXECUTE);
|
||||||
|
let vdso_test1 = vdso_vmo.create_clone(0, vdso_vmo.len());
|
||||||
|
vdso_test1.set_name("vdso/test1");
|
||||||
|
let vdso_test2 = vdso_vmo.create_clone(0, vdso_vmo.len());
|
||||||
|
vdso_test2.set_name("vdso/test2");
|
||||||
|
handles[K_FIRSTVDSO + 1] = Handle::new(vdso_test1, Rights::DEFAULT_VMO | Rights::EXECUTE);
|
||||||
|
handles[K_FIRSTVDSO + 2] = Handle::new(vdso_test2, Rights::DEFAULT_VMO | Rights::EXECUTE);
|
||||||
// FIXME correct rights for decompressor engine
|
// FIXME correct rights for decompressor engine
|
||||||
handles[K_USERBOOT_DECOMPRESSOR] =
|
handles[K_USERBOOT_DECOMPRESSOR] =
|
||||||
Handle::new(decompressor_vmo, Rights::DEFAULT_VMO | Rights::EXECUTE);
|
Handle::new(decompressor_vmo, Rights::DEFAULT_VMO | Rights::EXECUTE);
|
||||||
// TODO CrashLogVmo handle
|
// TODO to use correct CrashLogVmo handle
|
||||||
|
let crash_log_vmo = VMObjectPaged::new(1);
|
||||||
|
handles[K_CRASHLOG] = Handle::new(crash_log_vmo, Rights::DEFAULT_VMO);
|
||||||
|
// TODO to use correct CounterName handle
|
||||||
|
let counter_name_vmo = VMObjectPaged::new(1);
|
||||||
|
counter_name_vmo.set_name("counters/desc");
|
||||||
|
handles[K_COUNTERNAMES] = Handle::new(counter_name_vmo, Rights::DEFAULT_VMO);
|
||||||
|
// TODO to use correct CounterName handle
|
||||||
|
let kcounters_vmo = VMObjectPaged::new(1);
|
||||||
|
kcounters_vmo.set_name("counters/arena");
|
||||||
|
handles[K_COUNTERS] = Handle::new(kcounters_vmo, Rights::DEFAULT_VMO);
|
||||||
|
// TODO to use correct Instrumentation data handle
|
||||||
|
let instrumentation_data_vmo = VMObjectPaged::new(1);
|
||||||
|
instrumentation_data_vmo.set_name("UNIMPLEMENTED_VMO");
|
||||||
|
handles[K_FISTINSTRUMENTATIONDATA] =
|
||||||
|
Handle::new(instrumentation_data_vmo.clone(), Rights::DEFAULT_VMO);
|
||||||
|
handles[K_FISTINSTRUMENTATIONDATA + 1] =
|
||||||
|
Handle::new(instrumentation_data_vmo.clone(), Rights::DEFAULT_VMO);
|
||||||
|
handles[K_FISTINSTRUMENTATIONDATA + 2] =
|
||||||
|
Handle::new(instrumentation_data_vmo.clone(), Rights::DEFAULT_VMO);
|
||||||
|
|
||||||
// check: handle to root proc should be only
|
// check: handle to root proc should be only
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set() {
|
fn set() {
|
||||||
let timer = Timer::new();
|
let timer = Timer::create(0);
|
||||||
timer.set(timer_now() + Duration::from_millis(10), Duration::default());
|
timer.set(timer_now() + Duration::from_millis(10), Duration::default());
|
||||||
timer.set(timer_now() + Duration::from_millis(20), Duration::default());
|
timer.set(timer_now() + Duration::from_millis(20), Duration::default());
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cancel() {
|
fn cancel() {
|
||||||
let timer = Timer::new();
|
let timer = Timer::create(0);
|
||||||
timer.set(timer_now() + Duration::from_millis(10), Duration::default());
|
timer.set(timer_now() + Duration::from_millis(10), Duration::default());
|
||||||
|
|
||||||
std::thread::sleep(Duration::from_millis(5));
|
std::thread::sleep(Duration::from_millis(5));
|
||||||
|
|
|
@ -533,7 +533,12 @@ mod tests {
|
||||||
// duplicate handle which does not have `Rights::DUPLICATE` should fail.
|
// duplicate handle which does not have `Rights::DUPLICATE` should fail.
|
||||||
let handle_value = proc.add_handle(Handle::new(proc.clone(), Rights::empty()));
|
let handle_value = proc.add_handle(Handle::new(proc.clone(), Rights::empty()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
proc.dup_handle_operating_rights(handle_value, |_| Ok(Rights::SAME_RIGHTS)),
|
proc.dup_handle_operating_rights(handle_value, |handle_rights| {
|
||||||
|
if !handle_rights.contains(Rights::DUPLICATE) {
|
||||||
|
return Err(ZxError::ACCESS_DENIED);
|
||||||
|
}
|
||||||
|
Ok(handle_rights)
|
||||||
|
}),
|
||||||
Err(ZxError::ACCESS_DENIED)
|
Err(ZxError::ACCESS_DENIED)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,3 +27,11 @@ pub fn check_aligned(x: usize, align: usize) -> bool {
|
||||||
pub fn pages(size: usize) -> usize {
|
pub fn pages(size: usize) -> usize {
|
||||||
(size + PAGE_SIZE - 1) / PAGE_SIZE
|
(size + PAGE_SIZE - 1) / PAGE_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn roundup_pages(size: usize) -> usize {
|
||||||
|
if page_aligned(size) {
|
||||||
|
size
|
||||||
|
} else {
|
||||||
|
pages(size) * PAGE_SIZE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use {super::*, crate::object::*, kernel_hal::PageTable};
|
use {super::*, crate::object::*, alloc::sync::Arc, kernel_hal::PageTable};
|
||||||
|
|
||||||
mod paged;
|
mod paged;
|
||||||
mod physical;
|
mod physical;
|
||||||
|
@ -44,6 +44,11 @@ pub trait VMObject: KernelObject {
|
||||||
|
|
||||||
/// Decommit allocated physical memory.
|
/// Decommit allocated physical memory.
|
||||||
fn decommit(&self, offset: usize, len: usize);
|
fn decommit(&self, offset: usize, len: usize);
|
||||||
|
|
||||||
|
/// Create a child vmo
|
||||||
|
fn create_child(&self, offset: usize, len: usize) -> Arc<dyn VMObject>;
|
||||||
|
|
||||||
|
fn create_clone(&self, offset: usize, len: usize) -> Arc<dyn KernelObject>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -16,6 +16,8 @@ pub struct VMObjectPaged {
|
||||||
|
|
||||||
/// The mutable part of `VMObjectPaged`.
|
/// The mutable part of `VMObjectPaged`.
|
||||||
struct VMObjectPagedInner {
|
struct VMObjectPagedInner {
|
||||||
|
parent: Option<Arc<VMObjectPaged>>,
|
||||||
|
parent_offset: usize,
|
||||||
frames: Vec<Option<PhysFrame>>,
|
frames: Vec<Option<PhysFrame>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,83 +31,14 @@ impl VMObjectPaged {
|
||||||
|
|
||||||
Arc::new(VMObjectPaged {
|
Arc::new(VMObjectPaged {
|
||||||
base: KObjectBase::default(),
|
base: KObjectBase::default(),
|
||||||
inner: Mutex::new(VMObjectPagedInner { frames }),
|
inner: Mutex::new(VMObjectPagedInner {
|
||||||
|
parent: None,
|
||||||
|
parent_offset: 0usize,
|
||||||
|
frames,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl VMObject for VMObjectPaged {
|
|
||||||
fn read(&self, offset: usize, buf: &mut [u8]) {
|
|
||||||
self.inner
|
|
||||||
.lock()
|
|
||||||
.for_each_page(offset, buf.len(), |paddr, buf_range| {
|
|
||||||
kernel_hal::pmem_read(paddr, &mut buf[buf_range]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write(&self, offset: usize, buf: &[u8]) {
|
|
||||||
self.inner
|
|
||||||
.lock()
|
|
||||||
.for_each_page(offset, buf.len(), |paddr, buf_range| {
|
|
||||||
kernel_hal::pmem_write(paddr, &buf[buf_range]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
|
||||||
self.inner.lock().frames.len() * PAGE_SIZE
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_len(&self, len: usize) {
|
|
||||||
// FIXME parent and children? len < old_len?
|
|
||||||
let old_len = self.inner.lock().frames.len();
|
|
||||||
warn!("old_len: {:#x}, len: {:#x}", old_len, len);
|
|
||||||
if old_len < len {
|
|
||||||
self.inner.lock().frames.resize_with(len, Default::default);
|
|
||||||
self.commit(old_len, len - old_len);
|
|
||||||
} else {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn map_to(
|
|
||||||
&self,
|
|
||||||
page_table: &mut PageTable,
|
|
||||||
vaddr: usize,
|
|
||||||
offset: usize,
|
|
||||||
len: usize,
|
|
||||||
flags: MMUFlags,
|
|
||||||
) {
|
|
||||||
let start_page = offset / PAGE_SIZE;
|
|
||||||
let pages = len / PAGE_SIZE;
|
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
for i in 0..pages {
|
|
||||||
let frame = inner.commit(start_page + i);
|
|
||||||
page_table
|
|
||||||
.map(vaddr + i * PAGE_SIZE, frame.addr(), flags)
|
|
||||||
.expect("failed to map");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn commit(&self, offset: usize, len: usize) {
|
|
||||||
let start_page = offset / PAGE_SIZE;
|
|
||||||
let pages = len / PAGE_SIZE;
|
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
for i in 0..pages {
|
|
||||||
inner.commit(start_page + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decommit(&self, offset: usize, len: usize) {
|
|
||||||
let start_page = offset / PAGE_SIZE;
|
|
||||||
let pages = len / PAGE_SIZE;
|
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
for i in 0..pages {
|
|
||||||
inner.decommit(start_page + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VMObjectPagedInner {
|
|
||||||
/// Helper function to split range into sub-ranges within pages.
|
/// Helper function to split range into sub-ranges within pages.
|
||||||
///
|
///
|
||||||
/// All covered pages will be committed implicitly.
|
/// All covered pages will be committed implicitly.
|
||||||
|
@ -129,9 +62,10 @@ impl VMObjectPagedInner {
|
||||||
/// * `paddr`: the start physical address of the in-page range.
|
/// * `paddr`: the start physical address of the in-page range.
|
||||||
/// * `buf_range`: the range in view of the input buffer.
|
/// * `buf_range`: the range in view of the input buffer.
|
||||||
fn for_each_page(
|
fn for_each_page(
|
||||||
&mut self,
|
&self,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
buf_len: usize,
|
buf_len: usize,
|
||||||
|
for_write: bool,
|
||||||
mut f: impl FnMut(PhysAddr, Range<usize>),
|
mut f: impl FnMut(PhysAddr, Range<usize>),
|
||||||
) {
|
) {
|
||||||
let iter = BlockIter {
|
let iter = BlockIter {
|
||||||
|
@ -140,13 +74,155 @@ impl VMObjectPagedInner {
|
||||||
block_size_log2: 12,
|
block_size_log2: 12,
|
||||||
};
|
};
|
||||||
for block in iter {
|
for block in iter {
|
||||||
self.commit(block.block);
|
let paddr = self.inner.lock().get_page(block.block, for_write);
|
||||||
let paddr = self.frames[block.block].as_ref().unwrap().addr();
|
|
||||||
let buf_range = block.origin_begin() - offset..block.origin_end() - offset;
|
let buf_range = block.origin_begin() - offset..block.origin_end() - offset;
|
||||||
f(paddr + block.begin, buf_range);
|
f(paddr + block.begin, buf_range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_page(&self, page_idx: usize, for_write: bool) -> PhysAddr {
|
||||||
|
self.inner.lock().get_page(page_idx, for_write)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VMObject for VMObjectPaged {
|
||||||
|
fn read(&self, offset: usize, buf: &mut [u8]) {
|
||||||
|
self.for_each_page(offset, buf.len(), false, |paddr, buf_range| {
|
||||||
|
kernel_hal::pmem_read(paddr, &mut buf[buf_range]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, offset: usize, buf: &[u8]) {
|
||||||
|
self.for_each_page(offset, buf.len(), true, |paddr, buf_range| {
|
||||||
|
kernel_hal::pmem_write(paddr, &buf[buf_range]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.inner.lock().frames.len() * PAGE_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_len(&self, len: usize) {
|
||||||
|
assert!(page_aligned(len));
|
||||||
|
// FIXME parent and children? len < old_len?
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
let old_pages = inner.frames.len();
|
||||||
|
let new_pages = len / PAGE_SIZE;
|
||||||
|
warn!("old_pages: {:#x}, new_pages: {:#x}", old_pages, new_pages);
|
||||||
|
if old_pages < new_pages {
|
||||||
|
inner.frames.resize_with(len, Default::default);
|
||||||
|
(old_pages..new_pages).for_each(|idx| {
|
||||||
|
inner.commit(idx);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_to(
|
||||||
|
&self,
|
||||||
|
page_table: &mut PageTable,
|
||||||
|
vaddr: usize,
|
||||||
|
offset: usize,
|
||||||
|
len: usize,
|
||||||
|
flags: MMUFlags,
|
||||||
|
) {
|
||||||
|
let start_page = offset / PAGE_SIZE;
|
||||||
|
let pages = len / PAGE_SIZE;
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
for i in 0..pages {
|
||||||
|
let paddr = inner.get_page(start_page + i, true);
|
||||||
|
page_table
|
||||||
|
.map(vaddr + i * PAGE_SIZE, paddr, flags)
|
||||||
|
.expect("failed to map");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn commit(&self, offset: usize, len: usize) {
|
||||||
|
let start_page = offset / PAGE_SIZE;
|
||||||
|
let pages = len / PAGE_SIZE;
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
warn!("start_page: {:#x}, pages: {:#x}", start_page, pages);
|
||||||
|
for i in 0..pages {
|
||||||
|
inner.commit(start_page + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decommit(&self, offset: usize, len: usize) {
|
||||||
|
let start_page = offset / PAGE_SIZE;
|
||||||
|
let pages = len / PAGE_SIZE;
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
for i in 0..pages {
|
||||||
|
inner.decommit(start_page + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_child(&self, offset: usize, len: usize) -> Arc<dyn VMObject> {
|
||||||
|
assert!(page_aligned(offset));
|
||||||
|
assert!(page_aligned(len));
|
||||||
|
let mut frames = Vec::new();
|
||||||
|
let pages = self.len() / PAGE_SIZE;
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
frames.append(&mut inner.frames);
|
||||||
|
let old_parent = inner.parent.take();
|
||||||
|
|
||||||
|
// construct hidden_vmo as shared parent
|
||||||
|
let hidden_vmo = Arc::new(VMObjectPaged {
|
||||||
|
base: KObjectBase::default(),
|
||||||
|
inner: Mutex::new(VMObjectPagedInner {
|
||||||
|
parent: old_parent,
|
||||||
|
parent_offset: 0usize,
|
||||||
|
frames,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
// change current vmo's parent
|
||||||
|
inner.parent = Some(hidden_vmo.clone());
|
||||||
|
inner.frames.resize_with(pages, Default::default);
|
||||||
|
|
||||||
|
// create hidden_vmo's another child as result
|
||||||
|
let mut child_frames = Vec::new();
|
||||||
|
child_frames.resize_with(len / PAGE_SIZE, Default::default);
|
||||||
|
Arc::new(VMObjectPaged {
|
||||||
|
base: KObjectBase::default(),
|
||||||
|
inner: Mutex::new(VMObjectPagedInner {
|
||||||
|
parent: Some(hidden_vmo),
|
||||||
|
parent_offset: offset,
|
||||||
|
frames: child_frames,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_clone(&self, offset: usize, len: usize) -> Arc<dyn KernelObject> {
|
||||||
|
assert!(page_aligned(offset));
|
||||||
|
assert!(page_aligned(len));
|
||||||
|
let frames_offset = pages(offset);
|
||||||
|
let clone_size = pages(len);
|
||||||
|
let mut frames = Vec::new();
|
||||||
|
frames.resize_with(clone_size, || {
|
||||||
|
Some(PhysFrame::alloc().expect("faild to alloc frame"))
|
||||||
|
});
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
for i in 0..clone_size {
|
||||||
|
if inner.frames[frames_offset + i].is_some() {
|
||||||
|
kernel_hal::frame_copy(
|
||||||
|
inner.frames[frames_offset + i].as_ref().unwrap().addr(),
|
||||||
|
frames[i].as_ref().unwrap().addr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Arc::new(VMObjectPaged {
|
||||||
|
base: KObjectBase::default(),
|
||||||
|
inner: Mutex::new(VMObjectPagedInner {
|
||||||
|
parent: None,
|
||||||
|
parent_offset: offset,
|
||||||
|
frames,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VMObjectPagedInner {
|
||||||
fn commit(&mut self, page_idx: usize) -> &PhysFrame {
|
fn commit(&mut self, page_idx: usize) -> &PhysFrame {
|
||||||
self.frames[page_idx]
|
self.frames[page_idx]
|
||||||
.get_or_insert_with(|| PhysFrame::alloc().expect("failed to alloc frame"))
|
.get_or_insert_with(|| PhysFrame::alloc().expect("failed to alloc frame"))
|
||||||
|
@ -155,6 +231,42 @@ impl VMObjectPagedInner {
|
||||||
fn decommit(&mut self, page_idx: usize) {
|
fn decommit(&mut self, page_idx: usize) {
|
||||||
self.frames[page_idx] = None;
|
self.frames[page_idx] = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_page(&mut self, page_idx: usize, for_write: bool) -> PhysAddr {
|
||||||
|
if self.frames[page_idx].is_some() {
|
||||||
|
self.frames[page_idx].as_ref().unwrap().addr()
|
||||||
|
} else {
|
||||||
|
let parent_idx_offset = self.parent_offset / PAGE_SIZE;
|
||||||
|
//info!(
|
||||||
|
//"page_idx {:#x}, parent_offset {:#x}",
|
||||||
|
//page_idx, parent_idx_offset
|
||||||
|
//);
|
||||||
|
if for_write {
|
||||||
|
let target_addr = self.commit(page_idx).addr();
|
||||||
|
if self.parent.is_some() {
|
||||||
|
// TODO copy a page from parent if need write
|
||||||
|
//warn!("doing copy");
|
||||||
|
kernel_hal::frame_copy(
|
||||||
|
self.parent
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.get_page(parent_idx_offset + page_idx, false),
|
||||||
|
target_addr,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
target_addr
|
||||||
|
} else {
|
||||||
|
if self.parent.is_some() {
|
||||||
|
self.parent
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.get_page(parent_idx_offset + page_idx, false)
|
||||||
|
} else {
|
||||||
|
self.commit(page_idx).addr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -166,4 +278,21 @@ mod tests {
|
||||||
let vmo = VMObjectPaged::new(2);
|
let vmo = VMObjectPaged::new(2);
|
||||||
super::super::tests::read_write(&*vmo);
|
super::super::tests::read_write(&*vmo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_child() {
|
||||||
|
let vmo = VMObjectPaged::new(10);
|
||||||
|
vmo.write(0, &[1, 2, 3, 4]);
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
vmo.read(0, &mut buf);
|
||||||
|
assert_eq!(&buf, &[1, 2, 3, 4]);
|
||||||
|
let child_vmo = vmo.create_child(0, 4 * 4096);
|
||||||
|
child_vmo.read(0, &mut buf);
|
||||||
|
assert_eq!(&buf, &[1, 2, 3, 4]);
|
||||||
|
child_vmo.write(0, &[6, 7, 8, 9]);
|
||||||
|
vmo.read(0, &mut buf);
|
||||||
|
assert_eq!(&buf, &[1, 2, 3, 4]);
|
||||||
|
child_vmo.read(0, &mut buf);
|
||||||
|
assert_eq!(&buf, &[6, 7, 8, 9]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,14 @@ impl VMObject for VMObjectPhysical {
|
||||||
fn decommit(&self, _offset: usize, _len: usize) {
|
fn decommit(&self, _offset: usize, _len: usize) {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_child(&self, _offset: usize, _len: usize) -> Arc<dyn VMObject> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_clone(&self, _offset: usize, _len: usize) -> Arc<dyn KernelObject> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -94,8 +94,8 @@ impl Syscall<'_> {
|
||||||
&self,
|
&self,
|
||||||
handle_value: HandleValue,
|
handle_value: HandleValue,
|
||||||
options: u32,
|
options: u32,
|
||||||
offset: u64,
|
offset: usize,
|
||||||
size: u64,
|
size: usize,
|
||||||
mut out: UserOutPtr<HandleValue>,
|
mut out: UserOutPtr<HandleValue>,
|
||||||
) -> ZxResult<usize> {
|
) -> ZxResult<usize> {
|
||||||
let options = VmoCloneFlags::from_bits(options).ok_or(ZxError::INVALID_ARGS)?;
|
let options = VmoCloneFlags::from_bits(options).ok_or(ZxError::INVALID_ARGS)?;
|
||||||
|
@ -108,16 +108,14 @@ impl Syscall<'_> {
|
||||||
}
|
}
|
||||||
let proc = self.thread.proc();
|
let proc = self.thread.proc();
|
||||||
let vmo = proc.get_vmo_with_rights(handle_value, Rights::READ)?;
|
let vmo = proc.get_vmo_with_rights(handle_value, Rights::READ)?;
|
||||||
// TODO: optimize
|
let child_size = roundup_pages(size);
|
||||||
let mut buffer = vec![0u8; size as usize];
|
info!("size of child vmo: {:#x}", child_size);
|
||||||
vmo.read(offset as usize, &mut buffer);
|
let child_vmo = vmo.create_clone(offset as usize, child_size);
|
||||||
let child_vmo = VMObjectPaged::new(pages(size as usize));
|
|
||||||
child_vmo.write(0, &buffer);
|
|
||||||
out.write(proc.add_handle(Handle::new(child_vmo, Rights::DEFAULT_VMO)))?;
|
out.write(proc.add_handle(Handle::new(child_vmo, Rights::DEFAULT_VMO)))?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_vmo_set_size(&self, handle_value: HandleValue, size: u64) -> ZxResult<usize> {
|
pub fn sys_vmo_set_size(&self, handle_value: HandleValue, size: usize) -> ZxResult<usize> {
|
||||||
let vmo = self
|
let vmo = self
|
||||||
.thread
|
.thread
|
||||||
.proc()
|
.proc()
|
||||||
|
@ -128,7 +126,7 @@ impl Syscall<'_> {
|
||||||
size,
|
size,
|
||||||
vmo.len()
|
vmo.len()
|
||||||
);
|
);
|
||||||
vmo.set_len(pages(size as usize));
|
vmo.set_len(size);
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue