diff --git a/services/comps/time/src/tsc.rs b/services/comps/time/src/tsc.rs index 0a4d28dc9..3e2ddf0f3 100644 --- a/services/comps/time/src/tsc.rs +++ b/services/comps/time/src/tsc.rs @@ -13,7 +13,7 @@ use crate::{START_TIME, VDSO_DATA_UPDATE}; /// A instance of TSC clocksource. pub static CLOCK: Once> = Once::new(); -const MAX_DELAY_SECS: u64 = 60; +const MAX_DELAY_SECS: u64 = 100; /// Init tsc clocksource module. pub(super) fn init() { @@ -62,10 +62,11 @@ fn update_clocksource(timer: Arc) { fn init_timer() { let timer = Timer::new(update_clocksource).unwrap(); // The initial timer should be set as `clock.max_delay_secs() >> 1` or something much smaller than `max_delay_secs`. - // This is because the initialization of this timer occurs during system startup. - // Afterwards, the system will undergo additional initialization processes, during which time interrupts are disabled. + // This is because the initialization of this timer occurs during system startup, + // and the system will also undergo other initialization processes, during which time interrupts are disabled. // This results in the actual trigger time of the timer being delayed by about 5 seconds compared to the set time. - // TODO: This is a temporary handle, and should be modified in the future. + // If without KVM, the delayed time will be larger. + // TODO: This is a temporary solution, and should be modified in the future. timer.set(Duration::from_secs( CLOCK.get().unwrap().max_delay_secs() >> 1, )); diff --git a/services/libs/jinux-std/src/time/mod.rs b/services/libs/jinux-std/src/time/mod.rs index dd7c6aff3..5ffed2d13 100644 --- a/services/libs/jinux-std/src/time/mod.rs +++ b/services/libs/jinux-std/src/time/mod.rs @@ -14,7 +14,7 @@ pub type time_t = i64; pub type suseconds_t = i64; pub type clock_t = i64; -#[derive(Debug, Copy, Clone, TryFromInt)] +#[derive(Debug, Copy, Clone, TryFromInt, PartialEq)] #[repr(i32)] pub enum ClockID { CLOCK_REALTIME = 0, @@ -27,6 +27,16 @@ pub enum ClockID { CLOCK_BOOTTIME = 7, } +/// A list of all supported clock IDs for time-related functions. +pub const ALL_SUPPORTED_CLOCK_IDS: [ClockID; 6] = [ + ClockID::CLOCK_REALTIME, + ClockID::CLOCK_REALTIME_COARSE, + ClockID::CLOCK_MONOTONIC, + ClockID::CLOCK_MONOTONIC_COARSE, + ClockID::CLOCK_MONOTONIC_RAW, + ClockID::CLOCK_BOOTTIME, +]; + #[repr(C)] #[derive(Debug, Default, Copy, Clone, Pod)] pub struct timespec_t { diff --git a/services/libs/jinux-std/src/vdso.rs b/services/libs/jinux-std/src/vdso.rs index d42e54551..0a1432558 100644 --- a/services/libs/jinux-std/src/vdso.rs +++ b/services/libs/jinux-std/src/vdso.rs @@ -6,7 +6,7 @@ //! necessary time-related information, and a Virtual Memory Object (VMO) that encapsulates both the data and the //! VDSO routines. The VMO is intended to be mapped into the address space of every user space process for efficient access. //! -//! The module is initialized with `init`, which sets up the `START_SEC_COUNT` and prepares the VDSO instance for +//! The module is initialized with `init`, which sets up the `START_SECS_COUNT` and prepares the VDSO instance for //! use. It also hooks up the VDSO data update routine to the time management subsystem for periodic updates. use alloc::boxed::Box; @@ -20,7 +20,7 @@ use spin::Once; use crate::{ fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD}, - time::{ClockID, SystemTime}, + time::{ClockID, SystemTime, ALL_SUPPORTED_CLOCK_IDS}, vm::vmo::{Vmo, VmoOptions}, }; @@ -28,7 +28,7 @@ const CLOCK_TAI: usize = 11; const VDSO_BASES: usize = CLOCK_TAI + 1; const DEFAULT_CLOCK_MODE: VdsoClockMode = VdsoClockMode::Tsc; -static START_SEC_COUNT: Once = Once::new(); +static START_SECS_COUNT: Once = Once::new(); static VDSO: Once> = Once::new(); #[derive(Debug, Copy, Clone)] @@ -46,15 +46,15 @@ enum VdsoClockMode { #[repr(C)] #[derive(Debug, Default, Copy, Clone, Pod)] struct VdsoInstant { - sec: u64, - nanos_mult: u64, + secs: u64, + nanos_lshift: u64, } impl VdsoInstant { const fn zero() -> Self { Self { - sec: 0, - nanos_mult: 0, + secs: 0, + nanos_lshift: 0, } } } @@ -124,23 +124,27 @@ impl VdsoData { self.shift = coeff.shift(); } - fn update_clock_instant(&mut self, clockid: usize, sec: u64, nanos_mult: u64) { - self.basetime[clockid].sec = sec; - self.basetime[clockid].nanos_mult = nanos_mult; + fn update_clock_instant(&mut self, clockid: usize, secs: u64, nanos_lshift: u64) { + self.basetime[clockid].secs = secs; + self.basetime[clockid].nanos_lshift = nanos_lshift; } fn update_instant(&mut self, instant: Instant, instant_cycles: u64) { self.last_cycles = instant_cycles; - self.update_clock_instant( - ClockID::CLOCK_REALTIME as usize, - instant.secs() + START_SEC_COUNT.get().unwrap(), - instant.nanos() as u64 * self.mult as u64, - ); - self.update_clock_instant( - ClockID::CLOCK_MONOTONIC as usize, - instant.secs(), - instant.nanos() as u64 * self.mult as u64, - ); + const REALTIME_IDS: [ClockID; 2] = + [ClockID::CLOCK_REALTIME, ClockID::CLOCK_REALTIME_COARSE]; + for clock_id in ALL_SUPPORTED_CLOCK_IDS { + let secs = if REALTIME_IDS.contains(&clock_id) { + instant.secs() + START_SECS_COUNT.get().unwrap() + } else { + instant.secs() + }; + self.update_clock_instant( + clock_id as usize, + secs, + (instant.nanos() as u64) << self.shift as u64, + ); + } } } @@ -196,9 +200,13 @@ impl Vdso { fn update_instant(&self, instant: Instant, instant_cycles: u64) { self.data.lock().update_instant(instant, instant_cycles); + // Update begins. self.vmo.write_val(0x80, &1).unwrap(); - self.update_vmo_instant(ClockID::CLOCK_REALTIME); - self.update_vmo_instant(ClockID::CLOCK_MONOTONIC); + self.vmo.write_val(0x88, &instant_cycles).unwrap(); + for clock_id in ALL_SUPPORTED_CLOCK_IDS { + self.update_vmo_instant(clock_id); + } + // Update finishes. self.vmo.write_val(0x80, &0).unwrap(); } @@ -206,13 +214,16 @@ impl Vdso { fn update_vmo_instant(&self, clockid: ClockID) { let clock_index = clockid as usize; let secs_offset = 0xA0 + clock_index * 0x10; - let nanos_mult_offset = 0xA8 + clock_index * 0x10; + let nanos_lshift_offset = 0xA8 + clock_index * 0x10; let data = self.data.lock(); self.vmo - .write_val(secs_offset, &data.basetime[clock_index].sec) + .write_val(secs_offset, &data.basetime[clock_index].secs) .unwrap(); self.vmo - .write_val(nanos_mult_offset, &data.basetime[clock_index].nanos_mult) + .write_val( + nanos_lshift_offset, + &data.basetime[clock_index].nanos_lshift, + ) .unwrap(); } } @@ -222,11 +233,11 @@ fn update_vdso_instant(instant: Instant, instant_cycles: u64) { VDSO.get().unwrap().update_instant(instant, instant_cycles); } -/// Init `START_SEC_COUNT`, which is used to record the seconds passed since 1970-01-01 00:00:00. -fn init_start_sec_count() { +/// Init `START_SECS_COUNT`, which is used to record the seconds passed since 1970-01-01 00:00:00. +fn init_start_secs_count() { let now = SystemTime::now(); let time_duration = now.duration_since(&SystemTime::UNIX_EPOCH).unwrap(); - START_SEC_COUNT.call_once(|| time_duration.as_secs()); + START_SECS_COUNT.call_once(|| time_duration.as_secs()); } fn init_vdso() { @@ -236,7 +247,7 @@ fn init_vdso() { /// Init vdso module. pub(super) fn init() { - init_start_sec_count(); + init_start_secs_count(); init_vdso(); jinux_time::VDSO_DATA_UPDATE.call_once(|| Arc::new(update_vdso_instant)); }