From 6e57937b45424ac7c4e4f8f5da6d81220c7f7a32 Mon Sep 17 00:00:00 2001 From: "Hui, Chunyang" Date: Tue, 2 Jun 2020 09:30:17 +0000 Subject: [PATCH] Add support for sysinfo syscall --- src/libos/src/entry.rs | 4 +++ src/libos/src/misc/mod.rs | 2 ++ src/libos/src/misc/sysinfo.rs | 35 ++++++++++++++++++++++ src/libos/src/syscall/mod.rs | 11 +++++-- src/libos/src/time/mod.rs | 1 + src/libos/src/time/up_time.rs | 19 ++++++++++++ src/libos/src/vm/mod.rs | 1 + test/Makefile | 2 +- test/sysinfo/Makefile | 5 ++++ test/sysinfo/main.c | 56 +++++++++++++++++++++++++++++++++++ 10 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 src/libos/src/misc/sysinfo.rs create mode 100644 src/libos/src/time/up_time.rs create mode 100644 test/sysinfo/Makefile create mode 100644 test/sysinfo/main.c diff --git a/src/libos/src/entry.rs b/src/libos/src/entry.rs index 29ba3f4d..ce8d9870 100644 --- a/src/libos/src/entry.rs +++ b/src/libos/src/entry.rs @@ -8,6 +8,7 @@ use crate::exception::*; use crate::fs::HostStdioFds; use crate::process::ProcessFilter; use crate::signal::SigNum; +use crate::time::up_time::init; use crate::util::log::LevelFilter; use crate::util::mem_util::from_untrusted::*; use crate::util::sgx::allow_debug as sgx_allow_debug; @@ -72,6 +73,9 @@ pub extern "C" fn occlum_ecall_init(log_level: *const c_char, instance_dir: *con } HAS_INIT.store(true, Ordering::SeqCst); + + // Init boot up time stamp here. + time::up_time::init(); }); 0 diff --git a/src/libos/src/misc/mod.rs b/src/libos/src/misc/mod.rs index 617ef4cc..d4a27b04 100644 --- a/src/libos/src/misc/mod.rs +++ b/src/libos/src/misc/mod.rs @@ -1,7 +1,9 @@ use super::*; mod rlimit; +mod sysinfo; mod uname; pub use self::rlimit::{do_prlimit, resource_t, rlimit_t, ResourceLimits}; +pub use self::sysinfo::{do_sysinfo, sysinfo_t}; pub use self::uname::{do_uname, utsname_t}; diff --git a/src/libos/src/misc/sysinfo.rs b/src/libos/src/misc/sysinfo.rs new file mode 100644 index 00000000..00ed4950 --- /dev/null +++ b/src/libos/src/misc/sysinfo.rs @@ -0,0 +1,35 @@ +use super::*; +use crate::process::table; +use crate::time::up_time::get; +use crate::vm::USER_SPACE_VM_MANAGER; +use config::LIBOS_CONFIG; + +// This structure aligns with Linux kernels which are later than v2.3.23 (i386) and v2.3.48 (all architectures) +#[repr(C)] +#[derive(Clone, Default)] +pub struct sysinfo_t { + uptime: i64, + loads: [u64; 3], + totalram: u64, + freeram: u64, + sharedram: u64, + bufferram: u64, + totalswap: u64, + freeswap: u64, + procs: u16, + totalhigh: u64, + freehigh: u64, + mem_unit: u32, +} + +pub fn do_sysinfo() -> Result { + let info = sysinfo_t { + uptime: time::up_time::get().unwrap().as_secs() as i64, // Duration can't be negative + totalram: USER_SPACE_VM_MANAGER.get_total_size() as u64, + freeram: USER_SPACE_VM_MANAGER.get_free_size() as u64, + procs: table::get_all_processes().len() as u16, + mem_unit: 1, + ..Default::default() + }; + Ok(info) +} diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 13e0cb36..4bfa5a28 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -25,7 +25,7 @@ use crate::fs::{ do_readlink, do_readv, do_rename, do_rmdir, do_sendfile, do_stat, do_sync, do_truncate, do_unlink, do_write, do_writev, iovec_t, File, FileDesc, FileRef, HostStdioFds, Stat, }; -use crate::misc::{resource_t, rlimit_t, utsname_t}; +use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t}; use crate::net::{ do_accept, do_accept4, do_bind, do_connect, do_epoll_create, do_epoll_create1, do_epoll_ctl, do_epoll_pwait, do_epoll_wait, do_getpeername, do_getsockname, do_getsockopt, do_listen, @@ -176,7 +176,7 @@ macro_rules! process_syscall_table_with_callback { (Gettimeofday = 96) => do_gettimeofday(tv_u: *mut timeval_t), (Getrlimit = 97) => handle_unsupported(), (Getrusage = 98) => handle_unsupported(), - (SysInfo = 99) => handle_unsupported(), + (SysInfo = 99) => do_sysinfo(info: *mut sysinfo_t), (Times = 100) => handle_unsupported(), (Ptrace = 101) => handle_unsupported(), (Getuid = 102) => do_getuid(), @@ -755,6 +755,13 @@ fn do_brk(new_brk_addr: usize) -> Result { Ok(ret_brk_addr as isize) } +fn do_sysinfo(info: *mut sysinfo_t) -> Result { + check_mut_ptr(info)?; + let info = unsafe { &mut *info }; + *info = misc::do_sysinfo()?; + Ok(0) +} + // TODO: handle tz: timezone_t fn do_gettimeofday(tv_u: *mut timeval_t) -> Result { check_mut_ptr(tv_u)?; diff --git a/src/libos/src/time/mod.rs b/src/libos/src/time/mod.rs index c871b8c2..22b0cbca 100644 --- a/src/libos/src/time/mod.rs +++ b/src/libos/src/time/mod.rs @@ -8,6 +8,7 @@ use std::{fmt, u64}; use syscall::SyscallNum; mod profiler; +pub mod up_time; pub use profiler::GLOBAL_PROFILER; diff --git a/src/libos/src/time/up_time.rs b/src/libos/src/time/up_time.rs new file mode 100644 index 00000000..a9feabba --- /dev/null +++ b/src/libos/src/time/up_time.rs @@ -0,0 +1,19 @@ +use super::{do_clock_gettime, ClockID}; +use std::time::Duration; + +lazy_static! { + static ref BOOT_TIME_STAMP: Duration = do_clock_gettime(ClockID::CLOCK_MONOTONIC_RAW) + .unwrap() + .as_duration(); +} + +pub fn init() { + *BOOT_TIME_STAMP; +} + +pub fn get() -> Option { + do_clock_gettime(ClockID::CLOCK_MONOTONIC_RAW) + .unwrap() + .as_duration() + .checked_sub(*BOOT_TIME_STAMP) +} diff --git a/src/libos/src/vm/mod.rs b/src/libos/src/vm/mod.rs index f4588eca..7c1d8968 100644 --- a/src/libos/src/vm/mod.rs +++ b/src/libos/src/vm/mod.rs @@ -13,6 +13,7 @@ use self::vm_layout::VMLayout; use self::vm_manager::{VMManager, VMMapOptionsBuilder}; pub use self::process_vm::{MMapFlags, MRemapFlags, ProcessVM, ProcessVMBuilder, VMPerms}; +pub use self::user_space_vm::USER_SPACE_VM_MANAGER; pub use self::vm_range::VMRange; pub fn do_mmap( diff --git a/test/Makefile b/test/Makefile index 9c3f3a89..0e910e8e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -22,7 +22,7 @@ TEST_DEPS := client data_sink TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe time \ truncate readdir mkdir open stat link symlink chmod chown tls pthread uname rlimit \ server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \ - ioctl fcntl eventfd emulate_syscall access signal + ioctl fcntl eventfd emulate_syscall access signal sysinfo # Benchmarks: need to be compiled and run by bench-% target BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput diff --git a/test/sysinfo/Makefile b/test/sysinfo/Makefile new file mode 100644 index 00000000..9e1b6dec --- /dev/null +++ b/test/sysinfo/Makefile @@ -0,0 +1,5 @@ +include ../test_common.mk + +EXTRA_C_FLAGS := +EXTRA_LINK_FLAGS := +BIN_ARGS := diff --git a/test/sysinfo/main.c b/test/sysinfo/main.c new file mode 100644 index 00000000..53d9de5d --- /dev/null +++ b/test/sysinfo/main.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include "test.h" + +int test_sysinfo() { + const long MIN = 60; + const long HOUR = MIN * 60; + const long DAY = HOUR * 24; + const double MEGABYTE = 1024 * 1024; + struct sysinfo info; + int child_pid, status; + + // Test uptime + sleep(3); + + // Test procs number + int ret = posix_spawn(&child_pid, "/bin/getpid", NULL, NULL, NULL, NULL); + if (ret < 0 ) { + THROW_ERROR("spawn process error"); + } + + sysinfo (&info); + + printf ("system uptime: %ld days, %ld:%02ld:%02ld\n", + info.uptime / DAY, (info.uptime % DAY) / HOUR, + (info.uptime % HOUR) / MIN, info.uptime % MIN); + printf ("total RAM: %5.1f MB\n", info.totalram / MEGABYTE); + printf ("free RAM: %5.1f MB\n", info.freeram / MEGABYTE); + printf ("process count: %d\n", info.procs); + + if (info.uptime % MIN < 3) { + THROW_ERROR("system uptime error"); + } + + if (info.procs != 2 ) { + THROW_ERROR("system process count error"); + } + + ret = wait4(-1, &status, 0, NULL); + if (ret < 0) { + THROW_ERROR("failed to wait4 the child proces"); + } + + return 0; +} + +static test_case_t test_cases[] = { + TEST_CASE(test_sysinfo), +}; + +int main() { + return test_suite_run(test_cases, ARRAY_SIZE(test_cases)); +}