Fix mmap flags

This commit is contained in:
Zhang Junyang
2023-08-02 15:11:12 +08:00
committed by Tate, Hongliang Tian
parent 901cbebe44
commit 6b87ff03ac
2 changed files with 72 additions and 30 deletions

View File

@ -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::*; 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! { bitflags! {
pub struct MMapFlags : u32 { 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_FIXED = 0x10;
const MAP_ANONYMOUS = 0x20; const MAP_ANONYMOUS = 0x20;
const MAP_GROWSDOWN = 0x100; const MAP_GROWSDOWN = 0x100;
@ -24,11 +36,42 @@ bitflags! {
} }
} }
impl TryFrom<u64> for MMapFlags { #[derive(Debug)]
pub struct MMapOption {
typ: MMapType,
flags: MMapFlags,
}
impl TryFrom<u64> for MMapOption {
type Error = Error; type Error = Error;
fn try_from(value: u64) -> Result<Self> { fn try_from(value: u64) -> Result<Self> {
MMapFlags::from_bits(value as u32) let typ_raw = value as u32 & MAP_TYPE;
.ok_or_else(|| Error::with_message(Errno::EINVAL, "unknown mmap flags")) 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
} }
} }

View File

@ -1,7 +1,7 @@
//! This mod defines mmap flags and the handler to syscall mmap //! This mod defines mmap flags and the handler to syscall mmap
use crate::fs::file_table::FileDescripter; 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::perms::VmPerms;
use crate::vm::vmo::{VmoChildOptions, VmoOptions, VmoRightsOp}; use crate::vm::vmo::{VmoChildOptions, VmoOptions, VmoRightsOp};
use crate::{log_syscall_entry, prelude::*}; use crate::{log_syscall_entry, prelude::*};
@ -23,12 +23,12 @@ pub fn sys_mmap(
) -> Result<SyscallReturn> { ) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_MMAP); log_syscall_entry!(SYS_MMAP);
let perms = VmPerm::try_from(perms).unwrap(); 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( let res = do_sys_mmap(
addr as usize, addr as usize,
len as usize, len as usize,
perms, perms,
flags, option,
fd as _, fd as _,
offset as usize, offset as usize,
)?; )?;
@ -39,13 +39,13 @@ pub fn do_sys_mmap(
addr: Vaddr, addr: Vaddr,
len: usize, len: usize,
vm_perm: VmPerm, vm_perm: VmPerm,
flags: MMapFlags, option: MMapOption,
fd: FileDescripter, fd: FileDescripter,
offset: usize, offset: usize,
) -> Result<Vaddr> { ) -> Result<Vaddr> {
debug!( debug!(
"addr = 0x{:x}, len = 0x{:x}, perms = {:?}, flags = {:?}, fd = {}, offset = 0x{:x}", "addr = 0x{:x}, len = 0x{:x}, perms = {:?}, option = {:?}, fd = {}, offset = 0x{:x}",
addr, len, vm_perm, flags, fd, offset addr, len, vm_perm, option, fd, offset
); );
let len = len.align_up(PAGE_SIZE); let len = len.align_up(PAGE_SIZE);
@ -55,11 +55,10 @@ pub fn do_sys_mmap(
} }
let perms = VmPerms::from(vm_perm); let perms = VmPerms::from(vm_perm);
if flags.contains(MMapFlags::MAP_ANONYMOUS) { if option.flags().contains(MMapFlags::MAP_ANONYMOUS) {
// only support map anonymous areas. mmap_anonymous_vmo(addr, len, offset, perms, option)
mmap_anonymous_vmo(addr, len, offset, perms, flags)
} else { } 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, len: usize,
offset: usize, offset: usize,
perms: VmPerms, perms: VmPerms,
flags: MMapFlags, option: MMapOption,
) -> Result<Vaddr> { ) -> Result<Vaddr> {
// TODO: how to respect flags? assert!(option.flags().contains(MMapFlags::MAP_ANONYMOUS));
if flags.complement().contains(MMapFlags::MAP_ANONYMOUS)
| flags.complement().contains(MMapFlags::MAP_PRIVATE)
{
panic!("Unsupported mmap flags {:?} now", flags);
}
debug_assert!(offset == 0); 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<Rights> = VmoOptions::new(len); let vmo_options: VmoOptions<Rights> = VmoOptions::new(len);
let vmo = vmo_options.alloc()?; let vmo = vmo_options.alloc()?;
let current = current!(); let current = current!();
let root_vmar = current.root_vmar(); let root_vmar = current.root_vmar();
let mut vmar_map_options = root_vmar.new_map(vmo, perms)?; 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); vmar_map_options = vmar_map_options.offset(addr).can_overwrite(true);
} }
let map_addr = vmar_map_options.build()?; let map_addr = vmar_map_options.build()?;
@ -98,7 +97,7 @@ fn mmap_filebacked_vmo(
len: usize, len: usize,
offset: usize, offset: usize,
perms: VmPerms, perms: VmPerms,
flags: MMapFlags, option: MMapOption,
) -> Result<Vaddr> { ) -> Result<Vaddr> {
let current = current!(); let current = current!();
let page_cache_vmo = { 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 // map private
VmoChildOptions::new_cow(page_cache_vmo, offset..(offset + len)).alloc()? VmoChildOptions::new_cow(page_cache_vmo, offset..(offset + len)).alloc()?
} else { } else {
@ -123,7 +122,7 @@ fn mmap_filebacked_vmo(
let root_vmar = current.root_vmar(); let root_vmar = current.root_vmar();
let vm_map_options = { let vm_map_options = {
let mut options = root_vmar.new_map(vmo.to_dyn(), perms)?; 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 = options.offset(addr).can_overwrite(true);
} }
options options