From d0994e5f5d009701e79d827761cfab86492b94cd Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Sun, 10 May 2020 14:19:08 +0800 Subject: [PATCH 1/5] simplify code of DDK --- kernel-hal/src/consts.rs | 3 - kernel-hal/src/dummy.rs | 4 -- kernel-hal/src/lib.rs | 2 - zircon-object/src/dev/bti.rs | 111 +++++++++++++----------------- zircon-object/src/dev/iommu.rs | 27 +++----- zircon-object/src/dev/pmt.rs | 72 +++++++------------ zircon-object/src/vm/mod.rs | 7 +- zircon-object/src/vm/vmo/paged.rs | 2 +- zircon-syscall/src/ddk.rs | 101 ++++++++++++++------------- zircon-syscall/src/object.rs | 5 +- zircon-syscall/src/vmo.rs | 2 +- 11 files changed, 141 insertions(+), 195 deletions(-) delete mode 100644 kernel-hal/src/consts.rs diff --git a/kernel-hal/src/consts.rs b/kernel-hal/src/consts.rs deleted file mode 100644 index 3c189801f..000000000 --- a/kernel-hal/src/consts.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub const KERNEL_ASPACE_BASE: u64 = 0xffff_0000_0000_0000; -pub const PHYSMAP_BASE: u64 = KERNEL_ASPACE_BASE; -pub const PHYSMAP_BASE_PHYS: u64 = 0; diff --git a/kernel-hal/src/dummy.rs b/kernel-hal/src/dummy.rs index b2ba4ed76..6007f65c9 100644 --- a/kernel-hal/src/dummy.rs +++ b/kernel-hal/src/dummy.rs @@ -171,10 +171,6 @@ impl PhysFrame { pub fn zero_frame_addr() -> PhysAddr { unimplemented!() } - - pub fn wrap(addr: PhysAddr) -> Self { - PhysFrame { paddr: addr } - } } impl Drop for PhysFrame { diff --git a/kernel-hal/src/lib.rs b/kernel-hal/src/lib.rs index 87e50250e..998a1cb5f 100644 --- a/kernel-hal/src/lib.rs +++ b/kernel-hal/src/lib.rs @@ -39,13 +39,11 @@ pub mod defs { pub const PAGE_SIZE: usize = 0x1000; } -pub mod consts; mod dummy; mod future; pub mod user; pub mod vdso; -pub use self::consts::*; pub use self::defs::*; pub use self::dummy::*; pub use self::future::*; diff --git a/zircon-object/src/dev/bti.rs b/zircon-object/src/dev/bti.rs index 1e37e9fb1..922a2da0b 100644 --- a/zircon-object/src/dev/bti.rs +++ b/zircon-object/src/dev/bti.rs @@ -2,119 +2,102 @@ use { super::*, crate::object::*, crate::vm::*, - alloc::{ - collections::BTreeMap, - sync::{Arc, Weak}, - vec::Vec, - }, + alloc::{sync::Arc, vec::Vec}, dev::Iommu, spin::Mutex, }; -// BusTransactionInitiator -#[allow(dead_code)] -pub struct Bti { +/// Bus Transaction Initiator. +/// +/// Bus Transaction Initiators (BTIs) represent the bus mastering/DMA capability +/// of a device, and can be used for granting a device access to memory. +pub struct BusTransactionInitiator { base: KObjectBase, iommu: Arc, + #[allow(dead_code)] bti_id: u64, inner: Mutex, } +#[derive(Default)] struct BtiInner { - pmts: BTreeMap>, - self_ref: Weak, + /// A BTI manages a list of quarantined PMTs. + pmts: Vec>, } -impl_kobject!(Bti); +impl_kobject!(BusTransactionInitiator); -impl Bti { +impl BusTransactionInitiator { + /// Create a new bus transaction initiator. pub fn create(iommu: Arc, bti_id: u64) -> Arc { - let bti = Arc::new(Bti { + Arc::new(BusTransactionInitiator { base: KObjectBase::new(), iommu, bti_id, - inner: Mutex::new(BtiInner { - pmts: Default::default(), - self_ref: Default::default(), - }), - }); - bti.inner.lock().self_ref = Arc::downgrade(&bti); - bti + inner: Mutex::new(BtiInner::default()), + }) } - pub fn get_info(&self) -> ZxInfoBti { - ZxInfoBti { - minimum_contiguity: self.minimum_contiguity() as u64, - aspace_size: self.aspace_size() as u64, - pmo_count: self.get_pmo_count() as u64, - quarantine_count: self.get_quarantine_count() as u64, + /// Get information of BTI. + pub fn get_info(&self) -> BtiInfo { + BtiInfo { + minimum_contiguity: self.iommu.minimum_contiguity() as u64, + aspace_size: self.iommu.aspace_size() as u64, + pmo_count: self.pmo_count() as u64, + quarantine_count: self.quarantine_count() as u64, } } + /// Pin memory and grant access to it to the BTI. pub fn pin( - &self, + self: &Arc, vmo: Arc, offset: usize, size: usize, perms: IommuPerms, - ) -> ZxResult> { + ) -> ZxResult> { if size == 0 { return Err(ZxError::INVALID_ARGS); } - let pmt = Pmt::create(self.inner.lock().self_ref.clone(), vmo, perms, offset, size)?; - self.inner.lock().pmts.insert(pmt.id(), pmt.clone()); + let pmt = PinnedMemoryToken::create(self, vmo, perms, offset, size)?; + self.inner.lock().pmts.push(pmt.clone()); Ok(pmt) } - pub fn minimum_contiguity(&self) -> usize { - self.iommu.minimum_contiguity() + /// Releases all quarantined PMTs. + pub fn release_quarantine(&self) { + let mut inner = self.inner.lock(); + // remove no handle, the only Arc is from self.pmts + inner.pmts.retain(|pmt| Arc::strong_count(pmt) > 1); } - pub fn aspace_size(&self) -> usize { - self.iommu.aspace_size() + /// Release a PMT by KoID. + pub(super) fn release_pmt(&self, id: KoID) { + let mut inner = self.inner.lock(); + inner.pmts.retain(|pmt| pmt.id() != id); } - pub fn get_iommu(&self) -> Arc { + pub(super) fn iommu(&self) -> Arc { self.iommu.clone() } - pub fn release_pmt(&self, id: KoID) { - self.inner.lock().pmts.remove(&id).unwrap(); - } - - pub fn release_quarantine(&self) { - let mut inner = self.inner.lock(); - let mut to_release: Vec = Vec::new(); - for (id, pmt) in inner.pmts.iter() { - // no handle, the only arc is from self.pmts - if Arc::strong_count(&pmt) == 1 { - to_release.push(*id); - } - } - for id in to_release { - inner.pmts.remove(&id).unwrap(); - } - } - - pub fn get_pmo_count(&self) -> usize { + fn pmo_count(&self) -> usize { self.inner.lock().pmts.len() } - pub fn get_quarantine_count(&self) -> usize { - let mut cnt = 0; - for (_id, pmt) in self.inner.lock().pmts.iter() { - if Arc::strong_count(&pmt) == 1 { - // no handle, the only arc is from self.pmts - cnt += 1; - } - } - cnt + fn quarantine_count(&self) -> usize { + self.inner + .lock() + .pmts + .iter() + .filter(|pmt| Arc::strong_count(pmt) == 1) + .count() } } #[repr(C)] #[derive(Default)] -pub struct ZxInfoBti { +pub struct BtiInfo { minimum_contiguity: u64, aspace_size: u64, pmo_count: u64, diff --git a/zircon-object/src/dev/iommu.rs b/zircon-object/src/dev/iommu.rs index 56b36633d..9aa26dab7 100644 --- a/zircon-object/src/dev/iommu.rs +++ b/zircon-object/src/dev/iommu.rs @@ -1,26 +1,17 @@ -use { - crate::object::*, - crate::vm::*, - alloc::{sync::Arc, vec::Vec}, - bitflags::bitflags, -}; - -// Iommu refers to DummyIommu in zircon -// A dummy implementation, do not take it serious +use {crate::object::*, crate::vm::*, alloc::sync::Arc, bitflags::bitflags}; +/// Iommu refers to DummyIommu in zircon. +/// +/// A dummy implementation, do not take it serious. pub struct Iommu { base: KObjectBase, } -const IOMMU_TYPE_DUMMY: u32 = 0; - impl_kobject!(Iommu); impl Iommu { - pub fn create(type_: u32, _desc: Vec, _desc_size: usize) -> Arc { - if type_ != IOMMU_TYPE_DUMMY { - panic!("IOMMU {} is not implemented", type_); - } + /// Create a new `IOMMU`. + pub fn create() -> Arc { Arc::new(Iommu { base: KObjectBase::new(), }) @@ -35,7 +26,7 @@ impl Iommu { } pub fn aspace_size(&self) -> usize { - -1 as isize as usize + usize::MAX } pub fn map( @@ -48,7 +39,7 @@ impl Iommu { if perms == IommuPerms::empty() { return Err(ZxError::INVALID_ARGS); } - if !in_range(offset, size, vmo.len()) { + if offset + size > vmo.len() { return Err(ZxError::INVALID_ARGS); } let p_addr = vmo.commit_page(offset, MMUFlags::empty())?; @@ -69,7 +60,7 @@ impl Iommu { if perms == IommuPerms::empty() { return Err(ZxError::INVALID_ARGS); } - if !in_range(offset, size, vmo.len()) { + if offset + size > vmo.len() { return Err(ZxError::INVALID_ARGS); } let p_addr = vmo.commit_page(offset, MMUFlags::empty())?; diff --git a/zircon-object/src/dev/pmt.rs b/zircon-object/src/dev/pmt.rs index d1175372a..8180b20c4 100644 --- a/zircon-object/src/dev/pmt.rs +++ b/zircon-object/src/dev/pmt.rs @@ -2,69 +2,61 @@ use { super::*, crate::object::*, crate::vm::*, - crate::vm::{ceil, DevVAddr}, alloc::{ sync::{Arc, Weak}, + vec, vec::Vec, }, - spin::Mutex, }; -// PinnedMemoryToken -pub struct Pmt { +/// Pinned Memory Token. +/// +/// It will pin memory on construction and unpin on drop. +pub struct PinnedMemoryToken { base: KObjectBase, - bti: Weak, + bti: Weak, vmo: Arc, offset: usize, size: usize, mapped_addrs: Vec, - inner: Mutex, } -struct PmtInner { - unpinned: bool, -} - -impl_kobject!(Pmt); +impl_kobject!(PinnedMemoryToken); -impl Drop for Pmt { +impl Drop for PinnedMemoryToken { fn drop(&mut self) { - if !self.inner.lock().unpinned { - self.unpin().unwrap(); + if self.vmo.is_paged() { + self.vmo.unpin(self.offset, self.size).unwrap(); } } } -impl Pmt { - pub fn create( - bti: Weak, +impl PinnedMemoryToken { + /// Create a `PinnedMemoryToken` by `BusTransactionInitiator`. + pub(crate) fn create( + bti: &Arc, vmo: Arc, perms: IommuPerms, offset: usize, size: usize, ) -> ZxResult> { - let iommu = bti.upgrade().unwrap().get_iommu(); - if vmo.is_paged() { vmo.commit(offset, size)?; vmo.pin(offset, size)?; } - - let mapped_addrs = Pmt::map_into_iommu(iommu, vmo.clone(), offset, size, perms)?; - - Ok(Arc::new(Pmt { + let mapped_addrs = Self::map_into_iommu(&bti.iommu(), vmo.clone(), offset, size, perms)?; + Ok(Arc::new(PinnedMemoryToken { base: KObjectBase::new(), - bti, + bti: Arc::downgrade(bti), vmo, offset, size, mapped_addrs, - inner: Mutex::new(PmtInner { unpinned: false }), })) } - pub fn map_into_iommu( - iommu: Arc, + fn map_into_iommu( + iommu: &Arc, vmo: Arc, offset: usize, size: usize, @@ -72,10 +64,7 @@ impl Pmt { ) -> ZxResult> { if vmo.is_contiguous() { let (vaddr, _mapped_len) = iommu.map_contiguous(vmo, offset, size, perms)?; - // vec! is better, but compile error occurs. - let mut mapped_addrs: Vec = Vec::new(); - mapped_addrs.push(vaddr); - Ok(mapped_addrs) + Ok(vec![vaddr]) } else { assert_eq!(size % iommu.minimum_contiguity(), 0); let mut mapped_addrs: Vec = Vec::new(); @@ -101,7 +90,7 @@ impl Pmt { compress_results: bool, contiguous: bool, ) -> ZxResult> { - let iommu = self.bti.upgrade().unwrap().get_iommu(); + let iommu = self.bti.upgrade().unwrap().iommu(); if compress_results { if self.vmo.is_contiguous() { let num_addrs = ceil(self.size, iommu.minimum_contiguity()); @@ -115,10 +104,7 @@ impl Pmt { if !self.vmo.is_contiguous() { Err(ZxError::INVALID_ARGS) } else { - // vec! is better, but compile error occurs. - let mut encoded_addrs: Vec = Vec::new(); - encoded_addrs.push(self.mapped_addrs[0]); - Ok(encoded_addrs) + Ok(vec![self.mapped_addrs[0]]) } } else { let min_contig = if self.vmo.is_contiguous() { @@ -139,20 +125,10 @@ impl Pmt { } } - pub fn unpin_and_remove(&self) -> ZxResult { - self.unpin()?; + /// Unpin pages and revoke device access to them. + pub fn unpin(&self) { if let Some(bti) = self.bti.upgrade() { bti.release_pmt(self.base.id); } - Ok(()) - } - - fn unpin(&self) -> ZxResult { - let mut inner = self.inner.lock(); - if !inner.unpinned && self.vmo.is_paged() { - self.vmo.unpin(self.offset, self.size)?; - } - inner.unpinned = true; - Ok(()) } } diff --git a/zircon-object/src/vm/mod.rs b/zircon-object/src/vm/mod.rs index b072439d8..c506c770b 100644 --- a/zircon-object/src/vm/mod.rs +++ b/zircon-object/src/vm/mod.rs @@ -12,7 +12,7 @@ pub type PhysAddr = usize; /// Virtual Address pub type VirtAddr = usize; -// Device Address +/// Device Address pub type DevVAddr = usize; /// Size of a page @@ -49,11 +49,6 @@ pub fn round_down_pages(size: usize) -> usize { size / PAGE_SIZE * PAGE_SIZE } -// [offset, offset + size) is subset of [0, len) -pub fn in_range(offset: usize, size: usize, len: usize) -> bool { - offset <= len && size <= len - offset -} - #[cfg(test)] mod test { use super::*; diff --git a/zircon-object/src/vm/vmo/paged.rs b/zircon-object/src/vm/vmo/paged.rs index d51eb4771..a04c98ce1 100644 --- a/zircon-object/src/vm/vmo/paged.rs +++ b/zircon-object/src/vm/vmo/paged.rs @@ -531,7 +531,7 @@ impl VMObjectTrait for VMObjectPaged { fn unpin(&self, offset: usize, len: usize) -> ZxResult { { let inner = self.inner.lock(); - if !in_range(offset, len, inner.size) { + if offset + len > inner.size { return Err(ZxError::OUT_OF_RANGE); } if len == 0 { diff --git a/zircon-syscall/src/ddk.rs b/zircon-syscall/src/ddk.rs index 7e9b3b180..f31c670df 100644 --- a/zircon-syscall/src/ddk.rs +++ b/zircon-syscall/src/ddk.rs @@ -28,8 +28,11 @@ impl Syscall<'_> { if desc_size != IOMMU_DESC_SIZE { return Err(ZxError::INVALID_ARGS); } - let copied_desc = desc.read_array(desc_size)?; - let iommu = Iommu::create(type_, copied_desc, desc_size); + if type_ != IOMMU_TYPE_DUMMY { + unimplemented!("IOMMU {} is not implemented", type_); + } + let _copied_desc = desc.read_array(desc_size)?; + let iommu = Iommu::create(); let handle = proc.add_handle(Handle::new(iommu, Rights::DEFAULT_CHANNEL)); info!("iommu handle value {:#x}", handle); out.write(handle)?; @@ -55,7 +58,7 @@ impl Syscall<'_> { if !iommu.is_valid_bus_txn_id() { return Err(ZxError::INVALID_ARGS); } - let bti = Bti::create(iommu, bti_id); + let bti = BusTransactionInitiator::create(iommu, bti_id); let handle = proc.add_handle(Handle::new(bti, Rights::DEFAULT_BTI)); out.write(handle)?; Ok(()) @@ -73,55 +76,24 @@ impl Syscall<'_> { addrs_count: usize, mut out: UserOutPtr, ) -> ZxResult { + let options = BtiOptions::from_bits_truncate(options); info!( - "bti.pin: bti={:#x}, options={:?}, vmo={:#x}, offset={:#x}, size={:#x}, addrs: {:#x?}, addrs_count: {:#x}", + "bti.pin: bti={:#x}, options={:?}, vmo={:#x}, offset={:#x}, size={:#x}, addrs={:#x?}, addrs_count={:#x}", bti, options, vmo, offset, size, addrs, addrs_count ); let proc = self.thread.proc(); - let bti = proc.get_object_with_rights::(bti, Rights::MAP)?; + let bti = proc.get_object_with_rights::(bti, Rights::MAP)?; if !page_aligned(offset) || !page_aligned(size) { return Err(ZxError::INVALID_ARGS); } - let (vmo, rights) = proc.get_object_and_rights::(vmo)?; - if !rights.contains(Rights::MAP) { - return Err(ZxError::ACCESS_DENIED); - } - - let mut iommu_perms = IommuPerms::empty(); - let options = BtiOptions::from_bits_truncate(options); - if options.contains(BtiOptions::PERM_READ) { - if !rights.contains(Rights::READ) { - return Err(ZxError::ACCESS_DENIED); - } - iommu_perms.insert(IommuPerms::PERM_READ) - } - - if options.contains(BtiOptions::PERM_WRITE) { - if !rights.contains(Rights::WRITE) { - return Err(ZxError::ACCESS_DENIED); - } - iommu_perms.insert(IommuPerms::PERM_WRITE); - } - - if options.contains(BtiOptions::PERM_EXECUTE) { - // NOTE: Check Rights::READ instead of Rights::EXECUTE, - // because Rights::EXECUTE applies to the execution permission of the host CPU, - // but ZX_BTI_PERM_EXECUTE applies to transactions initiated by the bus device. - if !rights.contains(Rights::READ) { - return Err(ZxError::ACCESS_DENIED); - } - iommu_perms.insert(IommuPerms::PERM_EXECUTE); - } - if options.contains(BtiOptions::CONTIGUOUS) && options.contains(BtiOptions::COMPRESS) { - return Err(ZxError::INVALID_ARGS); - } - if options.contains(BtiOptions::CONTIGUOUS) && !vmo.is_contiguous() { - return Err(ZxError::INVALID_ARGS); - } + let vmo = proc.get_object_with_rights::(vmo, options.to_vmo_rights())?; let compress_results = options.contains(BtiOptions::COMPRESS); let contiguous = options.contains(BtiOptions::CONTIGUOUS); - let pmt = bti.pin(vmo, offset, size, iommu_perms)?; - let encoded_addrs = pmt.as_ref().encode_addrs(compress_results, contiguous)?; + if contiguous && (compress_results || !vmo.is_contiguous()) { + return Err(ZxError::INVALID_ARGS); + } + let pmt = bti.pin(vmo, offset, size, options.to_iommu_perms())?; + let encoded_addrs = pmt.encode_addrs(compress_results, contiguous)?; if encoded_addrs.len() != addrs_count { warn!( "bti.pin addrs_count = {}, but encoded_addrs.len = {}", @@ -139,17 +111,19 @@ impl Syscall<'_> { pub fn sys_pmt_unpin(&self, pmt: HandleValue) -> ZxResult { info!("pmt.unpin: pmt={:#x}", pmt); let proc = self.thread.proc(); - let pmt = proc.remove_object::(pmt)?; - pmt.as_ref().unpin_and_remove() + let pmt = proc.remove_object::(pmt)?; + pmt.unpin(); + Ok(()) } pub fn sys_bti_release_quarantine(&self, bti: HandleValue) -> ZxResult { info!("bti.release_quarantine: bti = {:#x}", bti); let proc = self.thread.proc(); - let bti = proc.get_object_with_rights::(bti, Rights::WRITE)?; + let bti = proc.get_object_with_rights::(bti, Rights::WRITE)?; bti.release_quarantine(); Ok(()) } + pub fn sys_pc_firmware_tables( &self, resource: HandleValue, @@ -167,6 +141,7 @@ impl Syscall<'_> { } } +const IOMMU_TYPE_DUMMY: u32 = 0; const IOMMU_MAX_DESC_LEN: usize = 4096; const IOMMU_DESC_SIZE: usize = 1; @@ -180,3 +155,37 @@ bitflags! { const CONTIGUOUS = 1 << 4; } } + +impl BtiOptions { + /// Get desired rights of VMO handle. + fn to_vmo_rights(self) -> Rights { + let mut rights = Rights::MAP; + if self.contains(BtiOptions::PERM_READ) { + rights.insert(Rights::READ); + } + if self.contains(BtiOptions::PERM_WRITE) { + rights.insert(Rights::WRITE); + } + if self.contains(BtiOptions::PERM_EXECUTE) { + // NOTE: Check Rights::READ instead of Rights::EXECUTE, + // because Rights::EXECUTE applies to the execution permission of the host CPU, + // but ZX_BTI_PERM_EXECUTE applies to transactions initiated by the bus device. + rights.insert(Rights::READ); + } + rights + } + + fn to_iommu_perms(self) -> IommuPerms { + let mut perms = IommuPerms::empty(); + if self.contains(BtiOptions::PERM_READ) { + perms.insert(IommuPerms::PERM_READ) + } + if self.contains(BtiOptions::PERM_WRITE) { + perms.insert(IommuPerms::PERM_WRITE); + } + if self.contains(BtiOptions::PERM_EXECUTE) { + perms.insert(IommuPerms::PERM_EXECUTE); + } + perms + } +} diff --git a/zircon-syscall/src/object.rs b/zircon-syscall/src/object.rs index a7fb6f9b0..41072b233 100644 --- a/zircon-syscall/src/object.rs +++ b/zircon-syscall/src/object.rs @@ -252,8 +252,9 @@ impl Syscall<'_> { avail.write(ids.len())?; } Topic::Bti => { - let bti = proc.get_object_with_rights::(handle, Rights::INSPECT)?; - UserOutPtr::::from(buffer).write(bti.get_info())?; + let bti = proc + .get_object_with_rights::(handle, Rights::INSPECT)?; + UserOutPtr::::from(buffer).write(bti.get_info())?; } _ => { error!("not supported info topic: {:?}", topic); diff --git a/zircon-syscall/src/vmo.rs b/zircon-syscall/src/vmo.rs index b51627da4..cb09b43f0 100644 --- a/zircon-syscall/src/vmo.rs +++ b/zircon-syscall/src/vmo.rs @@ -220,7 +220,7 @@ impl Syscall<'_> { } let proc = self.thread.proc(); proc.check_policy(PolicyCondition::NewVMO)?; - let _bti = proc.get_object_with_rights::(bti, Rights::MAP)?; + let _bti = proc.get_object_with_rights::(bti, Rights::MAP)?; let vmo = VmObject::new_contiguous(size, align_log2)?; let handle_value = proc.add_handle(Handle::new(vmo, Rights::DEFAULT_VMO)); out.write(handle_value)?; From b99152ba8fcb969993cd3c68e5286cb4222d1cf7 Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Sun, 10 May 2020 14:48:20 +0800 Subject: [PATCH 2/5] move Resource to dev mod again --- zircon-loader/src/lib.rs | 2 +- zircon-object/src/dev/mod.rs | 3 ++- zircon-object/src/{ => dev}/resource.rs | 1 - zircon-object/src/exception.rs | 1 - zircon-object/src/lib.rs | 2 -- zircon-syscall/src/ddk.rs | 2 +- zircon-syscall/src/debug.rs | 2 +- zircon-syscall/src/debuglog.rs | 2 +- zircon-syscall/src/resource.rs | 2 +- zircon-syscall/src/time.rs | 2 +- zircon-syscall/src/vmo.rs | 2 +- 11 files changed, 9 insertions(+), 12 deletions(-) rename zircon-object/src/{ => dev}/resource.rs (99%) delete mode 100644 zircon-object/src/exception.rs diff --git a/zircon-loader/src/lib.rs b/zircon-loader/src/lib.rs index 0a5e4fc01..4a5ff45aa 100644 --- a/zircon-loader/src/lib.rs +++ b/zircon-loader/src/lib.rs @@ -12,7 +12,7 @@ use { alloc::{boxed::Box, sync::Arc, vec::Vec}, kernel_hal::GeneralRegs, xmas_elf::ElfFile, - zircon_object::{ipc::*, object::*, resource::*, task::*, util::elf_loader::*, vm::*}, + zircon_object::{dev::*, ipc::*, object::*, task::*, util::elf_loader::*, vm::*}, zircon_syscall::Syscall, }; diff --git a/zircon-object/src/dev/mod.rs b/zircon-object/src/dev/mod.rs index d58150a3f..f0a433749 100644 --- a/zircon-object/src/dev/mod.rs +++ b/zircon-object/src/dev/mod.rs @@ -3,5 +3,6 @@ use super::*; mod bti; mod iommu; mod pmt; +mod resource; -pub use self::{bti::*, iommu::*, pmt::*}; +pub use self::{bti::*, iommu::*, pmt::*, resource::*}; diff --git a/zircon-object/src/resource.rs b/zircon-object/src/dev/resource.rs similarity index 99% rename from zircon-object/src/resource.rs rename to zircon-object/src/dev/resource.rs index 08aba0901..cefda1962 100644 --- a/zircon-object/src/resource.rs +++ b/zircon-object/src/dev/resource.rs @@ -24,7 +24,6 @@ bitflags! { } /// Address space rights and accounting. -#[allow(dead_code)] pub struct Resource { base: KObjectBase, kind: ResourceKind, diff --git a/zircon-object/src/exception.rs b/zircon-object/src/exception.rs deleted file mode 100644 index 8b1378917..000000000 --- a/zircon-object/src/exception.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/zircon-object/src/lib.rs b/zircon-object/src/lib.rs index e59d79b19..f819e9bc4 100644 --- a/zircon-object/src/lib.rs +++ b/zircon-object/src/lib.rs @@ -23,10 +23,8 @@ extern crate std; pub mod debuglog; pub mod dev; mod error; -pub mod exception; pub mod ipc; pub mod object; -pub mod resource; pub mod signal; pub mod task; pub mod util; diff --git a/zircon-syscall/src/ddk.rs b/zircon-syscall/src/ddk.rs index f31c670df..5a7741e8b 100644 --- a/zircon-syscall/src/ddk.rs +++ b/zircon-syscall/src/ddk.rs @@ -2,8 +2,8 @@ use { super::*, bitflags::bitflags, kernel_hal::DevVAddr, + zircon_object::dev::*, zircon_object::vm::{page_aligned, VmObject}, - zircon_object::{dev::*, resource::*}, }; impl Syscall<'_> { diff --git a/zircon-syscall/src/debug.rs b/zircon-syscall/src/debug.rs index 8d24fa4e5..a63eee2a0 100644 --- a/zircon-syscall/src/debug.rs +++ b/zircon-syscall/src/debug.rs @@ -1,5 +1,5 @@ use super::*; -use zircon_object::resource::*; +use zircon_object::dev::*; impl Syscall<'_> { pub fn sys_debug_write(&self, buf: UserInPtr, len: usize) -> ZxResult { diff --git a/zircon-syscall/src/debuglog.rs b/zircon-syscall/src/debuglog.rs index 4f13579f5..2fbe41092 100644 --- a/zircon-syscall/src/debuglog.rs +++ b/zircon-syscall/src/debuglog.rs @@ -1,6 +1,6 @@ use { super::*, - zircon_object::{debuglog::DebugLog, resource::*}, + zircon_object::{debuglog::DebugLog, dev::*}, }; const FLAG_READABLE: u32 = 0x4000_0000u32; diff --git a/zircon-syscall/src/resource.rs b/zircon-syscall/src/resource.rs index adbcb343d..d99de8127 100644 --- a/zircon-syscall/src/resource.rs +++ b/zircon-syscall/src/resource.rs @@ -1,4 +1,4 @@ -use {super::*, core::convert::TryFrom, zircon_object::resource::*}; +use {super::*, core::convert::TryFrom, zircon_object::dev::*}; impl Syscall<'_> { #[allow(clippy::too_many_arguments)] diff --git a/zircon-syscall/src/time.rs b/zircon-syscall/src/time.rs index 67db70fe1..789983558 100644 --- a/zircon-syscall/src/time.rs +++ b/zircon-syscall/src/time.rs @@ -6,7 +6,7 @@ use { time::Duration, }, kernel_hal::{sleep_until, timer_now, yield_now}, - zircon_object::{resource::*, task::*}, + zircon_object::{dev::*, task::*}, }; static UTC_OFFSET: AtomicU64 = AtomicU64::new(0); diff --git a/zircon-syscall/src/vmo.rs b/zircon-syscall/src/vmo.rs index cb09b43f0..54319e7d3 100644 --- a/zircon-syscall/src/vmo.rs +++ b/zircon-syscall/src/vmo.rs @@ -3,7 +3,7 @@ use { bitflags::bitflags, kernel_hal::CachePolicy, numeric_enum_macro::numeric_enum, - zircon_object::{dev::*, resource::*, task::PolicyCondition, vm::*}, + zircon_object::{dev::*, task::PolicyCondition, vm::*}, }; impl Syscall<'_> { From 7c2f44840b57b57568e9868b06c4d1c6e0f45ca2 Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Mon, 11 May 2020 09:16:41 +0800 Subject: [PATCH 3/5] implement sys_futex_wake_handle_close_thread_exit for libos --- zircon-syscall/src/futex.rs | 2 +- zircon-syscall/src/lib.rs | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/zircon-syscall/src/futex.rs b/zircon-syscall/src/futex.rs index af1683133..c67480523 100644 --- a/zircon-syscall/src/futex.rs +++ b/zircon-syscall/src/futex.rs @@ -1,4 +1,4 @@ -use {super::*, core::sync::atomic::*, zircon_object::task::ThreadState}; +use {super::*, zircon_object::task::ThreadState}; impl Syscall<'_> { pub async fn sys_futex_wait( diff --git a/zircon-syscall/src/lib.rs b/zircon-syscall/src/lib.rs index a5464be56..c32b0dfc9 100644 --- a/zircon-syscall/src/lib.rs +++ b/zircon-syscall/src/lib.rs @@ -12,7 +12,10 @@ extern crate log; use { self::time::Deadline, alloc::sync::Arc, - core::convert::TryFrom, + core::{ + convert::TryFrom, + sync::atomic::{AtomicI32, Ordering}, + }, futures::pin_mut, kernel_hal::{user::*, GeneralRegs}, zircon_object::object::*, @@ -257,6 +260,16 @@ impl Syscall<'_> { let _ = self.sys_handle_close(a3 as _); self.sys_thread_exit() }), + Sys::FUTEX_WAKE_HANDLE_CLOSE_THREAD_EXIT => { + // atomic_store_explicit(value_ptr, new_value, memory_order_release) + UserInPtr::::from(a0) + .as_ref() + .unwrap() + .store(a2 as i32, Ordering::Release); + let _ = self.sys_futex_wake(a0.into(), a1 as _); + let _ = self.sys_handle_close(a3 as _); + self.sys_thread_exit() + } Sys::OBJECT_GET_CHILD => { self.sys_object_get_child(a0 as _, a1 as _, a2 as _, a3.into()) } From 641eefb77da8b498baad39edebc5bbb673473763 Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Mon, 11 May 2020 09:38:26 +0800 Subject: [PATCH 4/5] implement sys_clock_read for libos --- zircon-syscall/src/lib.rs | 2 ++ zircon-syscall/src/time.rs | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/zircon-syscall/src/lib.rs b/zircon-syscall/src/lib.rs index c32b0dfc9..0d5ad0590 100644 --- a/zircon-syscall/src/lib.rs +++ b/zircon-syscall/src/lib.rs @@ -216,6 +216,8 @@ impl Syscall<'_> { Sys::CPRNG_DRAW_ONCE => self.sys_cprng_draw_once(a0 as _, a1 as _), Sys::NANOSLEEP => self.sys_nanosleep(a0.into()).await, Sys::CLOCK_GET => self.sys_clock_get(a0 as _, a1.into()), + Sys::CLOCK_READ => self.sys_clock_read(a0 as _, a1.into()), + Sys::CLOCK_ADJUST => self.sys_clock_adjust(a0 as _, a1 as _, a2 as _), Sys::TIMER_CREATE => self.sys_timer_create(a0 as _, a1 as _, a2.into()), Sys::DEBUG_WRITE => self.sys_debug_write(a0.into(), a1 as _), Sys::DEBUGLOG_CREATE => self.sys_debuglog_create(a0 as _, a1 as _, a2.into()), diff --git a/zircon-syscall/src/time.rs b/zircon-syscall/src/time.rs index 789983558..4e608f245 100644 --- a/zircon-syscall/src/time.rs +++ b/zircon-syscall/src/time.rs @@ -32,6 +32,13 @@ impl Syscall<'_> { } } + pub fn sys_clock_read(&self, handle: HandleValue, mut now: UserOutPtr) -> ZxResult { + info!("clock.read: handle={:#x?}", handle); + warn!("ignore clock handle"); + now.write(timer_now().as_nanos() as u64)?; + Ok(()) + } + pub fn sys_clock_adjust(&self, resource: HandleValue, clock_id: u32, offset: u64) -> ZxResult { info!( "clock.adjust: resource={:#x?}, id={:#x}, offset={:#x}", From 07a98c81a37a41d1fdbee209a9bfa0e904d77673 Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Mon, 11 May 2020 12:19:46 +0800 Subject: [PATCH 5/5] refactor VMO slice, make it a separate struct --- zircon-object/src/vm/vmar.rs | 2 +- zircon-object/src/vm/vmo/mod.rs | 36 ++---- zircon-object/src/vm/vmo/paged.rs | 183 +++------------------------ zircon-object/src/vm/vmo/physical.rs | 17 +-- zircon-object/src/vm/vmo/slice.rs | 126 ++++++++++++++++++ 5 files changed, 159 insertions(+), 205 deletions(-) create mode 100644 zircon-object/src/vm/vmo/slice.rs diff --git a/zircon-object/src/vm/vmar.rs b/zircon-object/src/vm/vmar.rs index 1ebebcdb2..a3540aafb 100644 --- a/zircon-object/src/vm/vmar.rs +++ b/zircon-object/src/vm/vmar.rs @@ -170,7 +170,7 @@ impl VmAddressRegion { let mut flags = flags; // if vmo != 0 { - flags |= MMUFlags::from_bits_truncate(vmo.get_cache_policy() as u32 as usize); + flags |= MMUFlags::from_bits_truncate(vmo.cache_policy() as u32 as usize); } // align = 1K? 2K? 4K? 8K? ... if !self.test_map(inner, offset, len, PAGE_SIZE) { diff --git a/zircon-object/src/vm/vmo/mod.rs b/zircon-object/src/vm/vmo/mod.rs index 06561681f..8de0a9bf4 100644 --- a/zircon-object/src/vm/vmo/mod.rs +++ b/zircon-object/src/vm/vmo/mod.rs @@ -1,5 +1,5 @@ use { - self::{paged::*, physical::*}, + self::{paged::*, physical::*, slice::*}, super::*, crate::object::*, alloc::{ @@ -14,6 +14,7 @@ use { mod paged; mod physical; +mod slice; kcounter!(VMO_PAGE_ALLOC, "vmo.page_alloc"); kcounter!(VMO_PAGE_DEALLOC, "vmo.page_dealloc"); @@ -63,20 +64,13 @@ pub trait VMObjectTrait: Sync + Send { user_id: KoID, ) -> ZxResult>; - fn create_slice( - self: Arc, - id: KoID, - offset: usize, - len: usize, - ) -> ZxResult>; - fn append_mapping(&self, mapping: Weak); fn remove_mapping(&self, mapping: Weak); fn complete_info(&self, info: &mut VmoInfo); - fn get_cache_policy(&self) -> CachePolicy; + fn cache_policy(&self) -> CachePolicy; fn set_cache_policy(&self, policy: CachePolicy) -> ZxResult; @@ -133,7 +127,6 @@ impl VmObject { } /// Create a new VMO representing a piece of contiguous physical memory. - /// You must ensure nobody has the ownership of this piece of memory yet. pub fn new_physical(paddr: PhysAddr, pages: usize) -> Arc { Arc::new(VmObject { base: KObjectBase::with_signal(Signal::VMO_ZERO_CHILDREN), @@ -196,25 +189,26 @@ impl VmObject { return Err(ZxError::OUT_OF_RANGE); } // child slice must be wholly contained - let parrent_size = self.inner.len(); + let parent_size = self.inner.len(); if !page_aligned(offset) { return Err(ZxError::INVALID_ARGS); } - if offset > parrent_size || size > parrent_size - offset { + if offset > parent_size || size > parent_size - offset { return Err(ZxError::INVALID_ARGS); } if self.resizable { return Err(ZxError::NOT_SUPPORTED); } - let base = KObjectBase::with(&self.base.name(), Signal::VMO_ZERO_CHILDREN); - let inner = self.inner.clone().create_slice(base.id, offset, size)?; + if self.inner.cache_policy() != CachePolicy::Cached && !self.inner.is_contiguous() { + return Err(ZxError::BAD_STATE); + } let child = Arc::new(VmObject { + base: KObjectBase::with(&self.base.name(), Signal::VMO_ZERO_CHILDREN), parent: Mutex::new(Arc::downgrade(self)), children: Mutex::new(Vec::new()), resizable: false, _counter: CountHelper::new(), - inner, - base, + inner: VMObjectSlice::new(self.inner.clone(), offset, size), }); self.add_child(&child); Ok(child) @@ -222,7 +216,7 @@ impl VmObject { /// Add child to the list and signal if ZeroChildren signal is active. /// If the number of children turns 0 to 1, signal it - pub fn add_child(&self, child: &Arc) { + fn add_child(&self, child: &Arc) { let mut children = self.children.lock(); children.retain(|x| x.strong_count() != 0); children.push(Arc::downgrade(child)); @@ -263,7 +257,7 @@ impl VmObject { } else { VmoInfoFlags::empty() }, - cache_policy: self.inner.get_cache_policy() as u32, + cache_policy: self.inner.cache_policy() as u32, ..Default::default() }; self.inner.complete_info(&mut ret); @@ -299,15 +293,13 @@ impl Drop for VmObject { if let Some(parent) = self.parent.lock().upgrade() { let mut my_children = { let mut my_children = self.children.lock(); - for ch in &mut (*my_children) { + for ch in my_children.iter_mut() { if let Some(ch) = ch.upgrade() { let mut ch_parent = ch.parent.lock(); *ch_parent = Arc::downgrade(&parent); } } - let mut res: Vec> = Vec::new(); - res.append(&mut (*my_children)); - res + my_children.clone() }; let mut children = parent.children.lock(); children.append(&mut my_children); diff --git a/zircon-object/src/vm/vmo/paged.rs b/zircon-object/src/vm/vmo/paged.rs index a04c98ce1..0d55e7b7b 100644 --- a/zircon-object/src/vm/vmo/paged.rs +++ b/zircon-object/src/vm/vmo/paged.rs @@ -16,8 +16,6 @@ enum VMOType { Origin, /// A snapshot of the parent node. Snapshot, - /// A Slice of the parent node. - Slice, /// Internal non-leaf node for snapshot. /// /// ```text @@ -53,10 +51,6 @@ impl VMOType { fn is_hidden(&self) -> bool { matches!(self, VMOType::Hidden { .. }) } - - fn is_slice(&self) -> bool { - matches!(self, VMOType::Slice) - } } /// The main VM object type, holding a list of pages. @@ -222,59 +216,22 @@ impl VMObjectPaged { } Ok(()) } - - fn if_slice_do(&self, offset: usize, f: F) -> Option> - where - F: FnOnce(&VMObjectPagedInner) -> ZxResult, - { - let inner = self.inner.lock(); - if inner.type_.is_slice() { - // deal with slice seperately - // A slice definitely has a parent. - if inner.parent.is_some() && offset < inner.parent_limit - inner.parent_offset { - Some(f(&inner)) - } else { - Some(Err(ZxError::OUT_OF_RANGE)) - } - } else { - // continue with codes below - None - } - } } impl VMObjectTrait for VMObjectPaged { fn read(&self, offset: usize, buf: &mut [u8]) -> ZxResult { - if self.get_cache_policy() != CachePolicy::Cached { + if self.cache_policy() != CachePolicy::Cached { return Err(ZxError::BAD_STATE); } - if let Some(res) = self.if_slice_do(offset, |inner| { - inner - .parent - .as_ref() - .unwrap() - .read(offset + inner.parent_offset, buf) - }) { - return res; - } self.for_each_page(offset, buf.len(), MMUFlags::READ, |paddr, buf_range| { kernel_hal::pmem_read(paddr, &mut buf[buf_range]); }) } fn write(&self, offset: usize, buf: &[u8]) -> ZxResult { - if self.get_cache_policy() != CachePolicy::Cached { + if self.cache_policy() != CachePolicy::Cached { return Err(ZxError::BAD_STATE); } - if let Some(res) = self.if_slice_do(offset, |inner| { - inner - .parent - .as_ref() - .unwrap() - .write(offset + inner.parent_offset, buf) - }) { - return res; - } self.for_each_page(offset, buf.len(), MMUFlags::WRITE, |paddr, buf_range| { kernel_hal::pmem_write(paddr, &buf[buf_range]); }) @@ -340,22 +297,8 @@ impl VMObjectTrait for VMObjectPaged { } fn decommit(&self, offset: usize, len: usize) -> ZxResult { - if let Some(res) = self.if_slice_do(offset, |inner| { - inner - .parent - .as_ref() - .unwrap() - .decommit(offset + inner.parent_offset, len) - }) { - return res; - } let mut inner = self.inner.lock(); - if inner.type_.is_slice() { - let parent_offset = offset + inner.parent_offset; - return inner.parent.as_ref().unwrap().decommit(parent_offset, len); - } - let check = inner.parent.is_none(); - if !check { + if inner.parent.is_some() { return Err(ZxError::NOT_SUPPORTED); } let start_page = offset / PAGE_SIZE; @@ -374,56 +317,10 @@ impl VMObjectTrait for VMObjectPaged { ) -> ZxResult> { assert!(page_aligned(offset)); assert!(page_aligned(len)); - if let Some(res) = self.if_slice_do(offset, |inner| { - inner - .parent - .as_ref() - .unwrap() - .create_child(offset + inner.parent_offset, len, user_id) - }) { - return res; - } let child = self.inner.lock().create_child(offset, len, user_id)?; Ok(child) } - fn create_slice( - self: Arc, - id: KoID, - offset: usize, - len: usize, - ) -> ZxResult> { - if let Some(res) = self.if_slice_do(offset, |inner| { - inner - .parent - .clone() - .unwrap() - .create_slice(id, offset + inner.parent_offset, len) - }) { - return res; - } - let inner = self.inner.lock(); - let my_cache_policy = inner.cache_policy; - if my_cache_policy != CachePolicy::Cached && !self.is_contiguous() { - return Err(ZxError::BAD_STATE); - } - let obj = VMObjectPaged::wrap(VMObjectPagedInner { - user_id: id, - type_: VMOType::Slice, - parent: Some(self.clone()), - parent_offset: offset, - parent_limit: offset + len, - size: len, - frames: BTreeMap::new(), - mappings: Vec::new(), - cache_policy: my_cache_policy, - contiguous: inner.is_contiguous(), - self_ref: Default::default(), - pin_count: 0, - }); - Ok(obj) - } - fn append_mapping(&self, mapping: Weak) { self.inner.lock().mappings.push(mapping); } @@ -439,7 +336,8 @@ impl VMObjectTrait for VMObjectPaged { info.flags |= VmoInfoFlags::TYPE_PAGED; self.inner.lock().complete_info(info); } - fn get_cache_policy(&self) -> CachePolicy { + + fn cache_policy(&self) -> CachePolicy { let inner = self.inner.lock(); inner.cache_policy } @@ -476,16 +374,7 @@ impl VMObjectTrait for VMObjectPaged { fn committed_pages_in_range(&self, start_idx: usize, end_idx: usize) -> usize { let inner = self.inner.lock(); - if inner.type_.is_slice() { - let pg_off = pages(inner.parent_offset); - inner - .parent - .as_ref() - .unwrap() - .committed_pages_in_range(start_idx + pg_off, end_idx + pg_off) - } else { - inner.committed_pages_in_range(start_idx, end_idx) - } + inner.committed_pages_in_range(start_idx, end_idx) } fn share_count(&self) -> usize { @@ -493,26 +382,13 @@ impl VMObjectTrait for VMObjectPaged { } fn pin(&self, offset: usize, len: usize) -> ZxResult { - { - // if_slice_do needs inner.lock, so we should release it after pre-check - let inner = self.inner.lock(); - if offset as usize > inner.size || len > inner.size - (offset as usize) { - return Err(ZxError::OUT_OF_RANGE); - } - if len == 0 { - return Ok(()); - } + let mut inner = self.inner.lock(); + if offset + len >= inner.size { + return Err(ZxError::OUT_OF_RANGE); } - if let Some(res) = self.if_slice_do(offset, |inner| { - inner - .parent - .as_ref() - .unwrap() - .pin(offset + inner.parent_offset, len) - }) { - return res; + if len == 0 { + return Ok(()); } - let mut inner = self.inner.lock(); let start_page = offset / PAGE_SIZE; let end_page = pages(offset + len); for i in start_page..end_page { @@ -529,26 +405,13 @@ impl VMObjectTrait for VMObjectPaged { } fn unpin(&self, offset: usize, len: usize) -> ZxResult { - { - let inner = self.inner.lock(); - if offset + len > inner.size { - return Err(ZxError::OUT_OF_RANGE); - } - if len == 0 { - return Ok(()); - } + let mut inner = self.inner.lock(); + if offset + len >= inner.size { + return Err(ZxError::OUT_OF_RANGE); } - if let Some(res) = self.if_slice_do(offset, |inner| { - inner - .parent - .as_ref() - .unwrap() - .pin(offset + inner.parent_offset, len) - }) { - return res; + if len == 0 { + return Ok(()); } - - let mut inner = self.inner.lock(); let start_page = offset / PAGE_SIZE; let end_page = pages(offset + len); for i in start_page..end_page { @@ -590,15 +453,6 @@ impl VMObjectPaged { flags: MMUFlags, child: &WeakRef, ) -> ZxResult { - if let Some(res) = self.if_slice_do(page_idx * PAGE_SIZE, |inner| { - inner.parent.as_ref().unwrap().commit_page_internal( - page_idx + pages(inner.parent_offset), - flags, - &inner.self_ref, - ) - }) { - return res; - } let mut inner = self.inner.lock(); // special case let no_parent = inner.parent.is_none(); @@ -692,11 +546,6 @@ impl VMObjectPaged { new_range: Option<(usize, usize)>, ) { let mut inner = self.inner.lock(); - if inner.type_.is_slice() { - // Just do nothing? - // - no frames to release? True, at least now - return; - } let (tag, other) = inner.type_.get_tag_and_other(old); let arc_other_child = other.upgrade().unwrap(); let mut other_child = arc_other_child.inner.lock(); diff --git a/zircon-object/src/vm/vmo/physical.rs b/zircon-object/src/vm/vmo/physical.rs index 3be70d140..00c4de9dd 100644 --- a/zircon-object/src/vm/vmo/physical.rs +++ b/zircon-object/src/vm/vmo/physical.rs @@ -87,20 +87,7 @@ impl VMObjectTrait for VMObjectPhysical { Err(ZxError::NOT_SUPPORTED) } - fn create_slice( - self: Arc, - _id: KoID, - offset: usize, - len: usize, - ) -> ZxResult> { - assert!(page_aligned(offset) && page_aligned(len)); - let obj = VMObjectPhysical::new(self.paddr + offset, len / PAGE_SIZE); - obj.inner.lock().cache_policy = self.inner.lock().cache_policy; - Ok(obj) - } - fn append_mapping(&self, _mapping: Weak) { - // unimplemented!() // TODO this function is only used when physical-vmo supports create_child let mut inner = self.inner.lock(); inner.mapping_count += 1; @@ -115,7 +102,7 @@ impl VMObjectTrait for VMObjectPhysical { warn!("VmoInfo for physical is unimplemented"); } - fn get_cache_policy(&self) -> CachePolicy { + fn cache_policy(&self) -> CachePolicy { let inner = self.inner.lock(); inner.cache_policy } @@ -161,7 +148,7 @@ mod tests { fn read_write() { let vmo = VmObject::new_physical(0x1000, 2); let vmphy = vmo.inner.clone(); - assert_eq!(vmphy.get_cache_policy(), CachePolicy::Uncached); + assert_eq!(vmphy.cache_policy(), CachePolicy::Uncached); super::super::tests::read_write(&vmo); } } diff --git a/zircon-object/src/vm/vmo/slice.rs b/zircon-object/src/vm/vmo/slice.rs new file mode 100644 index 000000000..317326e39 --- /dev/null +++ b/zircon-object/src/vm/vmo/slice.rs @@ -0,0 +1,126 @@ +use super::*; +use core::sync::atomic::{AtomicUsize, Ordering}; + +pub struct VMObjectSlice { + /// Parent node. + parent: Arc, + /// The offset from parent. + offset: usize, + /// The size in bytes. + size: usize, + /// Mapping count. + mapping_count: AtomicUsize, +} + +impl VMObjectSlice { + pub fn new(parent: Arc, offset: usize, size: usize) -> Arc { + Arc::new(VMObjectSlice { + parent, + offset, + size, + mapping_count: AtomicUsize::new(0), + }) + } + + fn check_range(&self, offset: usize, len: usize) -> ZxResult { + if offset + len >= self.size { + return Err(ZxError::OUT_OF_RANGE); + } + Ok(()) + } +} + +impl VMObjectTrait for VMObjectSlice { + fn read(&self, offset: usize, buf: &mut [u8]) -> ZxResult { + self.check_range(offset, buf.len())?; + self.parent.read(offset + self.offset, buf) + } + + fn write(&self, offset: usize, buf: &[u8]) -> ZxResult { + self.check_range(offset, buf.len())?; + self.parent.write(offset + self.offset, buf) + } + + fn len(&self) -> usize { + self.size + } + + fn set_len(&self, _len: usize) -> ZxResult { + unimplemented!() + } + + fn commit_page(&self, page_idx: usize, flags: MMUFlags) -> ZxResult { + self.parent + .commit_page(page_idx + self.offset / PAGE_SIZE, flags) + } + + fn commit(&self, offset: usize, len: usize) -> ZxResult { + self.parent.commit(offset + self.offset, len) + } + + fn decommit(&self, offset: usize, len: usize) -> ZxResult { + self.parent.decommit(offset + self.offset, len) + } + + fn create_child( + &self, + _offset: usize, + _len: usize, + _user_id: u64, + ) -> ZxResult> { + Err(ZxError::NOT_SUPPORTED) + } + + fn append_mapping(&self, _mapping: Weak) { + self.mapping_count.fetch_add(1, Ordering::SeqCst); + } + + fn remove_mapping(&self, _mapping: Weak) { + self.mapping_count.fetch_sub(1, Ordering::SeqCst); + } + + fn complete_info(&self, info: &mut VmoInfo) { + self.parent.complete_info(info); + } + + fn cache_policy(&self) -> CachePolicy { + self.parent.cache_policy() + } + + fn set_cache_policy(&self, _policy: CachePolicy) -> ZxResult { + Ok(()) + } + + fn share_count(&self) -> usize { + self.mapping_count.load(Ordering::SeqCst) + } + + fn committed_pages_in_range(&self, start_idx: usize, end_idx: usize) -> usize { + let po = pages(self.offset); + self.parent + .committed_pages_in_range(start_idx + po, end_idx + po) + } + + fn pin(&self, offset: usize, len: usize) -> ZxResult { + self.check_range(offset, len)?; + self.parent.pin(offset + self.offset, len) + } + + fn unpin(&self, offset: usize, len: usize) -> ZxResult { + self.check_range(offset, len)?; + self.parent.unpin(offset + self.offset, len) + } + + fn is_contiguous(&self) -> bool { + self.parent.is_contiguous() + } + + fn is_paged(&self) -> bool { + self.parent.is_paged() + } + + fn zero(&self, offset: usize, len: usize) -> ZxResult { + self.check_range(offset, len)?; + self.parent.zero(offset + self.offset, len) + } +}