VmMapping -> Arc<VmMapping>

This commit is contained in:
PanQL 2020-04-19 17:28:49 +08:00
parent e0ea3b01f9
commit d94d59a51a
4 changed files with 96 additions and 54 deletions

View File

@ -41,7 +41,7 @@ define_count_helper!(VmAddressRegion);
#[derive(Default)]
struct VmarInner {
children: Vec<Arc<VmAddressRegion>>,
mappings: Vec<VmMapping>,
mappings: Vec<Arc<VmMapping>>,
}
impl VmAddressRegion {
@ -127,14 +127,16 @@ impl VmAddressRegion {
let inner = guard.as_mut().ok_or(ZxError::BAD_STATE)?;
let offset = self.determine_offset(inner, vmar_offset, len, PAGE_SIZE)?;
let addr = self.addr + offset;
let mapping = VmMapping {
addr,
size: len,
let mapping = Arc::new(VmMapping {
inner: Arc::new(Mutex::new(VmMappingInner {
addr,
size: len,
vmo_offset,
})),
flags,
vmo,
vmo_offset,
page_table: self.page_table.clone(),
};
});
mapping.map();
inner.mappings.push(mapping);
Ok(addr)
@ -166,7 +168,7 @@ impl VmAddressRegion {
if let Some(new) = map.cut(begin, end) {
new_maps.push(new);
}
map.size == 0
map.size() == 0
});
inner.mappings.extend(new_maps);
for vmar in inner.children.drain_filter(|vmar| vmar.within(begin, end)) {
@ -183,8 +185,8 @@ impl VmAddressRegion {
.mappings
.iter()
.filter_map(|map| {
if map.addr >= addr && map.end_addr() <= end_addr {
Some(map.size)
if map.addr() >= addr && map.end_addr() <= end_addr {
Some(map.size())
} else {
None
}
@ -196,7 +198,7 @@ impl VmAddressRegion {
if inner
.mappings
.iter()
.filter(|map| map.addr >= addr && map.end_addr() <= addr) // get mappings in range: [addr, end_addr]
.filter(|map| map.addr() >= addr && map.end_addr() <= addr) // get mappings in range: [addr, end_addr]
.any(|map| !map.is_valid_mapping_flags(flags))
// check if protect flags is valid
{
@ -205,7 +207,7 @@ impl VmAddressRegion {
inner
.mappings
.iter()
.filter(|map| map.addr >= addr && map.end_addr() <= addr)
.filter(|map| map.addr() >= addr && map.end_addr() <= addr)
.for_each(|map| {
map.protect(flags);
});
@ -373,8 +375,8 @@ impl VmAddressRegion {
let guard = self.inner.lock();
let inner = guard.as_ref().unwrap();
for map in inner.mappings.iter() {
if map.vmo.name().starts_with("vdso") && map.vmo_offset == 0x7000 {
return Some(map.addr);
if map.vmo.name().starts_with("vdso") && map.inner.lock().vmo_offset == 0x7000 {
return Some(map.addr());
}
}
for vmar in inner.children.iter() {
@ -396,7 +398,7 @@ impl VmAddressRegion {
fn used_size(&self) -> usize {
let mut guard = self.inner.lock();
let inner = guard.as_mut().unwrap();
let map_size: usize = inner.mappings.iter().map(|map| map.size).sum();
let map_size: usize = inner.mappings.iter().map(|map| map.size()).sum();
let vmar_size: usize = inner.children.iter().map(|vmar| vmar.size).sum();
map_size + vmar_size
}
@ -411,95 +413,101 @@ pub struct VmarInfo {
/// Virtual Memory Mapping
pub struct VmMapping {
addr: VirtAddr,
size: usize,
flags: MMUFlags,
vmo: Arc<VmObject>,
vmo_offset: usize,
page_table: Arc<Mutex<PageTable>>,
inner: Arc<Mutex<VmMappingInner>>,
}
struct VmMappingInner {
addr: VirtAddr,
size: usize,
vmo_offset: usize,
}
impl core::fmt::Debug for VmMapping {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "addr: {:#x}, size: {:#x}", self.addr, self.size)
write!(f, "addr: {:#x}, size: {:#x}", self.addr(), self.size())
}
}
impl VmMapping {
fn map(&self) {
let mut page_table = self.page_table.lock();
let inner = self.inner.lock();
self.vmo.map_to(
&mut page_table,
self.addr,
self.vmo_offset,
self.size,
inner.addr,
inner.vmo_offset,
inner.size,
self.flags,
);
}
fn unmap(&self) {
let mut page_table = self.page_table.lock();
let inner = self.inner.lock();
self.vmo
.unmap_from(&mut page_table, self.addr, self.vmo_offset, self.size);
.unmap_from(&mut page_table, inner.addr, inner.vmo_offset, inner.size);
}
/// Cut and unmap regions in `[begin, end)`.
///
/// If it will be split, return another one.
fn cut(&mut self, begin: VirtAddr, end: VirtAddr) -> Option<Self> {
fn cut(&self, begin: VirtAddr, end: VirtAddr) -> Option<Arc<Self>> {
if !self.overlap(begin, end) {
return None;
}
if self.addr >= begin && self.end_addr() <= end {
let mut inner = self.inner.lock();
if inner.addr >= begin && inner.end_addr() <= end {
// subset: [xxxxxxxxxx]
self.unmap();
self.size = 0;
inner.size = 0;
None
} else if self.addr >= begin && self.addr < end {
} else if inner.addr >= begin && inner.addr < end {
// prefix: [xxxx------]
let cut_len = end - self.addr;
let cut_len = end - inner.addr;
let mut page_table = self.page_table.lock();
self.vmo
.unmap_from(&mut page_table, self.addr, self.vmo_offset, cut_len);
self.addr = end;
self.size -= cut_len;
self.vmo_offset += cut_len;
.unmap_from(&mut page_table, inner.addr, inner.vmo_offset, cut_len);
inner.addr = end;
inner.size -= cut_len;
inner.vmo_offset += cut_len;
None
} else if self.end_addr() <= end && self.end_addr() > begin {
} else if inner.end_addr() <= end && inner.end_addr() > begin {
// postfix: [------xxxx]
let cut_len = self.end_addr() - begin;
let new_len = begin - self.addr;
let cut_len = inner.end_addr() - begin;
let new_len = begin - inner.addr;
let mut page_table = self.page_table.lock();
self.vmo
.unmap_from(&mut page_table, begin, self.vmo_offset + new_len, cut_len);
self.size = new_len;
.unmap_from(&mut page_table, begin, inner.vmo_offset + new_len, cut_len);
inner.size = new_len;
None
} else {
// superset: [---xxxx---]
let cut_len = end - begin;
let new_len1 = begin - self.addr;
let new_len2 = self.end_addr() - end;
let new_len1 = begin - inner.addr;
let new_len2 = inner.end_addr() - end;
let mut page_table = self.page_table.lock();
self.vmo
.unmap_from(&mut page_table, begin, self.vmo_offset + new_len1, cut_len);
self.size = new_len1;
Some(VmMapping {
addr: end,
size: new_len2,
.unmap_from(&mut page_table, begin, inner.vmo_offset + new_len1, cut_len);
inner.size = new_len1;
Some(Arc::new( VmMapping {
inner: Arc::new(Mutex::new(VmMappingInner {
addr: end,
size: new_len2,
vmo_offset: inner.vmo_offset + (end - inner.addr),
})),
flags: self.flags,
vmo: self.vmo.clone(),
vmo_offset: self.vmo_offset + (end - self.addr),
page_table: self.page_table.clone(),
})
}))
}
}
fn overlap(&self, begin: VirtAddr, end: VirtAddr) -> bool {
!(self.addr >= end || self.end_addr() <= begin)
}
fn end_addr(&self) -> VirtAddr {
self.addr + self.size
let inner = self.inner.lock();
!(inner.addr >= end || inner.end_addr() <= begin)
}
pub fn is_valid_mapping_flags(&self, flags: MMUFlags) -> bool {
@ -517,10 +525,29 @@ impl VmMapping {
pub fn protect(&self, flags: MMUFlags) {
let mut pg_table = self.page_table.lock();
for i in 0..self.size {
pg_table.protect(self.addr + i * PAGE_SIZE, flags).unwrap();
let inner = self.inner.lock();
for i in 0..inner.size {
pg_table.protect(inner.addr + i * PAGE_SIZE, flags).unwrap();
}
}
fn size(&self) -> usize {
self.inner.lock().size
}
fn addr(&self) -> VirtAddr {
self.inner.lock().addr
}
fn end_addr(&self) -> VirtAddr {
self.inner.lock().end_addr()
}
}
impl VmMappingInner {
fn end_addr(&self) -> VirtAddr {
self.addr + self.size
}
}
impl Drop for VmMapping {

View File

@ -92,6 +92,14 @@ impl VmObject {
inner: self.inner.create_clone(offset, len),
})
}
pub fn create_child(&self, offset: usize, len: usize) -> Arc<Self> {
Arc::new(VmObject {
base: KObjectBase::default(),
_counter: CountHelper::new(),
inner: self.inner.create_child(offset, len),
})
}
}
impl Deref for VmObject {

View File

@ -13,11 +13,13 @@ pub struct VMObjectPaged {
inner: Mutex<VMObjectPagedInner>,
}
#[allow(dead_code)]
/// The mutable part of `VMObjectPaged`.
struct VMObjectPagedInner {
parent: Option<Arc<VMObjectPaged>>,
parent_offset: usize,
frames: Vec<Option<PhysFrame>>,
mappings: Vec<Arc<VmMapping>>,
}
impl VMObjectPaged {
@ -31,6 +33,7 @@ impl VMObjectPaged {
parent: None,
parent_offset: 0usize,
frames,
mappings: Vec::new(),
}),
})
}
@ -169,13 +172,15 @@ impl VMObjectTrait for VMObjectPaged {
let hidden_vmo = Arc::new(VMObjectPaged {
inner: Mutex::new(VMObjectPagedInner {
parent: old_parent,
parent_offset: 0usize,
parent_offset: inner.parent_offset,
frames,
mappings: Vec::new(),
}),
});
// change current vmo's parent
inner.parent = Some(hidden_vmo.clone());
inner.parent_offset = 0usize;
inner.frames.resize_with(pages, Default::default);
// create hidden_vmo's another child as result
@ -186,6 +191,7 @@ impl VMObjectTrait for VMObjectPaged {
parent: Some(hidden_vmo),
parent_offset: offset,
frames: child_frames,
mappings: Vec::new(),
}),
})
}
@ -211,6 +217,7 @@ impl VMObjectTrait for VMObjectPaged {
parent: None,
parent_offset: offset,
frames,
mappings: Vec::new(),
}),
})
}

View File

@ -131,7 +131,7 @@ impl Syscall<'_> {
let child_size = roundup_pages(size);
info!("size of child vmo: {:#x}", child_size);
let child_vmo = vmo.create_clone(offset as usize, child_size);
let child_vmo = vmo.create_child(offset as usize, child_size);
out.write(proc.add_handle(Handle::new(child_vmo, child_rights)))?;
Ok(())
}