diff --git a/Cargo.lock b/Cargo.lock index 32ff40ab7532ee9e58e4fbb12eae07f931566f2b..d2097dc850342c701930a1c5369d20b3db5d7ec5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ahash" @@ -233,8 +233,8 @@ checksum = "64072665120942deff5fd5425d6c1811b854f4939e7f1c01ce755f64432bbea7" [[package]] name = "redox_syscall" -version = "0.5.7" -source = "git+https://gitlab.redox-os.org/redox-os/syscall.git?branch=master#f3fc45a1b74debc4a188276640fdfb8be47ccc25" +version = "0.5.8" +source = "git+https://gitlab.redox-os.org/redox-os/syscall.git?branch=master#3d786423f1d9c71d408bc3c9a64648b883aaf36b" dependencies = [ "bitflags 2.6.0", ] diff --git a/src/context/memory.rs b/src/context/memory.rs index 615b610801d6fcfe849364c52133967d8ddfd510..890eb5b21e7a960cafa389decea4963491c5b480 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -1102,6 +1102,22 @@ pub struct GrantFileRef { impl Grant { // TODO: PageCount newtype, to avoid confusion between bytes and pages? + // `base` must be mapped by the caller. + pub fn allocated_one_page_nomap(base: Page, flags: PageFlags<RmmA>) -> Grant { + Grant { + base, + info: GrantInfo { + page_count: 1, + flags, + mapped: true, + provider: Provider::Allocated { + cow_file_ref: None, + phys_contiguous: false, + }, + }, + } + } + // TODO: is_pinned pub fn allocated_shared_one_page( frame: Frame, diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 0ab2b16052c02ceb8632c169a1498369b16d01b6..bf294ed4aebd661874eea3f462b584bf27f1c13c 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -370,6 +370,11 @@ impl RaiiFrame { pub fn get(&self) -> Frame { self.inner } + pub fn take(self) -> Frame { + let f = self.get(); + core::mem::forget(self); + f + } } impl Drop for RaiiFrame { diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index 43fbdbc2349e9ac01135ede43def75aab1ab6c9b..62f0753c29d860b20b06785a003c95df5f0a9fd6 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -1,4 +1,6 @@ //! Filesystem syscalls +use core::num::NonZeroUsize; + use alloc::{sync::Arc, vec::Vec}; use redox_path::RedoxPath; use spin::RwLock; @@ -7,7 +9,7 @@ use crate::{ context::{ self, file::{FileDescription, FileDescriptor, InternalFlags}, - memory::{AddrSpace, PageSpan}, + memory::{AddrSpace, GenericFlusher, Grant, PageSpan, TlbShootdownActions}, process, }, paging::{Page, VirtualAddress, PAGE_SIZE}, @@ -491,16 +493,51 @@ pub fn mremap( let new_page_count = new_size.div_ceil(PAGE_SIZE); let requested_dst_base = Some(new_base).filter(|_| new_address != 0); - let base = addr_space.r#move( - None, - src_span, - requested_dst_base, - new_page_count, - map_flags, - &mut Vec::new(), - )?; + if mremap_flags.contains(MremapFlags::KEEP_OLD) { + // TODO: This is a hack! Find a better interface for replacing this, perhaps a capability + // for non-CoW-borrowed i.e. owned frames, that can be inserted into address spaces. + if new_page_count != 1 { + return Err(Error::new(EOPNOTSUPP)); + } + + let raii_frame = addr_space.borrow_frame_enforce_rw_allocated(src_span.base)?; + + let base = addr_space.acquire_write().mmap( + &addr_space, + requested_dst_base, + NonZeroUsize::new(1).unwrap(), + map_flags, + &mut Vec::new(), + |page, page_flags, mapper, flusher| { + let frame = raii_frame.take(); + // XXX: add_ref(RefKind::Shared) is internally done by borrow_frame_enforce_rw_allocated(src_span.base). + // The page does not get unref-ed as we call take() on the `raii_frame`. + unsafe { + mapper + .map_phys(page.start_address(), frame.base(), page_flags) + .ok_or(Error::new(ENOMEM))? + .ignore(); + + flusher.queue(frame, None, TlbShootdownActions::NEW_MAPPING); + } + + Ok(Grant::allocated_one_page_nomap(page, page_flags)) + }, + )?; - Ok(base.start_address().data()) + Ok(base.start_address().data()) + } else { + let base = addr_space.r#move( + None, + src_span, + requested_dst_base, + new_page_count, + map_flags, + &mut Vec::new(), + )?; + + Ok(base.start_address().data()) + } } pub fn lseek(fd: FileHandle, pos: i64, whence: usize) -> Result<usize> {