[time] Adapt vdso module to SGX1 platform

This commit is contained in:
ClawSeven 2024-02-29 17:28:23 +08:00 committed by volcano
parent b2f721d1bb
commit e48cc13f79
6 changed files with 74 additions and 17 deletions

@ -408,13 +408,7 @@ unsafe impl Sync for Vdso {}
unsafe impl Send for Vdso {}
lazy_static! {
static ref VDSO: Option<Vdso> = Vdso::new().map_or_else(
|e| {
trace!("{}", e);
None
},
|v| Some(v)
);
static ref VDSO: Option<Vdso> = Vdso::new().ok();
}
/// Try to get time according to ClockId.
@ -455,7 +449,7 @@ pub fn clock_getres(clockid: ClockId) -> Result<Duration> {
}
}
fn clock_gettime_slow(clockid: ClockId) -> Result<Duration> {
pub fn clock_gettime_slow(clockid: ClockId) -> Result<Duration> {
let mut ts = libc::timespec {
tv_sec: 0,
tv_nsec: 0,
@ -486,7 +480,7 @@ fn clock_gettime_slow(clockid: ClockId) -> Result<Duration> {
}
}
fn clock_getres_slow(clockid: ClockId) -> Result<Duration> {
pub fn clock_getres_slow(clockid: ClockId) -> Result<Duration> {
let mut res = libc::timespec {
tv_sec: 0,
tv_nsec: 0,

@ -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();

@ -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();

@ -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;

@ -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<bool> = 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<Duration> 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<timespec_t> {
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<timespec_t> {
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: &timespec_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 {

@ -10,7 +10,7 @@ lazy_static! {
.as_duration();
}
pub fn init() {
pub(super) fn init() {
*BOOT_TIME_STAMP;
*BOOT_TIME_STAMP_SINCE_EPOCH;
}