From d3009db10bae1e4ed34c54dd7b3006d45cdd41e7 Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Mon, 7 Jan 2019 22:57:14 +0800 Subject: [PATCH] Add gettimeofday --- src/Enclave.edl | 1 + src/libos/include/syscall.h | 3 + src/libos/src/lib.rs | 1 + src/libos/src/syscall/mod.rs | 175 ++++++++++++++------------ src/libos/src/syscall/syscall_entry.c | 6 + src/libos/src/time/mod.rs | 27 ++++ src/pal/pal.c | 8 ++ test/Makefile | 2 +- test/time/Makefile | 4 + test/time/main.c | 9 ++ 10 files changed, 158 insertions(+), 78 deletions(-) create mode 100644 src/libos/src/time/mod.rs create mode 100644 test/time/Makefile create mode 100644 test/time/main.c diff --git a/src/Enclave.edl b/src/Enclave.edl index 44e1ebb6..07a84d84 100644 --- a/src/Enclave.edl +++ b/src/Enclave.edl @@ -14,5 +14,6 @@ enclave { untrusted { void ocall_print_string([in, string] const char* msg); int ocall_run_new_task(void); + void ocall_gettimeofday([out] long* seconds, [out] long* microseconds); }; }; diff --git a/src/libos/include/syscall.h b/src/libos/include/syscall.h index 5b97301f..9d76aad4 100644 --- a/src/libos/include/syscall.h +++ b/src/libos/include/syscall.h @@ -5,6 +5,7 @@ #include "syscall_nr.h" struct iovec; +struct timeval; #ifdef __cplusplus extern "C" { @@ -38,6 +39,8 @@ 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_gettimeofday(struct timeval* tv/*, struct timezone* tz*/); + extern int occlum_unknown(int num); #ifdef __cplusplus diff --git a/src/libos/src/lib.rs b/src/libos/src/lib.rs index be4a9ca2..0adbc212 100644 --- a/src/libos/src/lib.rs +++ b/src/libos/src/lib.rs @@ -32,6 +32,7 @@ mod process; mod syscall; mod vm; mod util; +mod time; use prelude::*; diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 44945663..e36a1471 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -1,11 +1,12 @@ use super::*; use prelude::*; -use std::{ptr}; use {std, fs, process, vm}; +use std::{ptr}; use std::ffi::{CStr, CString}; use fs::{off_t, FileDesc}; use vm::{VMAreaFlags, VMResizeOptions}; use process::{pid_t, ChildProcessFilter, FileAction}; +use time::{timeval_t}; // Use the internal syscall wrappers from sgx_tstd //use std::libc_fs as fs; //use std::libc_io as io; @@ -50,6 +51,81 @@ fn clone_cstrings_from_user_safely(user_ptr: *const *const c_char) } +/* + * This Rust-version of fdop correspond to the C-version one in Occlum. + * See /src/process/fdop.h. + */ +const FDOP_CLOSE : u32 = 1; +const FDOP_DUP2 : u32 = 2; +const FDOP_OPEN : u32 = 3; + +#[repr(C)] +#[derive(Debug)] +pub struct FdOp { + // We actually switch the prev and next fields in the libc definition. + prev: *const FdOp, + next: *const FdOp, + cmd: u32, + fd: u32, + srcfd: u32, + oflag: u32, + mode: u32, + path: *const u8, +} + +fn clone_file_actions_from_user_safely(fdop_ptr: *const FdOp) + -> Result, Error> +{ + let mut file_actions = Vec::new(); + + let mut fdop_ptr = fdop_ptr; + while fdop_ptr != ptr::null() { + check_ptr_from_user(fdop_ptr)?; + let fdop = unsafe { &*fdop_ptr }; + + let file_action = match fdop.cmd { + FDOP_CLOSE => { + FileAction::Close(fdop.fd) + }, + FDOP_DUP2 => { + FileAction::Dup2(fdop.srcfd, fdop.fd) + }, + FDOP_OPEN => { + return errno!(EINVAL, "Not implemented"); + }, + _ => { + return errno!(EINVAL, "Unknown file action command"); + }, + }; + file_actions.push(file_action); + + fdop_ptr = fdop.next; + } + + Ok(file_actions) +} + +fn do_spawn(child_pid_ptr: *mut c_uint, + path: *const c_char, + argv: *const *const c_char, + envp: *const *const c_char, + fdop_list: *const FdOp, + ) + -> Result<(), Error> +{ + check_mut_ptr_from_user(child_pid_ptr)?; + let path = clone_cstring_from_user_safely(path)?; + let argv = clone_cstrings_from_user_safely(argv)?; + let envp = clone_cstrings_from_user_safely(envp)?; + let file_actions = clone_file_actions_from_user_safely(fdop_list)?; + let parent = process::get_current(); + + let child_pid = process::do_spawn(&path, &argv, &envp, &file_actions, &parent)?; + + unsafe { *child_pid_ptr = child_pid }; + Ok(()) +} + fn do_read(fd: c_int, buf: *mut c_void, size: size_t) -> Result { @@ -244,6 +320,13 @@ fn do_pipe2(fds_u: *mut c_int, flags: c_int) -> Result<(), Error> { Ok(()) } +fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<(), Error> { + check_mut_ptr_from_user(tv_u)?; + let tv = time::do_gettimeofday(); + unsafe { *tv_u = tv; } + Ok(()) +} + const MAP_FAILED : *const c_void = ((-1) as i64) as *const c_void; @@ -414,82 +497,6 @@ pub extern "C" fn occlum_unknown(num: u32) println!("[WARNING] Unknown syscall (num = {})", num); } - -/* - * This Rust-version of fdop correspond to the C-version one in Occlum. - * See /src/process/fdop.h. - */ -const FDOP_CLOSE : u32 = 1; -const FDOP_DUP2 : u32 = 2; -const FDOP_OPEN : u32 = 3; - -#[repr(C)] -#[derive(Debug)] -pub struct FdOp { - // We actually switch the prev and next fields in the libc definition. - prev: *const FdOp, - next: *const FdOp, - cmd: u32, - fd: u32, - srcfd: u32, - oflag: u32, - mode: u32, - path: *const u8, -} - -fn clone_file_actions_from_user_safely(fdop_ptr: *const FdOp) - -> Result, Error> -{ - let mut file_actions = Vec::new(); - - let mut fdop_ptr = fdop_ptr; - while fdop_ptr != ptr::null() { - check_ptr_from_user(fdop_ptr)?; - let fdop = unsafe { &*fdop_ptr }; - - let file_action = match fdop.cmd { - FDOP_CLOSE => { - FileAction::Close(fdop.fd) - }, - FDOP_DUP2 => { - FileAction::Dup2(fdop.srcfd, fdop.fd) - }, - FDOP_OPEN => { - return errno!(EINVAL, "Not implemented"); - }, - _ => { - return errno!(EINVAL, "Unknown file action command"); - }, - }; - file_actions.push(file_action); - - fdop_ptr = fdop.next; - } - - Ok(file_actions) -} - -fn do_spawn(child_pid_ptr: *mut c_uint, - path: *const c_char, - argv: *const *const c_char, - envp: *const *const c_char, - fdop_list: *const FdOp, - ) - -> Result<(), Error> -{ - check_mut_ptr_from_user(child_pid_ptr)?; - let path = clone_cstring_from_user_safely(path)?; - let argv = clone_cstrings_from_user_safely(argv)?; - let envp = clone_cstrings_from_user_safely(envp)?; - let file_actions = clone_file_actions_from_user_safely(fdop_list)?; - let parent = process::get_current(); - - let child_pid = process::do_spawn(&path, &argv, &envp, &file_actions, &parent)?; - - unsafe { *child_pid_ptr = child_pid }; - Ok(()) -} - #[no_mangle] pub extern "C" fn occlum_spawn( child_pid: *mut c_uint, path: *const c_char, @@ -562,3 +569,17 @@ pub extern "C" fn occlum_dup3(old_fd: c_int, new_fd: c_int, flags: c_int) } } } + +// TODO: handle tz: timezone_t +#[no_mangle] +pub extern "C" fn occlum_gettimeofday(tv: *mut timeval_t) -> c_int +{ + match do_gettimeofday(tv) { + Ok(()) => { + 0 + } + Err(e) => { + e.errno.as_retval() + } + } +} diff --git a/src/libos/src/syscall/syscall_entry.c b/src/libos/src/syscall/syscall_entry.c index d47b90b0..75be0c7c 100644 --- a/src/libos/src/syscall/syscall_entry.c +++ b/src/libos/src/syscall/syscall_entry.c @@ -144,6 +144,12 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long ret = (long) occlum_dup3(old_fd, new_fd, flags); break; } + case SYS_gettimeofday: { + DECL_SYSCALL_ARG(struct timeval*, tv, arg0); + //DECL_SYSCALL_ARG(struct timezone*, tz, arg1); + ret = (long) occlum_gettimeofday(tv/*, tz*/); + break; + } default: ret = occlum_unknown(num); break; diff --git a/src/libos/src/time/mod.rs b/src/libos/src/time/mod.rs new file mode 100644 index 00000000..c746479b --- /dev/null +++ b/src/libos/src/time/mod.rs @@ -0,0 +1,27 @@ +use super::*; + +#[allow(non_camel_case_types)] +pub type time_t = i64; + +#[allow(non_camel_case_types)] +pub type suseconds_t = i64; + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct timeval_t { + sec: time_t, + usec: suseconds_t, +} + +pub fn do_gettimeofday() -> timeval_t { + let mut tv : timeval_t = Default::default(); + unsafe { + ocall_gettimeofday(&mut tv.sec as *mut time_t, + &mut tv.usec as *mut suseconds_t); + } + tv +} + +extern { + fn ocall_gettimeofday(sec: *mut time_t, usec: *mut suseconds_t) -> sgx_status_t; +} diff --git a/src/pal/pal.c b/src/pal/pal.c index b02d1a57..cfd660bb 100644 --- a/src/pal/pal.c +++ b/src/pal/pal.c @@ -4,6 +4,7 @@ #include #include +#include #define MAX_PATH FILENAME_MAX @@ -197,6 +198,13 @@ int ocall_run_new_task(void) { return ret; } +void ocall_gettimeofday(long* seconds, long* microseconds) { + struct timeval tv; + gettimeofday(&tv, NULL); + *seconds = tv.tv_sec; + *microseconds = tv.tv_usec; +} + /* Application entry */ int SGX_CDECL main(int argc, char *argv[]) diff --git a/test/Makefile b/test/Makefile index eab555a3..179660b5 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 malloc file getpid spawn pipe +TEST_SUITES := empty hello_world malloc file getpid spawn pipe time BUILD_TEST_SUITES := $(TEST_SUITES:%=%) RUN_TEST_SUITES := $(TEST_SUITES:%=test-%) CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) diff --git a/test/time/Makefile b/test/time/Makefile new file mode 100644 index 00000000..b71a4d49 --- /dev/null +++ b/test/time/Makefile @@ -0,0 +1,4 @@ +include ../test_common.mk + +EXTRA_C_FLAGS := +EXTRA_LINK_FLAGS := diff --git a/test/time/main.c b/test/time/main.c new file mode 100644 index 00000000..367522f8 --- /dev/null +++ b/test/time/main.c @@ -0,0 +1,9 @@ +#include +#include + +int main() { + struct timeval tv; + gettimeofday(&tv, NULL); + printf("sec = %lu, usec = %lu\n", tv.tv_sec, tv.tv_usec); + return 0; +}