diff --git a/Cargo.lock b/Cargo.lock index 04a30d298a..759e5cb468 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "byteorder" version = "1.4.3" @@ -104,7 +110,7 @@ name = "kernel" version = "0.4.1" dependencies = [ "bitfield", - "bitflags", + "bitflags 1.3.2", "byteorder", "cc", "fdt", @@ -209,14 +215,14 @@ version = "10.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6aa2540135b6a94f74c7bc90ad4b794f822026a894f3d7bcd185c100d13d4ad6" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "redox_syscall" version = "0.4.1" dependencies = [ - "bitflags", + "bitflags 2.4.1", ] [[package]] @@ -387,7 +393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55b5be8cc34d017d8aabec95bc45a43d0f20e8b2a31a453cabc804fe996f8dca" dependencies = [ "bit_field", - "bitflags", + "bitflags 1.3.2", "raw-cpuid", ] diff --git a/src/context/memory.rs b/src/context/memory.rs index 8c4a83060c..8ea5c41aea 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -777,6 +777,30 @@ impl Grant { }, }) } + pub fn zeroed_phys_contiguous(span: PageSpan, flags: PageFlags, mapper: &mut PageMapper, mut flusher: impl Flusher) -> Result { + let base = crate::memory::allocate_frames(span.count).ok_or(Enomem)?; + + for (i, page) in span.pages().enumerate() { + let frame = base.next_by(i); + + get_page_info(base).expect("PageInfo must exist for allocated frame").refcount.store(RefCount::One.to_raw(), Ordering::Relaxed); + + unsafe { + let result = mapper.map_phys(page.start_address(), frame.start_address(), flags).expect("TODO: page table OOM"); + flusher.consume(result); + } + } + + Ok(Grant { + base: span.base, + info: GrantInfo { + page_count: span.count, + flags, + mapped: true, + provider: Provider::Allocated { cow_file_ref: None }, + }, + }) + } pub fn zeroed(span: PageSpan, flags: PageFlags, mapper: &mut PageMapper, mut flusher: impl Flusher, shared: bool) -> Result { const MAX_EAGER_PAGES: usize = 16; diff --git a/src/scheme/memory.rs b/src/scheme/memory.rs index d3f8abb013..bf9ac68cd9 100644 --- a/src/scheme/memory.rs +++ b/src/scheme/memory.rs @@ -23,7 +23,8 @@ pub struct MemoryScheme; // TODO: Use crate that autogenerates conversion functions. #[repr(u8)] enum Handle { - Anonymous = 0, + Zeroed = 0, + ZeroedPhysContiguous = 4, PhysicalWb = 1, PhysicalUc = 2, @@ -42,7 +43,8 @@ pub enum MemoryType { impl Handle { fn from_raw(raw: usize) -> Option { Some(match raw { - 0 => Self::Anonymous, + 0 => Self::Zeroed, + 4 => Self::ZeroedPhysContiguous, 1 => Self::PhysicalWb, 2 => Self::PhysicalUc, @@ -55,16 +57,26 @@ impl Handle { } impl MemoryScheme { - pub fn fmap_anonymous(addr_space: &Arc>, map: &Map) -> Result { + pub fn fmap_anonymous(addr_space: &Arc>, map: &Map, is_phys_contiguous: bool) -> Result { let span = PageSpan::validate_nonempty(VirtualAddress::new(map.address), map.size).ok_or(Error::new(EINVAL))?; let page_count = NonZeroUsize::new(span.count).ok_or(Error::new(EINVAL))?; let mut notify_files = Vec::new(); + if is_phys_contiguous && map.flags.contains(MapFlags::MAP_SHARED) { + // TODO: Should this be supported? + return Err(Error::new(EOPNOTSUPP)); + } + let page = addr_space .write() .mmap((map.address != 0).then_some(span.base), page_count, map.flags, &mut notify_files, |dst_page, flags, mapper, flusher| { - Ok(Grant::zeroed(PageSpan::new(dst_page, page_count.get()), flags, mapper, flusher, map.flags.contains(MapFlags::MAP_SHARED))?) + let span = PageSpan::new(dst_page, page_count.get()); + if is_phys_contiguous { + Ok(Grant::zeroed_phys_contiguous(span, flags, mapper, flusher)?) + } else { + Ok(Grant::zeroed(span, flags, mapper, flusher, map.flags.contains(MapFlags::MAP_SHARED))?) + } })?; handle_notify_files(notify_files); @@ -121,7 +133,8 @@ impl MemoryScheme { impl KernelScheme for MemoryScheme { fn kopen(&self, path: &str, _flags: usize, ctx: CallerCtx) -> Result { let intended_handle = match path.trim_start_matches('/') { - "" => Handle::Anonymous, + "" | "zeroed" => Handle::Zeroed, + "zeroed_phys_contiguous" => Handle::ZeroedPhysContiguous, "physical" | "physical@wb" => Handle::PhysicalWb, "physical@uc" => Handle::PhysicalUc, "physical@wc" => Handle::PhysicalWc, @@ -130,7 +143,7 @@ impl KernelScheme for MemoryScheme { _ => return Err(Error::new(ENOENT)), }; - if ctx.uid != 0 && !matches!(intended_handle, Handle::Anonymous) { + if ctx.uid != 0 && !matches!(intended_handle, Handle::Zeroed) { return Err(Error::new(EACCES)); } @@ -146,7 +159,8 @@ impl KernelScheme for MemoryScheme { } fn kfmap(&self, id: usize, addr_space: &Arc>, map: &Map, _consume: bool) -> Result { match Handle::from_raw(id).ok_or(Error::new(EBADF))? { - Handle::Anonymous => Self::fmap_anonymous(addr_space, map), + Handle::Zeroed => Self::fmap_anonymous(addr_space, map, false), + Handle::ZeroedPhysContiguous => Self::fmap_anonymous(addr_space, map, true), Handle::PhysicalWb => Self::physmap(map.offset, map.size, map.flags, MemoryType::Writeback), Handle::PhysicalUc => Self::physmap(map.offset, map.size, map.flags, MemoryType::Uncacheable), Handle::PhysicalWc => Self::physmap(map.offset, map.size, map.flags, MemoryType::WriteCombining), @@ -156,7 +170,8 @@ impl KernelScheme for MemoryScheme { fn kfpath(&self, id: usize, dst: UserSliceWo) -> Result { // TODO: Copy scheme name elsewhere in the kernel? let src = match Handle::from_raw(id).ok_or(Error::new(EBADF))? { - Handle::Anonymous => "memory:", + Handle::Zeroed => "memory:zeroed", + Handle::ZeroedPhysContiguous => "memory:zeroed_phys_contiguous", Handle::PhysicalWb => "memory:physical@wb", Handle::PhysicalUc => "memory:physical@uc", Handle::PhysicalWc => "memory:physical@wc", diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 28d400aa1d..5f670ccdbf 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -77,7 +77,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack let addrspace = AddrSpace::current()?; let map = unsafe { UserSlice::ro(c, d)?.read_exact::()? }; if b == !0 { - MemoryScheme::fmap_anonymous(&addrspace, &map) + MemoryScheme::fmap_anonymous(&addrspace, &map, false) } else { file_op_generic(fd, |scheme, _, number| scheme.kfmap(number, &addrspace, &map, false)) }