diff --git a/services/libs/jinux-std/src/process/process_vm/mmap_flags.rs b/services/libs/jinux-std/src/process/process_vm/mmap_flags.rs index 3c95269df..d2224f192 100644 --- a/services/libs/jinux-std/src/process/process_vm/mmap_flags.rs +++ b/services/libs/jinux-std/src/process/process_vm/mmap_flags.rs @@ -1,13 +1,25 @@ +//! Definition of MMap flags, conforming to the linux mmap interface: +//! https://man7.org/linux/man-pages/man2/mmap.2.html +//! +//! The first 4 bits of the flag value represents the type of memory map, +//! while other bits are used as memory map flags. +//! + use crate::prelude::*; -// The definition of MMapFlags is from occlum +// The map type mask +const MAP_TYPE: u32 = 0xf; + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum MMapType { + MapFile = 0x0, + MapShared = 0x1, + MapPrivate = 0x2, + MapSharedValidate = 0x3, +} + bitflags! { pub struct MMapFlags : u32 { - const MAP_FILE = 0x0; - const MAP_SHARED = 0x1; - const MAP_PRIVATE = 0x2; - const MAP_SHARED_VALIDATE = 0x3; - const MAP_TYPE = 0xf; const MAP_FIXED = 0x10; const MAP_ANONYMOUS = 0x20; const MAP_GROWSDOWN = 0x100; @@ -24,11 +36,42 @@ bitflags! { } } -impl TryFrom for MMapFlags { +#[derive(Debug)] +pub struct MMapOption { + typ: MMapType, + flags: MMapFlags, +} + +impl TryFrom for MMapOption { type Error = Error; fn try_from(value: u64) -> Result { - MMapFlags::from_bits(value as u32) - .ok_or_else(|| Error::with_message(Errno::EINVAL, "unknown mmap flags")) + let typ_raw = value as u32 & MAP_TYPE; + let flags_raw = value as u32 & !MAP_TYPE; + let typ = match typ_raw { + 0x0 => MMapType::MapFile, + 0x1 => MMapType::MapShared, + 0x2 => MMapType::MapPrivate, + 0x3 => MMapType::MapSharedValidate, + _ => return Err(Error::with_message(Errno::EINVAL, "unknown mmap flags")), + }; + if let Some(flags) = MMapFlags::from_bits(flags_raw) { + Ok(MMapOption { + typ: typ, + flags: flags, + }) + } else { + Err(Error::with_message(Errno::EINVAL, "unknown mmap flags")) + } + } +} + +impl MMapOption { + pub fn typ(&self) -> MMapType { + self.typ + } + + pub fn flags(&self) -> MMapFlags { + self.flags } } diff --git a/services/libs/jinux-std/src/syscall/mmap.rs b/services/libs/jinux-std/src/syscall/mmap.rs index 790324f65..8ced8b4aa 100644 --- a/services/libs/jinux-std/src/syscall/mmap.rs +++ b/services/libs/jinux-std/src/syscall/mmap.rs @@ -1,7 +1,7 @@ //! This mod defines mmap flags and the handler to syscall mmap use crate::fs::file_table::FileDescripter; -use crate::process::process_vm::mmap_flags::MMapFlags; +use crate::process::process_vm::mmap_flags::{MMapFlags, MMapOption, MMapType}; use crate::vm::perms::VmPerms; use crate::vm::vmo::{VmoChildOptions, VmoOptions, VmoRightsOp}; use crate::{log_syscall_entry, prelude::*}; @@ -23,12 +23,12 @@ pub fn sys_mmap( ) -> Result { log_syscall_entry!(SYS_MMAP); let perms = VmPerm::try_from(perms).unwrap(); - let flags = MMapFlags::try_from(flags).unwrap(); + let option = MMapOption::try_from(flags).unwrap(); let res = do_sys_mmap( addr as usize, len as usize, perms, - flags, + option, fd as _, offset as usize, )?; @@ -39,13 +39,13 @@ pub fn do_sys_mmap( addr: Vaddr, len: usize, vm_perm: VmPerm, - flags: MMapFlags, + option: MMapOption, fd: FileDescripter, offset: usize, ) -> Result { debug!( - "addr = 0x{:x}, len = 0x{:x}, perms = {:?}, flags = {:?}, fd = {}, offset = 0x{:x}", - addr, len, vm_perm, flags, fd, offset + "addr = 0x{:x}, len = 0x{:x}, perms = {:?}, option = {:?}, fd = {}, offset = 0x{:x}", + addr, len, vm_perm, option, fd, offset ); let len = len.align_up(PAGE_SIZE); @@ -55,11 +55,10 @@ pub fn do_sys_mmap( } let perms = VmPerms::from(vm_perm); - if flags.contains(MMapFlags::MAP_ANONYMOUS) { - // only support map anonymous areas. - mmap_anonymous_vmo(addr, len, offset, perms, flags) + if option.flags().contains(MMapFlags::MAP_ANONYMOUS) { + mmap_anonymous_vmo(addr, len, offset, perms, option) } else { - mmap_filebacked_vmo(addr, fd, len, offset, perms, flags) + mmap_filebacked_vmo(addr, fd, len, offset, perms, option) } } @@ -68,23 +67,23 @@ fn mmap_anonymous_vmo( len: usize, offset: usize, perms: VmPerms, - flags: MMapFlags, + option: MMapOption, ) -> Result { - // TODO: how to respect flags? - if flags.complement().contains(MMapFlags::MAP_ANONYMOUS) - | flags.complement().contains(MMapFlags::MAP_PRIVATE) - { - panic!("Unsupported mmap flags {:?} now", flags); - } + assert!(option.flags().contains(MMapFlags::MAP_ANONYMOUS)); debug_assert!(offset == 0); + // TODO: implement features presented by other flags. + if option.typ() != MMapType::MapPrivate { + panic!("Unsupported mmap flags {:?} now", option); + } + let vmo_options: VmoOptions = VmoOptions::new(len); let vmo = vmo_options.alloc()?; let current = current!(); let root_vmar = current.root_vmar(); let mut vmar_map_options = root_vmar.new_map(vmo, perms)?; - if flags.contains(MMapFlags::MAP_FIXED) { + if option.flags().contains(MMapFlags::MAP_FIXED) { vmar_map_options = vmar_map_options.offset(addr).can_overwrite(true); } let map_addr = vmar_map_options.build()?; @@ -98,7 +97,7 @@ fn mmap_filebacked_vmo( len: usize, offset: usize, perms: VmPerms, - flags: MMapFlags, + option: MMapOption, ) -> Result { let current = current!(); let page_cache_vmo = { @@ -111,7 +110,7 @@ fn mmap_filebacked_vmo( ))? }; - let vmo = if flags.contains(MMapFlags::MAP_PRIVATE) { + let vmo = if option.typ() == MMapType::MapPrivate { // map private VmoChildOptions::new_cow(page_cache_vmo, offset..(offset + len)).alloc()? } else { @@ -123,7 +122,7 @@ fn mmap_filebacked_vmo( let root_vmar = current.root_vmar(); let vm_map_options = { let mut options = root_vmar.new_map(vmo.to_dyn(), perms)?; - if flags.contains(MMapFlags::MAP_FIXED) { + if option.flags().contains(MMapFlags::MAP_FIXED) { options = options.offset(addr).can_overwrite(true); } options