From ea00690e682ab7d8abca2b9a006101ae8bee795e Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Sat, 15 Dec 2018 23:44:00 +0800 Subject: [PATCH] Add mmap, munmap, mremap and brk syscalls --- src/libos/include/syscall.h | 7 +++ src/libos/src/syscall.rs | 78 +++++++++++++++++++++++++++++++++- src/libos/src/syscall_entry.c | 33 +++++++++++++- src/libos/src/vm/mod.rs | 40 ++++++++++++++++- src/libos/src/vm/process_vm.rs | 1 + test/Makefile | 2 +- test/malloc/Makefile | 4 ++ test/malloc/main.c | 16 +++++++ 8 files changed, 176 insertions(+), 5 deletions(-) create mode 100644 test/malloc/Makefile create mode 100644 test/malloc/main.c diff --git a/src/libos/include/syscall.h b/src/libos/include/syscall.h index 2f7d8458..01f1eb81 100644 --- a/src/libos/include/syscall.h +++ b/src/libos/include/syscall.h @@ -17,12 +17,19 @@ extern ssize_t occlum_write(int fd, const void* buf, size_t size); extern ssize_t occlum_readv(int fd, struct iovec* iov, int count); extern ssize_t occlum_writev(int fd, const struct iovec* iov, int count); extern off_t occlum_lseek(int fd, off_t offset, int whence); + extern int occlum_spawn(int* child_pid, const char* path, const char** argv, const char** envp); extern int occlum_wait4(int child_pid, int* status, int options/*, struct rusage* rusage*/); extern unsigned int occlum_getpid(void); extern void occlum_exit(int status); + +extern void *occlum_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); +extern int occlum_munmap(void *addr, size_t length); +extern void *occlum_mremap(void *old_address, size_t old_size, size_t new_size, int flags, void *new_address); +extern void* occlum_brk(void* addr); + extern int occlum_unknown(int num); #ifdef __cplusplus diff --git a/src/libos/src/syscall.rs b/src/libos/src/syscall.rs index 018ba4e1..4f155b55 100644 --- a/src/libos/src/syscall.rs +++ b/src/libos/src/syscall.rs @@ -1,6 +1,8 @@ use prelude::*; -use {std, file, file_table, fs, process}; +use {std, file, file_table, fs, process, vm}; use std::ffi::{CStr, CString}; +use fs::{off_t}; +use vm::{VMAreaFlags, VMResizeOptions}; // Use the internal syscall wrappers from sgx_tstd //use std::libc_fs as fs; //use std::libc_io as io; @@ -158,6 +160,80 @@ pub fn do_lseek(fd: c_int, offset: off_t, whence: c_int) -> Result fs::do_lseek(fd, seek_from) } +fn do_mmap(addr: *const c_void, size: size_t, prot: c_int, + flags: c_int, fd: c_int, offset: off_t) + -> Result<*const c_void, Error> +{ + let addr = addr as usize; + let size = size as usize; + let flags = VMAreaFlags(prot as u32); + vm::do_mmap(addr, size, flags).map(|ret_addr| ret_addr as *const c_void) +} + +fn do_munmap(addr: *const c_void, size: size_t) -> Result<(), Error> { + let addr = addr as usize; + let size = size as usize; + vm::do_munmap(addr, size) +} + +fn do_mremap(old_addr: *const c_void, old_size: size_t, + new_size: size_t, flags: c_int, new_addr: *const c_void) + -> Result<*const c_void, Error> +{ + let old_addr = old_addr as usize; + let old_size = old_size as usize; + let mut options = VMResizeOptions::new(new_size)?; + // TODO: handle flags and new_addr + vm::do_mremap(old_addr, old_size, &options) + .map(|ret_addr| ret_addr as *const c_void) +} + +fn do_brk(new_brk_addr: *const c_void) -> Result<*const c_void, Error> { + let new_brk_addr = new_brk_addr as usize; + vm::do_brk(new_brk_addr).map(|ret_brk_addr| ret_brk_addr as *const c_void) +} + + +const MAP_FAILED : *const c_void = ((-1) as i64) as *const c_void; + +#[no_mangle] +pub extern "C" fn occlum_mmap(addr: *const c_void, length: size_t, prot: c_int, + flags: c_int, fd: c_int, offset: off_t) + -> *const c_void +{ + match do_mmap(addr, length, prot, flags, fd, offset) { + Ok(ret_addr) => { ret_addr }, + Err(e) => { MAP_FAILED } + } +} + +#[no_mangle] +pub extern "C" fn occlum_munmap(addr: *const c_void, length: size_t) -> c_int { + match do_munmap(addr, length) { + Ok(()) => { 0 }, + Err(e) => { -1 } + } +} + +#[no_mangle] +pub extern "C" fn occlum_mremap(old_addr: *const c_void, old_size: size_t, + new_size: size_t, flags: c_int, + new_addr: *const c_void) + -> *const c_void +{ + match do_mremap(old_addr, old_size, new_size, flags, new_addr) { + Ok(ret_addr) => { ret_addr }, + Err(e) => { MAP_FAILED } + } +} + +#[no_mangle] +pub extern "C" fn occlum_brk(addr: *const c_void) -> *const c_void { + match do_brk(addr) { + Ok(ret_addr) => { ret_addr }, + Err(e) => { MAP_FAILED } + } +} #[no_mangle] pub extern "C" fn occlum_open(path_buf: * const c_char, flags: c_int, mode: c_int) -> c_int { diff --git a/src/libos/src/syscall_entry.c b/src/libos/src/syscall_entry.c index 0b2301d9..5f4178b4 100644 --- a/src/libos/src/syscall_entry.c +++ b/src/libos/src/syscall_entry.c @@ -4,7 +4,7 @@ #define DECL_SYSCALL_ARG(_type, _name, _arg) \ _type _name = (_type) (_arg) -long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4) { +long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) { long ret = 0; switch (num) { @@ -81,10 +81,39 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long ret = occlum_getpid(); break; } + case SYS_mmap: { + DECL_SYSCALL_ARG(void*, addr, arg0); + DECL_SYSCALL_ARG(size_t, length, arg1); + DECL_SYSCALL_ARG(int, prot, arg2); + DECL_SYSCALL_ARG(int, flags, arg3); + DECL_SYSCALL_ARG(int, fd, arg4); + DECL_SYSCALL_ARG(off_t, offset, arg5); + ret = (long) occlum_mmap(addr, length, prot, flags, fd, offset); + break; + } + case SYS_munmap: { + DECL_SYSCALL_ARG(void*, addr, arg0); + DECL_SYSCALL_ARG(size_t, length, arg1); + ret = occlum_munmap(addr, length); + break; + } + case SYS_mremap: { + DECL_SYSCALL_ARG(void*, old_addr, arg0); + DECL_SYSCALL_ARG(size_t, old_size, arg1); + DECL_SYSCALL_ARG(size_t, new_size, arg2); + DECL_SYSCALL_ARG(int, flags, arg3); + DECL_SYSCALL_ARG(void*, new_addr, arg4); + ret = (long) occlum_mremap(old_addr, old_size, new_size, flags, new_addr); + break; + } + case SYS_brk: { + DECL_SYSCALL_ARG(void*, addr, arg0); + ret = (long) occlum_brk(addr); + break; + } default: ret = occlum_unknown(num); break; } - return ret; } diff --git a/src/libos/src/vm/mod.rs b/src/libos/src/vm/mod.rs index d1564474..5bfde2b0 100644 --- a/src/libos/src/vm/mod.rs +++ b/src/libos/src/vm/mod.rs @@ -1,5 +1,8 @@ use prelude::*; use std::{fmt}; +use file_table::{FileDesc}; +use fs::{off_t}; +use process::{Process, ProcessRef, get_current}; // TODO: Rename VMSpace to VMUniverse @@ -13,8 +16,43 @@ mod process_vm; pub use self::vm_range::{VMRange, VMRangeTrait}; pub use self::process_vm::{ProcessVM}; -pub const PAGE_SIZE : usize = 4096; +// TODO: separate proc and flags +// TODO: accept fd and offset +pub fn do_mmap(addr: usize, size: usize, flags: VMAreaFlags) + -> Result +{ + let current_ref = get_current(); + let mut current_process = current_ref.lock().unwrap(); + let current_vm = current_process.get_vm_mut(); + current_vm.mmap(addr, size, flags) +} +pub fn do_munmap(addr: usize, size: usize) -> Result<(), Error> { + let current_ref = get_current(); + let mut current_process = current_ref.lock().unwrap(); + let current_vm = current_process.get_vm_mut(); + current_vm.munmap(addr, size) +} + +// TODO: accept flags +pub fn do_mremap(old_addr: usize, old_size: usize, options: &VMResizeOptions) + -> Result +{ + let current_ref = get_current(); + let mut current_process = current_ref.lock().unwrap(); + let current_vm = current_process.get_vm_mut(); + current_vm.mremap(old_addr, old_size, options) +} + +pub fn do_brk(addr: usize) -> Result { + let current_ref = get_current(); + let mut current_process = current_ref.lock().unwrap(); + let current_vm = current_process.get_vm_mut(); + current_vm.brk(addr) +} + + +pub const PAGE_SIZE : usize = 4096; #[derive(Debug)] pub struct VMSpace { diff --git a/src/libos/src/vm/process_vm.rs b/src/libos/src/vm/process_vm.rs index a5526f4f..34aa8b8c 100644 --- a/src/libos/src/vm/process_vm.rs +++ b/src/libos/src/vm/process_vm.rs @@ -145,6 +145,7 @@ impl ProcessVM { self.get_stack_vma().get_end() } + // TODO: override the mmaping of already mmaped range pub fn mmap(&mut self, addr: usize, size: usize, flags: VMAreaFlags) -> Result { diff --git a/test/Makefile b/test/Makefile index 9ad5bd22..31a45a08 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) PROJECT_DIR := $(realpath $(CUR_DIR)/../) -TEST_SUITES := empty hello_world +TEST_SUITES := empty hello_world malloc BUILD_TEST_SUITES := $(TEST_SUITES:%=%) RUN_TEST_SUITES := $(TEST_SUITES:%=run-%) CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) diff --git a/test/malloc/Makefile b/test/malloc/Makefile new file mode 100644 index 00000000..b71a4d49 --- /dev/null +++ b/test/malloc/Makefile @@ -0,0 +1,4 @@ +include ../test_common.mk + +EXTRA_C_FLAGS := +EXTRA_LINK_FLAGS := diff --git a/test/malloc/main.c b/test/malloc/main.c new file mode 100644 index 00000000..1aec5002 --- /dev/null +++ b/test/malloc/main.c @@ -0,0 +1,16 @@ +#include +#include + +#define MAX_SIZE (1*1024*1024) +#define MIN_SIZE 8 + +int main(void) { + printf("Testing malloc and free...\n"); + for (size_t buf_size = MIN_SIZE; buf_size <= MAX_SIZE; buf_size *= 4) { + printf("buf_size = %lu\n", buf_size); + void* buf = malloc(buf_size); + free(buf); + } + printf("Done.\n"); + return 0; +}