Skip to content

Commit

Permalink
Merge pull request #1041 from mkroening/aarch64-timer-overflow
Browse files Browse the repository at this point in the history
fix: overflow in time calculation on AArch64
  • Loading branch information
stlankes authored Jan 25, 2024
2 parents b94c818 + 77e6e29 commit 58fa692
Show file tree
Hide file tree
Showing 10 changed files with 40 additions and 42 deletions.
6 changes: 4 additions & 2 deletions src/arch/aarch64/kernel/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ pub fn shutdown() -> ! {
pub fn get_timer_ticks() -> u64 {
// We simulate a timer with a 1 microsecond resolution by taking the CPU timestamp
// and dividing it by the CPU frequency in MHz.
(1000000 * get_timestamp()) / u64::from(CPU_FREQUENCY.get())
let ticks = 1000000 * u128::from(get_timestamp()) / u128::from(CPU_FREQUENCY.get());
u64::try_from(ticks).unwrap()
}

#[inline]
Expand Down Expand Up @@ -226,7 +227,8 @@ pub fn detect_frequency() {
fn __set_oneshot_timer(wakeup_time: Option<u64>) {
if let Some(wt) = wakeup_time {
// wt is the absolute wakeup time in microseconds based on processor::get_timer_ticks.
let deadline: u64 = (wt * u64::from(CPU_FREQUENCY.get())) / 1000000;
let deadline = u128::from(wt) * u128::from(CPU_FREQUENCY.get()) / 1000000;
let deadline = u64::try_from(deadline).unwrap();

unsafe {
asm!(
Expand Down
12 changes: 7 additions & 5 deletions src/arch/aarch64/kernel/systemtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ fn rtc_read(off: usize) -> u32 {
value
}

pub fn get_boot_time() -> u64 {
*BOOT_TIME.get().unwrap()
}

pub fn init() {
let dtb = unsafe {
Dtb::from_raw(core::ptr::from_exposed_addr(
Expand Down Expand Up @@ -91,7 +87,8 @@ pub fn init() {
info!("Hermit booted on {boot_time}");

let micros = u64::try_from(boot_time.unix_timestamp_nanos() / 1000).unwrap();
BOOT_TIME.set(micros).unwrap();
let current_ticks = super::processor::get_timer_ticks();
BOOT_TIME.set(micros - current_ticks).unwrap();

return;
}
Expand All @@ -101,3 +98,8 @@ pub fn init() {
PL031_ADDRESS.set(VirtAddr::zero()).unwrap();
BOOT_TIME.set(0).unwrap();
}

/// Returns the current time in microseconds since UNIX epoch.
pub fn now_micros() -> u64 {
*BOOT_TIME.get().unwrap() + super::processor::get_timer_ticks()
}
3 changes: 0 additions & 3 deletions src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ cfg_if::cfg_if! {
pub use self::aarch64::kernel::processor::set_oneshot_timer;
pub use self::aarch64::kernel::scheduler;
pub use self::aarch64::kernel::switch;
pub use self::aarch64::kernel::systemtime::get_boot_time;
#[cfg(feature = "smp")]
pub use self::aarch64::kernel::application_processor_init;
pub use self::aarch64::kernel::{
Expand All @@ -43,7 +42,6 @@ cfg_if::cfg_if! {
pub use self::x86_64::kernel::processor;
pub use self::x86_64::kernel::scheduler;
pub use self::x86_64::kernel::switch;
pub use self::x86_64::kernel::systemtime::get_boot_time;
#[cfg(target_os = "none")]
pub use self::x86_64::kernel::{
boot_application_processors,
Expand All @@ -61,7 +59,6 @@ cfg_if::cfg_if! {
#[cfg(feature = "smp")]
pub use self::riscv64::kernel::application_processor_init;
pub use self::riscv64::kernel::processor::{self, set_oneshot_timer, wakeup_core};
pub use self::riscv64::kernel::systemtime::get_boot_time;
pub use self::riscv64::kernel::{
boot_application_processors,
boot_processor_init,
Expand Down
7 changes: 4 additions & 3 deletions src/arch/riscv64/kernel/systemtime.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use log::warn;

pub fn get_boot_time() -> u64 {
warn!("`get_boot_time` is currently stubbed");
0
/// Returns the current time in microseconds since UNIX epoch.
pub fn now_micros() -> u64 {
warn!("time is currently stubbed");
super::processor::get_timer_ticks()
}
9 changes: 5 additions & 4 deletions src/arch/x86_64/kernel/systemtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,6 @@ impl Rtc {

static BOOT_TIME: OnceCell<u64> = OnceCell::new();

pub fn get_boot_time() -> u64 {
*BOOT_TIME.get().unwrap()
}

pub fn init() {
let boot_time = match boot_info().platform_info {
PlatformInfo::Multiboot { .. } => {
Expand All @@ -199,3 +195,8 @@ pub fn init() {
let micros = u64::try_from(boot_time.unix_timestamp_nanos() / 1000).unwrap();
BOOT_TIME.set(micros).unwrap();
}

/// Returns the current time in microseconds since UNIX epoch.
pub fn now_micros() -> u64 {
*BOOT_TIME.get().unwrap() + super::processor::get_timer_ticks()
}
4 changes: 2 additions & 2 deletions src/executor/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl<'a> NetworkInterface<'a> {

// use the current time based on the wall-clock time as seed
let mut config = Config::new(hardware_addr);
config.random_seed = (arch::get_boot_time() + arch::processor::get_timer_ticks()) / 1000000;
config.random_seed = (arch::kernel::systemtime::now_micros()) / 1000000;
if device.capabilities().medium == Medium::Ethernet {
config.hardware_addr = hardware_addr;
}
Expand Down Expand Up @@ -129,7 +129,7 @@ impl<'a> NetworkInterface<'a> {

// use the current time based on the wall-clock time as seed
let mut config = Config::new(hardware_addr);
config.random_seed = (arch::get_boot_time() + arch::processor::get_timer_ticks()) / 1000000;
config.random_seed = (arch::kernel::systemtime::now_micros()) / 1000000;
if device.capabilities().medium == Medium::Ethernet {
config.hardware_addr = hardware_addr;
}
Expand Down
3 changes: 1 addition & 2 deletions src/executor/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ fn start_endpoint() -> u16 {

#[inline]
pub(crate) fn now() -> Instant {
let microseconds = arch::processor::get_timer_ticks() + arch::get_boot_time();
Instant::from_micros_const(microseconds.try_into().unwrap())
Instant::from_micros_const(arch::kernel::systemtime::now_micros().try_into().unwrap())
}

async fn network_run() {
Expand Down
12 changes: 6 additions & 6 deletions src/fs/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ struct RomFileInterface {
impl ObjectInterface for RomFileInterface {
fn read(&self, buf: &mut [u8]) -> Result<usize, IoError> {
{
let microseconds = arch::processor::get_timer_ticks() + arch::get_boot_time();
let microseconds = arch::kernel::systemtime::now_micros();
let mut guard = self.inner.write();
guard.attr.st_atime = microseconds / 1_000_000;
guard.attr.st_atime_nsec = (microseconds % 1_000_000) * 1000;
Expand Down Expand Up @@ -114,7 +114,7 @@ pub struct RamFileInterface {
impl ObjectInterface for RamFileInterface {
fn read(&self, buf: &mut [u8]) -> Result<usize, IoError> {
{
let microseconds = arch::processor::get_timer_ticks() + arch::get_boot_time();
let microseconds = arch::kernel::systemtime::now_micros();
let mut guard = self.inner.write();
guard.attr.st_atime = microseconds / 1_000_000;
guard.attr.st_atime_nsec = (microseconds % 1_000_000) * 1000;
Expand All @@ -141,7 +141,7 @@ impl ObjectInterface for RamFileInterface {
}

fn write(&self, buf: &[u8]) -> Result<usize, IoError> {
let microseconds = arch::processor::get_timer_ticks() + arch::get_boot_time();
let microseconds = arch::kernel::systemtime::now_micros();
let mut guard = self.inner.write();
let mut pos_guard = self.pos.lock();
let pos = *pos_guard;
Expand Down Expand Up @@ -214,7 +214,7 @@ impl VfsNode for RomFile {

impl RomFile {
pub unsafe fn new(ptr: *const u8, length: usize, mode: AccessPermission) -> Self {
let microseconds = arch::processor::get_timer_ticks() + arch::get_boot_time();
let microseconds = arch::kernel::systemtime::now_micros();
let attr = FileAttr {
st_size: length.try_into().unwrap(),
st_mode: mode | AccessPermission::S_IFREG,
Expand Down Expand Up @@ -270,7 +270,7 @@ impl VfsNode for RamFile {

impl RamFile {
pub fn new(mode: AccessPermission) -> Self {
let microseconds = arch::processor::get_timer_ticks() + arch::get_boot_time();
let microseconds = arch::kernel::systemtime::now_micros();
let attr = FileAttr {
st_mode: mode | AccessPermission::S_IFREG,
st_atime: microseconds / 1_000_000,
Expand Down Expand Up @@ -298,7 +298,7 @@ pub(crate) struct MemDirectory {

impl MemDirectory {
pub fn new(mode: AccessPermission) -> Self {
let microseconds = arch::processor::get_timer_ticks() + arch::get_boot_time();
let microseconds = arch::kernel::systemtime::now_micros();

Self {
inner: Arc::new(RwSpinLock::new(BTreeMap::new())),
Expand Down
22 changes: 10 additions & 12 deletions src/syscalls/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,12 @@ extern "C" fn __sys_clock_gettime(clock_id: u64, tp: *mut timespec) -> i32 {
let result = unsafe { &mut *tp };

match clock_id {
CLOCK_REALTIME | CLOCK_MONOTONIC => {
let mut microseconds = arch::processor::get_timer_ticks();

if clock_id == CLOCK_REALTIME {
microseconds += arch::get_boot_time();
}

*result = timespec::from_usec(microseconds);
CLOCK_REALTIME => {
*result = timespec::from_usec(arch::kernel::systemtime::now_micros());
0
}
CLOCK_MONOTONIC => {
*result = timespec::from_usec(arch::processor::get_timer_ticks());
0
}
_ => {
Expand Down Expand Up @@ -119,10 +117,10 @@ extern "C" fn __sys_clock_nanosleep(
+ (requested_time.tv_nsec as u64) / 1_000;

if flags & TIMER_ABSTIME > 0 {
microseconds -= arch::processor::get_timer_ticks();

if clock_id == CLOCK_REALTIME {
microseconds -= arch::get_boot_time();
microseconds -= arch::kernel::systemtime::now_micros();
} else {
microseconds -= arch::processor::get_timer_ticks();
}
}

Expand Down Expand Up @@ -164,7 +162,7 @@ extern "C" fn __sys_gettimeofday(tp: *mut timeval, tz: usize) -> i32 {
if let Some(result) = unsafe { tp.as_mut() } {
// Return the current time based on the wallclock time when we were booted up
// plus the current timer ticks.
let microseconds = arch::get_boot_time() + arch::processor::get_timer_ticks();
let microseconds = arch::kernel::systemtime::now_micros();
*result = timeval::from_usec(microseconds);
}

Expand Down
4 changes: 1 addition & 3 deletions src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ pub struct SystemTime(timespec);
impl SystemTime {
/// Returns the system time corresponding to "now".
pub fn now() -> Self {
let microseconds = arch::processor::get_timer_ticks() + arch::get_boot_time();

Self(timespec::from_usec(microseconds))
Self(timespec::from_usec(arch::kernel::systemtime::now_micros()))
}
}

Expand Down

0 comments on commit 58fa692

Please sign in to comment.