From 6110b6d1e95b379df3f618b23ca36ea4b654baf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Jan 2024 17:11:21 +0100 Subject: [PATCH 1/4] refactor: replace uses of get_boot_time with now_micros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/arch/aarch64/kernel/systemtime.rs | 5 +++++ src/arch/mod.rs | 3 --- src/arch/riscv64/kernel/systemtime.rs | 5 +++++ src/arch/x86_64/kernel/systemtime.rs | 5 +++++ src/executor/device.rs | 4 ++-- src/executor/network.rs | 3 +-- src/fs/mem.rs | 12 ++++++------ src/syscalls/timer.rs | 22 ++++++++++------------ src/time.rs | 4 +--- 9 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/arch/aarch64/kernel/systemtime.rs b/src/arch/aarch64/kernel/systemtime.rs index 68bc4fac81..748713f7ac 100644 --- a/src/arch/aarch64/kernel/systemtime.rs +++ b/src/arch/aarch64/kernel/systemtime.rs @@ -101,3 +101,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 { + get_boot_time() + super::processor::get_timer_ticks() +} diff --git a/src/arch/mod.rs b/src/arch/mod.rs index 881bd4790f..c093434eda 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -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::{ @@ -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, @@ -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, diff --git a/src/arch/riscv64/kernel/systemtime.rs b/src/arch/riscv64/kernel/systemtime.rs index 5903473c3c..7100aa3d72 100644 --- a/src/arch/riscv64/kernel/systemtime.rs +++ b/src/arch/riscv64/kernel/systemtime.rs @@ -4,3 +4,8 @@ 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 { + get_boot_time() + super::processor::get_timer_ticks() +} diff --git a/src/arch/x86_64/kernel/systemtime.rs b/src/arch/x86_64/kernel/systemtime.rs index c936b7cc4c..f89cc7ad7c 100644 --- a/src/arch/x86_64/kernel/systemtime.rs +++ b/src/arch/x86_64/kernel/systemtime.rs @@ -199,3 +199,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 { + get_boot_time() + super::processor::get_timer_ticks() +} diff --git a/src/executor/device.rs b/src/executor/device.rs index 971a6f0c6b..7e689e67e5 100644 --- a/src/executor/device.rs +++ b/src/executor/device.rs @@ -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; } @@ -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; } diff --git a/src/executor/network.rs b/src/executor/network.rs index 258a396ff7..96677786ea 100644 --- a/src/executor/network.rs +++ b/src/executor/network.rs @@ -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() { diff --git a/src/fs/mem.rs b/src/fs/mem.rs index 8c15ee5a3c..f482d011b5 100644 --- a/src/fs/mem.rs +++ b/src/fs/mem.rs @@ -48,7 +48,7 @@ struct RomFileInterface { impl ObjectInterface for RomFileInterface { fn read(&self, buf: &mut [u8]) -> Result { { - 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; @@ -114,7 +114,7 @@ pub struct RamFileInterface { impl ObjectInterface for RamFileInterface { fn read(&self, buf: &mut [u8]) -> Result { { - 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; @@ -141,7 +141,7 @@ impl ObjectInterface for RamFileInterface { } fn write(&self, buf: &[u8]) -> Result { - 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; @@ -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, @@ -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, @@ -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())), diff --git a/src/syscalls/timer.rs b/src/syscalls/timer.rs index 75ecf49a65..2e63005c3d 100644 --- a/src/syscalls/timer.rs +++ b/src/syscalls/timer.rs @@ -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 } _ => { @@ -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(); } } @@ -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); } diff --git a/src/time.rs b/src/time.rs index d2633d14b9..f62d55e108 100644 --- a/src/time.rs +++ b/src/time.rs @@ -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())) } } From a09c676afac351a8c4a87cd44accb57b3d369a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Jan 2024 18:04:19 +0100 Subject: [PATCH 2/4] refactor(arch): remove get_boot_time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/arch/aarch64/kernel/systemtime.rs | 6 +----- src/arch/riscv64/kernel/systemtime.rs | 8 ++------ src/arch/x86_64/kernel/systemtime.rs | 6 +----- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/arch/aarch64/kernel/systemtime.rs b/src/arch/aarch64/kernel/systemtime.rs index 748713f7ac..72bf702a9b 100644 --- a/src/arch/aarch64/kernel/systemtime.rs +++ b/src/arch/aarch64/kernel/systemtime.rs @@ -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( @@ -104,5 +100,5 @@ pub fn init() { /// Returns the current time in microseconds since UNIX epoch. pub fn now_micros() -> u64 { - get_boot_time() + super::processor::get_timer_ticks() + *BOOT_TIME.get().unwrap() + super::processor::get_timer_ticks() } diff --git a/src/arch/riscv64/kernel/systemtime.rs b/src/arch/riscv64/kernel/systemtime.rs index 7100aa3d72..df7f6d0185 100644 --- a/src/arch/riscv64/kernel/systemtime.rs +++ b/src/arch/riscv64/kernel/systemtime.rs @@ -1,11 +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 { - get_boot_time() + super::processor::get_timer_ticks() + warn!("time is currently stubbed"); + super::processor::get_timer_ticks() } diff --git a/src/arch/x86_64/kernel/systemtime.rs b/src/arch/x86_64/kernel/systemtime.rs index f89cc7ad7c..6b1f35122e 100644 --- a/src/arch/x86_64/kernel/systemtime.rs +++ b/src/arch/x86_64/kernel/systemtime.rs @@ -172,10 +172,6 @@ impl Rtc { static BOOT_TIME: OnceCell = 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 { .. } => { @@ -202,5 +198,5 @@ pub fn init() { /// Returns the current time in microseconds since UNIX epoch. pub fn now_micros() -> u64 { - get_boot_time() + super::processor::get_timer_ticks() + *BOOT_TIME.get().unwrap() + super::processor::get_timer_ticks() } From 370d9ba9410a305978a46dc7ca657a2df5d3e6b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Jan 2024 18:07:30 +0100 Subject: [PATCH 3/4] fix(aarch64): adjust time for non-zero timer on boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/arch/aarch64/kernel/systemtime.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/arch/aarch64/kernel/systemtime.rs b/src/arch/aarch64/kernel/systemtime.rs index 72bf702a9b..ebb939ea2e 100644 --- a/src/arch/aarch64/kernel/systemtime.rs +++ b/src/arch/aarch64/kernel/systemtime.rs @@ -87,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; } From 77e6e2952b8b429bdcbdcab42dd02ccc104e4036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 25 Jan 2024 18:14:08 +0100 Subject: [PATCH 4/4] fix(aarch64): fix overflow in get_timer_ticks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/arch/aarch64/kernel/processor.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/arch/aarch64/kernel/processor.rs b/src/arch/aarch64/kernel/processor.rs index 9d025ddbf4..4ef9c0aed7 100644 --- a/src/arch/aarch64/kernel/processor.rs +++ b/src/arch/aarch64/kernel/processor.rs @@ -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] @@ -226,7 +227,8 @@ pub fn detect_frequency() { fn __set_oneshot_timer(wakeup_time: Option) { 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!(