Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/aarch64/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub const VVAR_PAGES: usize = 5;
pub const VVAR_PAGES: usize = 4;

#[repr(i32)]
pub enum ClockMode {
Expand Down
64 changes: 11 additions & 53 deletions src/aarch64/vdso_data.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
use axplat::time::{
NANOS_PER_SEC, current_ticks, monotonic_time_nanos, nanos_to_ticks, wall_time_nanos,
};

use super::config::ClockMode;
use crate::update::{VdsoClock, clocks_calc_mult_shift, update_vdso_clock};

use crate::vdso_time_data::VdsoTimeData;
#[repr(C)]
#[repr(align(4096))]
pub struct VdsoData {
pub clock_page0: VdsoClock,
pub _unused: [u8; 1648],
pub tz_minuteswest: i32,
pub tz_dsttime: i32,
pub hrtimer_res: u32,
pub _pad: [u8; 4096 - 1956],
pub clock_page1: VdsoClock,
pub time_data: VdsoTimeData,
pub timen_data: [u8; 4096],
pub rng_data: [u8; 4096],
pub arch_data: [u8; 4096],
}

impl Default for VdsoData {
Expand All @@ -26,46 +16,14 @@ impl Default for VdsoData {
impl VdsoData {
pub const fn new() -> Self {
Self {
clock_page0: VdsoClock::new(),
_unused: [0; 1648],
tz_minuteswest: 0,
tz_dsttime: 0,
hrtimer_res: 1,
_pad: [0; 4096 - 1956],
clock_page1: VdsoClock::new(),
time_data: VdsoTimeData::new(),
timen_data: [0u8; 4096],
rng_data: [0u8; 4096],
arch_data: [0u8; 4096],
}
}

pub fn update(&mut self) {
let wall_ns = wall_time_nanos();
let mono_ns = monotonic_time_nanos();

let ticks_per_sec = nanos_to_ticks(NANOS_PER_SEC);
let mult_shift = clocks_calc_mult_shift(ticks_per_sec, NANOS_PER_SEC, 10);
let cycle_now = current_ticks();

self.clock_page0.write_seqcount_begin();
self.clock_page0.clock_mode = ClockMode::Cntvct as i32;
self.clock_page0.mask = u64::MAX;
update_vdso_clock(
&mut self.clock_page0,
cycle_now,
wall_ns,
mono_ns,
mult_shift,
);
self.clock_page0.write_seqcount_end();

self.clock_page1.write_seqcount_begin();
self.clock_page1.clock_mode = ClockMode::Cntvct as i32;
self.clock_page1.mask = u64::MAX;
update_vdso_clock(
&mut self.clock_page1,
cycle_now,
wall_ns,
mono_ns,
mult_shift,
);
self.clock_page1.write_seqcount_end();
pub fn time_update(&mut self) {
self.time_data.update();
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod embed;
pub mod guard;
mod update;
pub mod vdso;
mod vdso_time_data;

cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
Expand Down
4 changes: 2 additions & 2 deletions src/loongarch64/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub const VVAR_PAGES: usize = 44;
#[cfg(target_arch = "loongarch64")]
pub const VVAR_PAGES: usize = 20;

#[repr(i32)]
pub enum ClockMode {
None,
Expand Down
41 changes: 11 additions & 30 deletions src/loongarch64/vdso_data.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,24 @@
use axplat::time::{
NANOS_PER_SEC, current_ticks, monotonic_time_nanos, nanos_to_ticks, wall_time_nanos,
};

use crate::update::{VdsoClock, clocks_calc_mult_shift, update_vdso_clock};
use crate::vdso_time_data::VdsoTimeData;

#[repr(C)]
#[repr(align(4096))]
#[derive(Default)]
pub struct VdsoData {
pub clocks: [VdsoClock; 2],
pub tz_minuteswest: i32,
pub tz_dsttime: i32,
pub hrtimer_res: u32,
pub time_data: VdsoTimeData,
}

impl Default for VdsoData {
fn default() -> Self {
Self::new()
}
}

impl VdsoData {
/// Create a new VdsoData with default values.
pub const fn new() -> Self {
Self {
clocks: [VdsoClock::new(), VdsoClock::new()],
tz_minuteswest: 0,
tz_dsttime: 0,
hrtimer_res: 1,
time_data: VdsoTimeData::new(),
}
}

/// Update vDSO clocks and basetimes.
pub fn update(&mut self) {
let cycle_now = current_ticks();
let wall_ns = wall_time_nanos();
let mono_ns = monotonic_time_nanos();

let ticks_per_sec = nanos_to_ticks(NANOS_PER_SEC);
let mult_shift = clocks_calc_mult_shift(ticks_per_sec, NANOS_PER_SEC, 10);

for clk in &mut self.clocks {
clk.write_seqcount_begin();
update_vdso_clock(clk, cycle_now, wall_ns, mono_ns, mult_shift);
clk.write_seqcount_end();
}
pub fn time_update(&mut self) {
self.time_data.update();
}
}
2 changes: 1 addition & 1 deletion src/riscv64/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub const VVAR_PAGES: usize = 2;
pub const VVAR_PAGES: usize = 4;

#[repr(i32)]
pub enum ClockMode {
Expand Down
39 changes: 11 additions & 28 deletions src/riscv64/vdso_data.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,24 @@
use axplat::time::{
NANOS_PER_SEC, current_ticks, monotonic_time_nanos, nanos_to_ticks, wall_time_nanos,
};

use crate::update::{VdsoClock, clocks_calc_mult_shift, update_vdso_clock};
use crate::vdso_time_data::VdsoTimeData;

#[repr(C)]
#[repr(align(4096))]
#[derive(Default)]
pub struct VdsoData {
pub clocks: [VdsoClock; 2],
pub tz_minuteswest: i32,
pub tz_dsttime: i32,
pub hrtimer_res: u32,
pub time_data: VdsoTimeData,
}

impl Default for VdsoData {
fn default() -> Self {
Self::new()
}
}

impl VdsoData {
pub const fn new() -> Self {
Self {
clocks: [VdsoClock::new(), VdsoClock::new()],
tz_minuteswest: 0,
tz_dsttime: 0,
hrtimer_res: 1,
time_data: VdsoTimeData::new(),
}
}

pub fn update(&mut self) {
let cycle_now = current_ticks();
let wall_ns = wall_time_nanos();
let mono_ns = monotonic_time_nanos();

let ticks_per_sec = nanos_to_ticks(NANOS_PER_SEC);
let mult_shift = clocks_calc_mult_shift(ticks_per_sec, NANOS_PER_SEC, 10);

for clk in &mut self.clocks {
clk.write_seqcount_begin();
update_vdso_clock(clk, cycle_now, wall_ns, mono_ns, mult_shift);
clk.write_seqcount_end();
}
pub fn time_update(&mut self) {
self.time_data.update();
}
}
76 changes: 16 additions & 60 deletions src/update.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use core::sync::atomic::{AtomicU32, AtomicU64, Ordering};
use core::sync::atomic::Ordering;

use axplat::time::NANOS_PER_SEC;

use crate::config::ClockMode;

/// Number of clock bases
const VDSO_BASES: usize = 16;
use crate::{config::ClockMode, vdso_time_data::VdsoClock};

/// vDSO timestamp structure
#[repr(C)]
Expand All @@ -24,47 +21,6 @@ impl VdsoTimestamp {
}
}

#[repr(C)]
#[derive(Default)]
pub struct VdsoClock {
pub seq: AtomicU32,
pub clock_mode: i32,
pub cycle_last: AtomicU64,
pub mask: u64,
pub mult: u32,
pub shift: u32,
pub basetime: [VdsoTimestamp; VDSO_BASES],
pub _unused: u32,
}

impl VdsoClock {
/// Create a new VdsoClock with default values.
pub const fn new() -> Self {
Self {
seq: AtomicU32::new(0),
clock_mode: 1,
cycle_last: AtomicU64::new(0),
mask: u64::MAX,
mult: 0,
shift: 32,
basetime: [VdsoTimestamp::new(); VDSO_BASES],
_unused: 0,
}
}

pub fn write_seqcount_begin(&self) {
let seq = self.seq.load(Ordering::Relaxed);
self.seq.store(seq.wrapping_add(1), Ordering::Release);
core::sync::atomic::fence(Ordering::SeqCst);
}

pub fn write_seqcount_end(&self) {
core::sync::atomic::fence(Ordering::SeqCst);
let seq = self.seq.load(Ordering::Relaxed);
self.seq.store(seq.wrapping_add(1), Ordering::Release);
}
}

/// Update vDSO clock.
pub fn update_vdso_clock(
clk: &mut VdsoClock,
Expand All @@ -74,10 +30,10 @@ pub fn update_vdso_clock(
mult_shift: (u32, u32),
) {
let prev_cycle = clk.cycle_last.load(Ordering::Relaxed);
let prev_basetime_ns = clk.basetime[1]
let prev_basetime_ns = clk.time_data[1]
.sec
.wrapping_mul(NANOS_PER_SEC)
.wrapping_add(clk.basetime[1].nsec);
.wrapping_add(clk.time_data[1].nsec);

// Check if this is a counter-based clock mode (non-None)
let is_counter_mode = clk.clock_mode != (ClockMode::None as i32);
Expand All @@ -89,16 +45,16 @@ pub fn update_vdso_clock(
let (mult, shift) = mult_shift;
clk.mult = mult;
clk.shift = shift;
clk.basetime[1].sec = mono_ns / NANOS_PER_SEC;
clk.basetime[1].nsec = (mono_ns % NANOS_PER_SEC) << shift;
clk.time_data[1].sec = mono_ns / NANOS_PER_SEC;
clk.time_data[1].nsec = (mono_ns % NANOS_PER_SEC) << shift;
clk.cycle_last.store(cycle_now, Ordering::Relaxed);
} else {
let (mult, shift) = mult_shift;
if !(mult == u32::MAX && shift == 0) {
clk.mult = mult;
clk.shift = shift;
clk.basetime[1].sec = mono_ns / NANOS_PER_SEC;
clk.basetime[1].nsec = (mono_ns % NANOS_PER_SEC) << shift;
clk.time_data[1].sec = mono_ns / NANOS_PER_SEC;
clk.time_data[1].nsec = (mono_ns % NANOS_PER_SEC) << shift;
clk.cycle_last.store(cycle_now, Ordering::Relaxed);
} else {
let delta_cycles = (cycle_now.wrapping_sub(prev_cycle)) & clk.mask;
Expand All @@ -107,26 +63,26 @@ pub fn update_vdso_clock(
let (mult, shift) = clocks_calc_mult_shift(delta_cycles, delta_ns, 1);
clk.mult = mult;
clk.shift = shift;
clk.basetime[1].sec = mono_ns / NANOS_PER_SEC;
clk.basetime[1].nsec = (mono_ns % NANOS_PER_SEC) << shift;
clk.time_data[1].sec = mono_ns / NANOS_PER_SEC;
clk.time_data[1].nsec = (mono_ns % NANOS_PER_SEC) << shift;
clk.cycle_last.store(cycle_now, Ordering::Relaxed);
}
}
}
} else {
// ClockMode::None - No cycle->ns conversion; store direct monotonic ns.
clk.mult = 0;
clk.basetime[1].sec = mono_ns / NANOS_PER_SEC;
clk.basetime[1].nsec = mono_ns % NANOS_PER_SEC;
clk.time_data[1].sec = mono_ns / NANOS_PER_SEC;
clk.time_data[1].nsec = mono_ns % NANOS_PER_SEC;
clk.cycle_last.store(0, Ordering::Relaxed);
}

// Update realtime and boottime entries.
let shift = clk.shift;
clk.basetime[0].sec = wall_ns / NANOS_PER_SEC;
clk.basetime[0].nsec = (wall_ns % NANOS_PER_SEC) << shift;
clk.basetime[7].sec = clk.basetime[1].sec;
clk.basetime[7].nsec = clk.basetime[1].nsec;
clk.time_data[0].sec = wall_ns / NANOS_PER_SEC;
clk.time_data[0].nsec = (wall_ns % NANOS_PER_SEC) << shift;
clk.time_data[7].sec = clk.time_data[1].sec;
clk.time_data[7].nsec = clk.time_data[1].nsec;

if clk.seq.load(Ordering::Relaxed) < 10 {
let cycle_val = clk.cycle_last.load(Ordering::Relaxed);
Expand Down
9 changes: 7 additions & 2 deletions src/vdso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,21 @@ pub static mut VDSO_DATA: crate::vdso_data::VdsoData = crate::vdso_data::VdsoDat
pub fn init_vdso_data() {
unsafe {
let data_ptr = core::ptr::addr_of_mut!(VDSO_DATA);
(*data_ptr).update();
(*data_ptr).time_update();
log::info!("vDSO data initialized at {:#x}", data_ptr as usize);
#[cfg(target_arch = "aarch64")]
{
enable_cntvct_access();
log::info!("vDSO CNTVCT access enabled");
}
}
}

/// Update vDSO data
pub fn update_vdso_data() {
unsafe {
let data_ptr = core::ptr::addr_of_mut!(VDSO_DATA);
(*data_ptr).update();
(*data_ptr).time_update();
}
}

Expand Down
Loading