From d3e84d22696f476a278bc86e610b6001030a6503 Mon Sep 17 00:00:00 2001 From: ClawSeven Date: Thu, 29 Feb 2024 17:28:23 +0800 Subject: [PATCH] [time] Adapt vdso module to SGX1 platform --- src/libos/crates/vdso-time/src/lib.rs | 12 ++----- src/libos/src/entry.rs | 6 ++-- src/libos/src/exception/cpuid.rs | 19 +++++++++- src/libos/src/exception/mod.rs | 2 ++ src/libos/src/time/mod.rs | 50 +++++++++++++++++++++++++-- src/libos/src/time/up_time.rs | 2 +- 6 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/libos/crates/vdso-time/src/lib.rs b/src/libos/crates/vdso-time/src/lib.rs index 9737f2f6..a234af8f 100644 --- a/src/libos/crates/vdso-time/src/lib.rs +++ b/src/libos/crates/vdso-time/src/lib.rs @@ -408,13 +408,7 @@ unsafe impl Sync for Vdso {} unsafe impl Send for Vdso {} lazy_static! { - static ref VDSO: Option = Vdso::new().map_or_else( - |e| { - trace!("{}", e); - None - }, - |v| Some(v) - ); + static ref VDSO: Option = Vdso::new().ok(); } /// Try to get time according to ClockId. @@ -455,7 +449,7 @@ pub fn clock_getres(clockid: ClockId) -> Result { } } -fn clock_gettime_slow(clockid: ClockId) -> Result { +pub fn clock_gettime_slow(clockid: ClockId) -> Result { let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0, @@ -486,7 +480,7 @@ fn clock_gettime_slow(clockid: ClockId) -> Result { } } -fn clock_getres_slow(clockid: ClockId) -> Result { +pub fn clock_getres_slow(clockid: ClockId) -> Result { let mut res = libc::timespec { tv_sec: 0, tv_nsec: 0, diff --git a/src/libos/src/entry.rs b/src/libos/src/entry.rs index f6ffdc76..6a36a7b2 100644 --- a/src/libos/src/entry.rs +++ b/src/libos/src/entry.rs @@ -10,7 +10,7 @@ use crate::interrupt; use crate::process::idle_reap_zombie_children; use crate::process::{ProcessFilter, SpawnAttr}; use crate::signal::SigNum; -use crate::time::up_time::init; +use crate::time::init; use crate::util::host_file_util::{host_file_buffer, parse_host_file, write_host_file, HostFile}; use crate::util::log::LevelFilter; use crate::util::mem_util::from_untrusted::*; @@ -96,8 +96,8 @@ pub extern "C" fn occlum_ecall_init( interrupt::init(); - // Init boot up time stamp here. - time::up_time::init(); + // Init vdso and boot up time stamp here. + time::init(); vm::init_user_space(); diff --git a/src/libos/src/exception/cpuid.rs b/src/libos/src/exception/cpuid.rs index b8580ac6..eab9234c 100644 --- a/src/libos/src/exception/cpuid.rs +++ b/src/libos/src/exception/cpuid.rs @@ -18,7 +18,7 @@ struct CpuIdInput { #[repr(C)] #[derive(Eq, PartialEq, Hash, Clone, Copy, Debug)] -struct CpuIdResult { +pub struct CpuIdResult { eax: u32, ebx: u32, ecx: u32, @@ -218,6 +218,15 @@ impl CpuId { }; cpuid_result } + + pub fn support_sgx2(&self) -> bool { + const SGX_CPUID: u32 = 12; + let cpuid = self.get_cpuid_info(SGX_CPUID, 0); + + // The 0th bit set to 1 in `cpuid.eax` indicates that the SGX feature is enabled. + // The 1st bit set to 1 in `cpuid.eax` indicates that the SGX2 feature is enabled. + (cpuid.eax & 0b11) == 0b11 + } } lazy_static! { @@ -247,6 +256,14 @@ fn get_cpuid_info_via_ocall(cpuid_input: CpuIdInput) -> CpuIdResult { cpuid_result } +pub fn is_cpu_support_sgx2() -> bool { + CPUID.support_sgx2() +} + +pub fn get_cpuid_info(leaf: u32, subleaf: u32) -> CpuIdResult { + CPUID.get_cpuid_info(leaf, subleaf) +} + pub fn setup_cpuid_info() { // Make lazy_static to be executed at runtime in order to be initialized let max_basic_leaf = CPUID.get_max_basic_leaf(); diff --git a/src/libos/src/exception/mod.rs b/src/libos/src/exception/mod.rs index 4669224c..612f73fb 100644 --- a/src/libos/src/exception/mod.rs +++ b/src/libos/src/exception/mod.rs @@ -11,6 +11,8 @@ use crate::vm::{enclave_page_fault_handler, is_page_committed, VMRange, USER_SPA use sgx_types::*; use sgx_types::{sgx_exception_type_t, sgx_exception_vector_t}; +pub use self::cpuid::{get_cpuid_info, is_cpu_support_sgx2}; + const ENCLU: u32 = 0xd7010f; const EACCEPT: u32 = 0x5; const EACCEPTCOPY: u32 = 0x7; diff --git a/src/libos/src/time/mod.rs b/src/libos/src/time/mod.rs index 8bcbb794..9f5044e6 100644 --- a/src/libos/src/time/mod.rs +++ b/src/libos/src/time/mod.rs @@ -1,9 +1,12 @@ use self::timer_slack::*; use super::*; +use crate::exception::is_cpu_support_sgx2; use core::convert::TryFrom; use process::pid_t; use rcore_fs::dev::TimeProvider; use rcore_fs::vfs::Timespec; +use sgx_trts::enclave::{rsgx_get_enclave_mode, EnclaveMode}; +use spin::Once; use std::time::Duration; use std::{fmt, u64}; use syscall::SyscallNum; @@ -28,6 +31,26 @@ pub type clock_t = i64; /// Clock ticks per second pub const SC_CLK_TCK: u64 = 100; +static IS_ENABLE_VDSO: Once = Once::new(); + +pub fn init() { + init_vdso(); + up_time::init(); +} + +fn init_vdso() { + IS_ENABLE_VDSO.call_once(|| match rsgx_get_enclave_mode() { + EnclaveMode::Hw if is_cpu_support_sgx2() => true, + EnclaveMode::Sim => true, + _ => false, + }); +} + +#[inline(always)] +fn is_enable_vdso() -> bool { + IS_ENABLE_VDSO.get().map_or(false, |is_enable| *is_enable) +} + #[repr(C)] #[derive(Debug, Default, Copy, Clone)] #[allow(non_camel_case_types)] @@ -75,7 +98,14 @@ impl From for timeval_t { } pub fn do_gettimeofday() -> timeval_t { - let tv = timeval_t::from(vdso_time::clock_gettime(ClockId::CLOCK_REALTIME).unwrap()); + let duration = if is_enable_vdso() { + vdso_time::clock_gettime(ClockId::CLOCK_REALTIME).unwrap() + } else { + // SGX1 Hardware doesn't support rdtsc instruction + vdso_time::clock_gettime_slow(ClockId::CLOCK_REALTIME).unwrap() + }; + + let tv = timeval_t::from(duration); tv.validate() .expect("gettimeofday returned invalid timeval_t"); tv @@ -145,14 +175,28 @@ impl timespec_t { pub type clockid_t = i32; pub fn do_clock_gettime(clockid: ClockId) -> Result { - let tv = timespec_t::from(vdso_time::clock_gettime(clockid).unwrap()); + let duration = if is_enable_vdso() { + vdso_time::clock_gettime(clockid).unwrap() + } else { + // SGX1 Hardware doesn't support rdtsc instruction + vdso_time::clock_gettime_slow(clockid).unwrap() + }; + + let tv = timespec_t::from(duration); tv.validate() .expect("clock_gettime returned invalid timespec"); Ok(tv) } pub fn do_clock_getres(clockid: ClockId) -> Result { - let res = timespec_t::from(vdso_time::clock_getres(clockid).unwrap()); + let duration = if is_enable_vdso() { + vdso_time::clock_getres(clockid).unwrap() + } else { + // SGX1 Hardware doesn't support rdtsc instruction + vdso_time::clock_getres_slow(clockid).unwrap() + }; + + let res = timespec_t::from(duration); let validate_resolution = |res: ×pec_t| -> Result<()> { // The resolution can be ranged from 1 nanosecond to a few milliseconds if res.sec == 0 && res.nsec > 0 && res.nsec < 1_000_000_000 { diff --git a/src/libos/src/time/up_time.rs b/src/libos/src/time/up_time.rs index 9a1b83a8..65ef7301 100644 --- a/src/libos/src/time/up_time.rs +++ b/src/libos/src/time/up_time.rs @@ -10,7 +10,7 @@ lazy_static! { .as_duration(); } -pub fn init() { +pub(super) fn init() { *BOOT_TIME_STAMP; *BOOT_TIME_STAMP_SINCE_EPOCH; }