Support schemes.

This commit is contained in:
4lDO2
2023-06-22 17:20:56 +02:00
parent f53a1ffd53
commit 593e21d95e
3 changed files with 57 additions and 27 deletions
+53 -18
View File
@@ -205,11 +205,16 @@ impl AddrSpace {
}
}
pub fn mmap(&mut self, page: Option<Page>, page_count: NonZeroUsize, flags: MapFlags, map: impl FnOnce(Page, PageFlags<RmmA>, &mut PageMapper, &mut dyn Flusher<RmmA>) -> Result<Grant>) -> Result<Page> {
self.mmap_multiple(page, page_count, flags, move |page, flags, mapper, flusher| Ok(Some(map(page, flags, mapper, flusher)?)))
}
pub fn mmap_multiple<I: IntoIterator<Item = Grant>>(&mut self, page: Option<Page>, page_count: NonZeroUsize, flags: MapFlags, map: impl FnOnce(Page, PageFlags<RmmA>, &mut PageMapper, &mut dyn Flusher<RmmA>) -> Result<I>) -> Result<Page> {
// Finally, the end of all "T0DO: Abstract with other grant creation"!
let selected_span = self.grants.find_free_at(self.mmap_min, page, page_count.get(), flags)?;
// TODO: Threads share address spaces, so not only the inactive flusher should be sending
// out IPIs.
// out IPIs. IPIs will only be sent when downgrading mappings (i.e. when a stale TLB entry
// will not be corrected by a page fault), and will furthermore require proper
// synchronization.
let (mut active, mut inactive);
let flusher = if self.is_current() {
active = PageFlushAll::new();
@@ -219,7 +224,10 @@ impl AddrSpace {
&mut inactive as &mut dyn Flusher<RmmA>
};
self.grants.insert(map(selected_span.base, page_flags(flags), &mut self.table.utable, flusher)?);
let iter = map(selected_span.base, page_flags(flags), &mut self.table.utable, flusher)?;
for grant in iter {
self.grants.insert(grant);
}
Ok(selected_span.base)
}
@@ -401,6 +409,7 @@ impl UserGrants {
return Err(Error::new(EEXIST));
}
if flags.contains(MapFlags::MAP_FIXED) {
// TODO: find_free_at -> Result<(PageSpan, needs_to_unmap: PageSpan)>
return Err(Error::new(EOPNOTSUPP));
} else {
// TODO: Find grant close to requested address?
@@ -703,7 +712,13 @@ impl Grant {
})
}
// TODO: Return multiple grants.
// TODO: Do not return Vec, return an iterator perhaps? Referencing the source address space?
/// Borrow all pages in the range `[src_base, src_base+page_count)` from `src_address_space`,
/// mapping them into `[dst_base, dst_base+page_count)`. While the pages are borrowed,
/// subsequent mappings/mprotects/etc. will not be visible in the destination address space;
/// the *pages present at that time* are borrowed, rather than the source range permanently, by
/// reference.
pub fn borrow(
src_address_space_lock: Arc<RwLock<AddrSpace>>,
src_address_space: &AddrSpace,
@@ -714,7 +729,7 @@ impl Grant {
dst_mapper: &mut PageMapper,
dst_flusher: impl Flusher<RmmA>,
eager: bool,
) -> Result<Grant, Enomem> {
) -> Result<Vec<Grant>, Enomem> {
/*
if eager {
for page in PageSpan::new(src_base, page_count) {
@@ -723,20 +738,40 @@ impl Grant {
}
*/
Ok(Grant {
base: dst_base,
info: GrantInfo {
page_count,
flags,
mapped: true,
provider: Provider::External {
src_base,
address_space: src_address_space_lock,
cow: false,
pages: None,
}
},
})
let mut dst_grants = Vec::with_capacity(1);
let src_span = PageSpan::new(src_base, page_count);
for (src_base, src_grant) in src_address_space.grants.conflicts(src_span) {
let grant_span = PageSpan::new(src_base, src_grant.page_count);
let common_span = src_span.intersection(grant_span);
let offset_from_src_base = common_span.base.offset_from(src_base);
dst_grants.push(Grant {
base: dst_base.next_by(offset_from_src_base),
info: GrantInfo {
page_count: common_span.count,
flags,
mapped: true,
provider: match src_grant.provider {
Provider::Allocated { ref pages } => Provider::External {
src_base,
address_space: Arc::clone(&src_address_space_lock),
cow: false,
pages: None,
},
Provider::PhysBorrowed { base: src_phys_base } => Provider::PhysBorrowed {
base: src_phys_base.next_by(offset_from_src_base),
},
Provider::Fmap { .. } => todo!(),
Provider::External { ref address_space, src_base, cow, ref pages } => Provider::External { address_space: Arc::clone(address_space), src_base, cow, pages: pages.as_ref().map(|pages| pages.iter().map(|pg| pg.as_ref().map(|pg| pg.ref_clone(false))).collect::<Vec<_>>().into()) },
}
},
});
}
Ok(dst_grants)
}
// TODO: This is limited to one page. Should it be (if some magic new proc: API is introduced)?
pub fn cow(
+3 -8
View File
@@ -687,9 +687,6 @@ impl KernelScheme for ProcScheme {
if Arc::ptr_eq(addrspace, dst_addr_space) {
return Err(Error::new(EBUSY));
}
/*
// Limit to transferring/borrowing at most one grant, or part of a grant (splitting
// will be mandatory if grants are coalesced).
let (requested_dst_page, page_count) = crate::syscall::validate_region(map.address, map.size)?;
let (src_page, _) = crate::syscall::validate_region(map.offset, map.size)?;
@@ -718,7 +715,7 @@ impl KernelScheme for ProcScheme {
let src_mapper = &mut src_addr_space.table.utable;
let src_page_count = NonZeroUsize::new(src_grant_span.count).ok_or(Error::new(EINVAL))?;
let result_page = if consume {
let result_base = if consume {
let grant = src_addr_space.grants.remove(src_grant_span.base).expect("grant cannot disappear");
let (before, middle, after) = grant.extract(src_grant_span).expect("called intersect(), must succeed");
@@ -727,12 +724,10 @@ impl KernelScheme for ProcScheme {
dst_addr_space.mmap(requested_dst_page, src_page_count, map.flags, |dst_page, _flags, dst_mapper, dst_flusher| Grant::transfer(middle, dst_page, src_mapper, dst_mapper, InactiveFlusher::new(), dst_flusher))?
} else {
dst_addr_space.mmap(requested_dst_page, src_page_count, map.flags, |dst_page, flags, dst_mapper, flusher| Ok(Grant::borrow(src_grant_span.base, dst_page, src_grant_span.count, flags, None, src_mapper, dst_mapper, flusher)?))?
dst_addr_space.mmap_multiple(requested_dst_page, src_page_count, map.flags, |dst_page, flags, dst_mapper, flusher| Ok(Grant::borrow(Arc::clone(addrspace), src_addr_space, src_grant_span.base, dst_page, src_grant_span.count, flags, dst_mapper, flusher, true)?))?
};
*/
//Ok(result_page.start_address().data())
todo!()
Ok(result_base.start_address().data())
}
_ => Err(Error::new(EBADF)),
}
+1 -1
View File
@@ -261,7 +261,7 @@ impl UserInner {
let (_middle_part_of_buf, tail_part_of_buf) = middle_tail_part_of_buf.split_at(middle_page_count * PAGE_SIZE).expect("split must succeed");
if let Some(middle_page_count) = NonZeroUsize::new(middle_page_count) {
dst_space.mmap(Some(first_middle_dst_page), middle_page_count, map_flags, move |dst_page, page_flags, mapper, flusher| {
dst_space.mmap_multiple(Some(first_middle_dst_page), middle_page_count, map_flags, move |dst_page, page_flags, mapper, flusher| {
Ok(Grant::borrow(Arc::clone(&cur_space_lock), &mut *cur_space_lock.write(), first_middle_src_page, dst_page, middle_page_count.get(), page_flags, mapper, flusher, true)?)
})?;
}