Fix a bug and support more clockids in vdso.

This commit is contained in:
Chen Chengjun 2023-12-14 13:56:18 +08:00 committed by Tate, Hongliang Tian
parent d24775001f
commit 47d2a895af
3 changed files with 56 additions and 34 deletions

View File

@ -13,7 +13,7 @@ use crate::{START_TIME, VDSO_DATA_UPDATE};
/// A instance of TSC clocksource.
pub static CLOCK: Once<Arc<ClockSource>> = 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<Timer>) {
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,
));

View File

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

View File

@ -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<u64> = Once::new();
static START_SECS_COUNT: Once<u64> = Once::new();
static VDSO: Once<Arc<Vdso>> = 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));
}