diff --git a/src/context/memory.rs b/src/context/memory.rs index cc83a298b3..82088019c8 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -1,6 +1,6 @@ use alloc::collections::BTreeMap; use alloc::{sync::Arc, vec::Vec}; -use syscall::GrantFlags; +use syscall::{GrantFlags, MunmapFlags}; use core::cmp; use core::fmt::Debug; use core::num::NonZeroUsize; @@ -40,6 +40,7 @@ pub fn map_flags(page_flags: PageFlags) -> MapFlags { pub struct UnmapResult { pub file_desc: Option, pub size: usize, + pub flags: MunmapFlags, } impl UnmapResult { pub fn unmap(mut self) -> Result<()> { @@ -53,7 +54,7 @@ impl UnmapResult { let funmap_result = crate::scheme::schemes() .get(scheme_id).map(Arc::clone).ok_or(Error::new(ENODEV)) - .and_then(|scheme| scheme.kfunmap(number, base_offset, self.size)); + .and_then(|scheme| scheme.kfunmap(number, base_offset, self.size, self.flags)); if let Ok(fd) = Arc::try_unwrap(description) { fd.into_inner().try_close()?; @@ -1070,6 +1071,13 @@ impl Grant { // TODO: Verify deadlock immunity } + let (use_info, require_info, is_fmap_shared) = match self.info.provider { + Provider::Allocated { .. } => (true, true, Some(false)), + Provider::AllocatedShared { .. } => (true, true, None), + Provider::External { .. } => (true, false, None), + Provider::PhysBorrowed { .. } => (false, false, None), + Provider::FmapBorrowed { .. } => (true, false, Some(true)), + }; for page in self.span().pages() { // Lazy mappings do not need to be unmapped. @@ -1078,13 +1086,6 @@ impl Grant { }; let frame = Frame::containing_address(phys); - let (use_info, require_info) = match self.info.provider { - Provider::Allocated { .. } => (true, true), - Provider::AllocatedShared { .. } => (true, true), - Provider::External { .. } => (true, false), - Provider::PhysBorrowed { .. } => (false, false), - Provider::FmapBorrowed { .. } => (true, false), - }; // TODO: use_info IS A HACK! It shouldn't be possible to obtain *any* PhysBorrowed // grants to allocator-owned memory! Replace physalloc/physfree with something like // madvise(range, PHYSICALLY_CONTIGUOUS). @@ -1106,13 +1107,17 @@ impl Grant { // Dummy value, won't be read. let provider = core::mem::replace(&mut self.info.provider, Provider::AllocatedShared { is_pinned_userscheme_borrow: false }); + let mut munmap_flags = MunmapFlags::empty(); + munmap_flags.set(MunmapFlags::NEEDS_SYNC, is_fmap_shared.unwrap_or(false) && self.info.flags.has_write()); + UnmapResult { size: self.info.page_count * PAGE_SIZE, file_desc: match provider { Provider::Allocated { cow_file_ref } => cow_file_ref, Provider::FmapBorrowed { file_ref, .. } => Some(file_ref), _ => None, - } + }, + flags: munmap_flags, } } diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index a9052e4baa..2de767dca8 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -13,7 +13,7 @@ use alloc::{ sync::Arc, vec::Vec, }; -use syscall::CallerCtx; +use syscall::{CallerCtx, MunmapFlags}; use core::sync::atomic::AtomicUsize; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; @@ -311,7 +311,7 @@ pub trait KernelScheme: Scheme + Send + Sync + 'static { fn kfmap(&self, number: usize, addr_space: &Arc>, map: &crate::syscall::data::Map, consume: bool) -> Result { Err(Error::new(EOPNOTSUPP)) } - fn kfunmap(&self, number: usize, offset: usize, size: usize) -> Result<()> { + fn kfunmap(&self, number: usize, offset: usize, size: usize, flags: MunmapFlags) -> Result<()> { Err(Error::new(EOPNOTSUPP)) } diff --git a/src/scheme/user.rs b/src/scheme/user.rs index 159087f14f..b629106ba4 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -2,7 +2,7 @@ use alloc::sync::{Arc, Weak}; use alloc::boxed::Box; use alloc::collections::BTreeMap; use alloc::vec::Vec; -use syscall::{SKMSG_FRETURNFD, CallerCtx, SKMSG_PROVIDE_MMAP, MAP_FIXED_NOREPLACE}; +use syscall::{SKMSG_FRETURNFD, CallerCtx, SKMSG_PROVIDE_MMAP, MAP_FIXED_NOREPLACE, MunmapFlags}; use core::num::NonZeroUsize; use core::sync::atomic::{AtomicBool, Ordering}; use core::{mem, usize}; @@ -834,14 +834,14 @@ impl KernelScheme for UserScheme { inner.fmap_inner(Arc::clone(addr_space), file, map) } - fn kfunmap(&self, number: usize, offset: usize, size: usize) -> Result<()> { + fn kfunmap(&self, number: usize, offset: usize, size: usize, flags: MunmapFlags) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; let res = inner.call_extended(CallerCtx { pid: context::context_id().into(), uid: offset as u32, gid: (offset >> 32) as u32, - }, [KSMSG_MUNMAP, number, size, 0])?; + }, [KSMSG_MUNMAP, number, size, flags.bits()])?; match res { Response::Regular(_) => Ok(()), diff --git a/syscall b/syscall index 534267760f..f0976e1d60 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit 534267760f1388f5577090dc2f5b9443356cb3dc +Subproject commit f0976e1d6020e6854ca30ed1f6d61b10dfc4fa58