Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions kernel-hal-bare/src/arch/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,3 +354,28 @@ pub fn init() {
pub fn fetch_fault_vaddr() -> VirtAddr {
Cr2::read().as_u64() as _
}

lazy_static! {
static ref RANGECHECKER: Mutex<Vec<(usize, usize)>> = Mutex::new(Vec::default());
}

#[export_name = "dma_range_check"]
pub fn dma_check(paddr: PhysAddr, pages: usize) -> bool {
let mut checker = RANGECHECKER.lock();
let paddr_end = paddr + pages * PAGE_SIZE;
let conflict = checker.iter().any(|range| {
range.0 <= paddr && range.1 > paddr || range.0 <= paddr_end && paddr_end < range.1
});
if !conflict {
checker.push((paddr, paddr_end));
}
!conflict
}

#[export_name = "dma_range_recycle"]
pub fn dma_recycle(paddr: PhysAddr, pages: usize) {
let paddr_end = paddr + pages * PAGE_SIZE;
RANGECHECKER
.lock()
.retain(|range| !(range.0 == paddr && range.1 == paddr_end));
}
5 changes: 3 additions & 2 deletions kernel-hal-bare/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,11 @@ pub fn frame_copy(src: PhysAddr, target: PhysAddr) {

/// Zero `target` frame.
#[export_name = "hal_frame_zero"]
pub fn frame_zero(target: PhysAddr) {
pub fn frame_zero_in_range(target: PhysAddr, start: usize, end: usize) {
assert!(start < PAGE_SIZE && end <= PAGE_SIZE);
trace!("frame_zero: {:#x}", target);
unsafe {
core::ptr::write_bytes(phys_to_virt(target) as *mut u8, 0, PAGE_SIZE);
core::ptr::write_bytes(phys_to_virt(target + start) as *mut u8, 0, end - start);
}
}

Expand Down
8 changes: 8 additions & 0 deletions kernel-hal-unix/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,14 @@ pub fn init() {
});
}

#[export_name = "dma_range_check"]
pub fn dma_check(_paddr: PhysAddr, _pages: usize) -> bool {
true
}

#[export_name = "dma_range_recycle"]
pub fn dma_recycle(_paddr: PhysAddr, _pages: usize) {}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
14 changes: 13 additions & 1 deletion kernel-hal/src/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ pub fn frame_copy(_src: PhysAddr, _target: PhysAddr) {
/// Zero `target` frame.
#[linkage = "weak"]
#[export_name = "hal_frame_zero"]
pub fn frame_zero(_target: PhysAddr) {
pub fn frame_zero_in_range(_target: PhysAddr, _start: usize, _end: usize) {
unimplemented!()
}

Expand Down Expand Up @@ -261,3 +261,15 @@ pub fn vdso_constants() -> VdsoConstants {
pub fn fetch_fault_vaddr() -> VirtAddr {
unimplemented!()
}

#[linkage = "weak"]
#[export_name = "dma_range_check"]
pub fn dma_check(_paddr: PhysAddr, _pages: usize) -> bool {
unimplemented!()
}

#[linkage = "weak"]
#[export_name = "dma_range_recycle"]
pub fn dma_recycle(_paddr: PhysAddr, _pages: usize) {
unimplemented!()
}
2 changes: 1 addition & 1 deletion zircon-loader/src/kcounter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub fn create_kcounter_vmo() -> (Arc<VmObject>, Arc<VmObject>) {
kcounters_arena_end as usize / PAGE_SIZE,
"all kcounters must in the same page"
);
unsafe { VmObject::new_physical(paddr, 1) }
VmObject::new_physical(paddr, 1)
};
kcounters_vmo.set_name("counters/arena");
(counter_name_vmo, kcounters_vmo)
Expand Down
4 changes: 2 additions & 2 deletions zircon-loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,9 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
let constants: [u8; 112] = unsafe { core::mem::transmute(kernel_hal::vdso_constants()) };
vdso_vmo.write(VDSO_CONSTANT_BASE, &constants).unwrap();
vdso_vmo.set_name("vdso/full");
let vdso_test1 = vdso_vmo.create_child(false, 0, vdso_vmo.len());
let vdso_test1 = vdso_vmo.create_child(false, false, 0, vdso_vmo.len());
vdso_test1.set_name("vdso/test1");
let vdso_test2 = vdso_vmo.create_child(false, 0, vdso_vmo.len());
let vdso_test2 = vdso_vmo.create_child(false, false, 0, vdso_vmo.len());
vdso_test2.set_name("vdso/test2");
handles[K_FIRSTVDSO] = Handle::new(vdso_vmo, Rights::DEFAULT_VMO | Rights::EXECUTE);
handles[K_FIRSTVDSO + 1] = Handle::new(vdso_test1, Rights::DEFAULT_VMO | Rights::EXECUTE);
Expand Down
59 changes: 49 additions & 10 deletions zircon-object/src/vm/vmo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,13 @@ pub trait VMObjectTrait: Sync + Send {
fn decommit(&self, offset: usize, len: usize) -> ZxResult;

/// Create a child VMO.
fn create_child(&self, offset: usize, len: usize, user_id: KoID) -> Arc<dyn VMObjectTrait>;
fn create_child(
&self,
is_slice: bool,
offset: usize,
len: usize,
user_id: KoID,
) -> Arc<dyn VMObjectTrait>;

fn append_mapping(&self, mapping: Weak<VmMapping>);

Expand All @@ -71,6 +77,8 @@ pub trait VMObjectTrait: Sync + Send {
fn share_count(&self) -> usize;

fn committed_pages_in_range(&self, start_idx: usize, end_idx: usize) -> usize;

fn zero(&self, offset: usize, len: usize) -> ZxResult;
}

pub struct VmObject {
Expand All @@ -79,6 +87,7 @@ pub struct VmObject {
children: Mutex<Vec<Weak<VmObject>>>,
_counter: CountHelper,
resizable: bool,
is_slice: bool,
inner: Arc<dyn VMObjectTrait>,
}

Expand All @@ -97,42 +106,60 @@ impl VmObject {
parent: Default::default(),
children: Mutex::new(Vec::new()),
resizable,
is_slice: false,
_counter: CountHelper::new(),
inner: VMObjectPaged::new(base.id, pages),
base,
})
}

/// Create a new VMO representing a piece of contiguous physical memory.
///
/// # Safety
///
/// You must ensure nobody has the ownership of this piece of memory yet.
#[allow(unsafe_code)]
pub unsafe fn new_physical(paddr: PhysAddr, pages: usize) -> Arc<Self> {
pub fn new_physical(paddr: PhysAddr, pages: usize) -> Arc<Self> {
Arc::new(VmObject {
base: KObjectBase::with_signal(Signal::VMO_ZERO_CHILDREN),
parent: Default::default(),
children: Mutex::new(Vec::new()),
resizable: true,
is_slice: false,
_counter: CountHelper::new(),
inner: VMObjectPhysical::new(paddr, pages),
})
}

/// Create a child VMO.
pub fn create_child(self: &Arc<Self>, resizable: bool, offset: usize, len: usize) -> Arc<Self> {
pub fn create_child(
self: &Arc<Self>,
is_slice: bool,
resizable: bool,
offset: usize,
len: usize,
) -> Arc<Self> {
assert!(!(is_slice && resizable));
if self.is_slice {
assert!(is_slice, "create a not-slice child for a slice parent!!!");
}
let base = KObjectBase::with_signal(Signal::VMO_ZERO_CHILDREN);
base.set_name(&self.base.name());
let child = Arc::new(VmObject {
parent: Arc::downgrade(self),
parent: if is_slice && self.is_slice {
self.parent.clone()
} else {
Arc::downgrade(self)
},
children: Mutex::new(Vec::new()),
resizable,
is_slice,
_counter: CountHelper::new(),
inner: self.inner.create_child(offset, len, base.id),
inner: self.inner.create_child(is_slice, offset, len, base.id),
base,
});
self.children.lock().push(Arc::downgrade(&child));
if self.is_slice {
let arc_parent = self.parent.upgrade().unwrap();
arc_parent.children.lock().push(Arc::downgrade(&child));
} else {
self.children.lock().push(Arc::downgrade(&child));
}
self.base.signal_clear(Signal::VMO_ZERO_CHILDREN);
child
}
Expand Down Expand Up @@ -182,6 +209,10 @@ impl VmObject {
pub fn is_resizable(&self) -> bool {
self.resizable
}

pub fn is_slice(&self) -> bool {
self.is_slice
}
}

impl Deref for VmObject {
Expand All @@ -197,6 +228,14 @@ impl Drop for VmObject {
if let Some(parent) = self.parent.upgrade() {
let mut children = parent.children.lock();
children.retain(|c| c.strong_count() != 0);
children.iter().for_each(|child| {
let arc_child = child.upgrade().unwrap();
let mut locked_children = arc_child.children.lock();
locked_children.retain(|c| c.strong_count() != 0);
if locked_children.is_empty() {
arc_child.base.signal_set(Signal::VMO_ZERO_CHILDREN);
}
});
if children.is_empty() {
parent.base.signal_set(Signal::VMO_ZERO_CHILDREN);
}
Expand Down
Loading