* [PATCH 2/2] gpu: nova-core: add support for GPU timer block.
@ 2026-10-26 2:56 ` Dave Airlie via B4 Relay
0 siblings, 0 replies; 10+ messages in thread
From: Dave Airlie via B4 Relay @ 2026-10-26 2:56 UTC (permalink / raw)
To: Andreas Hindborg, Boqun Feng, FUJITA Tomonori, Lyude Paul,
Gary Guo, Danilo Krummrich, Alexandre Courbot
Cc: rust-for-linux, nova-gpu, Dave Airlie
From: Dave Airlie <airlied@redhat.com>
This is needed to calculate the system timer offset that is passed
to GSP init.
2 HALs exist:
a) tu102 is the gv100 path from open-gpu, the priv level is checked
and the cpu time is written to the gpu timer. no offset is used.
b) gh100 is the gh100 path from open-gpu, where the secure system
timer is read, the offset is calculated and on everything after
GH100 the offset gets written to secure registers, and also
sent to GSP.
Signed-off-by: Dave Airlie <airlied@redhat.com>
---
drivers/gpu/nova-core/gpu.rs | 5 +++
drivers/gpu/nova-core/nova_core.rs | 1 +
drivers/gpu/nova-core/regs.rs | 40 +++++++++++++++++++++
drivers/gpu/nova-core/timer.rs | 37 +++++++++++++++++++
drivers/gpu/nova-core/timer/hal.rs | 32 +++++++++++++++++
drivers/gpu/nova-core/timer/hal/gh100.rs | 61 ++++++++++++++++++++++++++++++++
drivers/gpu/nova-core/timer/hal/tu102.rs | 55 ++++++++++++++++++++++++++++
7 files changed, 231 insertions(+)
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 4e59072cab50..85ff4a98d783 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -53,6 +53,7 @@
GpuMm,
VramAddress, //
},
+ timer::Timer,
vgpu::VgpuManager, //
};
@@ -331,6 +332,8 @@ struct GspResources<'gpu> {
// TODO: use different resource types for each boot method, and make the relevant Gsp methods
// generic against them.
fsp: Option<Fsp<'gpu>>,
+ /// Timer instance - contains offset
+ timer: Timer,
/// vGPU state detected before GSP boot.
vgpu: VgpuManager,
/// GSP runtime data.
@@ -497,6 +500,8 @@ pub(crate) fn new<'a>(
fsp: Fsp::try_new(dev, bar, spec.chipset)?,
+ timer: Timer::new(bar, spec.chipset)?,
+
vgpu: VgpuManager::new(pdev, spec.chipset, fsp.as_mut()),
gsp <- Gsp::new(pdev, bar),
diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs
index a8f6dc22057b..ee59d81e5105 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -27,6 +27,7 @@
mod sbuffer;
#[cfg(CONFIG_NOVA_CORE_SELFTESTS)]
mod selftest;
+mod timer;
mod vbios;
mod vgpu;
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index 88662da634dc..d5c67625b561 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -419,6 +419,24 @@ pub(crate) fn mem_scrubbing_done(self) -> bool {
}
}
+// PTIMER
+
+register! {
+ base: NovaRegisters;
+
+ pub(crate) NV_PTIMER_TIME_PRIV_LEVEL_MASK(u32) @ 0x00009430 {
+ 4:4 level0 => bool;
+ }
+
+ pub(crate) NV_PTIMER_TIME_0(u32) @ 0x00009400 {
+ 31:5 nsec;
+ }
+
+ pub(crate) NV_PTIMER_TIME_1(u32) @ 0x00009410 {
+ 28:0 nsec;
+ }
+}
+
// The modules below provide registers that are not identical on all supported chips. They should
// only be used in HAL modules.
@@ -520,6 +538,28 @@ pub(crate) mod gh100 {
31:0 fsp_boot_complete;
}
}
+
+ // PGC6/TIMER
+ register! {
+ base: NovaRegisters;
+
+ pub(crate) NV_PGC6_SCI_SEC_TIMER_TIME_0(u32) @ 0x00118f54 {
+ 31:5 nsec;
+ }
+
+ pub(crate) NV_PGC6_SCI_SEC_TIMER_TIME_1(u32) @ 0x00118f58 {
+ 28:0 nsec;
+ }
+
+ pub(crate) NV_PGC6_SCI_SYS_TIMER_OFFSET_0(u32) @ 0x00118df4 {
+ 0:0 update;
+ 31:5 nsec;
+ }
+
+ pub(crate) NV_PGC6_SCI_SYS_TIMER_OFFSET_1(u32) @ 0x00118df8 {
+ 28:0 nsec;
+ }
+ }
}
pub(crate) mod gb202 {
diff --git a/drivers/gpu/nova-core/timer.rs b/drivers/gpu/nova-core/timer.rs
new file mode 100644
index 000000000000..7fcb9cff8648
--- /dev/null
+++ b/drivers/gpu/nova-core/timer.rs
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+
+mod hal;
+
+use kernel::{
+ prelude::*,
+ time::*, //
+};
+
+use crate::{
+ driver::Bar0,
+ gpu::Chipset, //
+};
+
+#[pin_data]
+pub(crate) struct Timer {
+ chipset: Chipset,
+ sys_timer_offset_ns: i64,
+}
+
+impl Timer {
+ pub(crate) fn new(bar: Bar0<'_>, chipset: Chipset) -> Result<Self> {
+ Ok(Self {
+ chipset,
+ sys_timer_offset_ns: hal::timer_hal(chipset).init(chipset, bar)?,
+ })
+ }
+
+ #[expect(dead_code)]
+ pub(crate) fn sys_timer_offset_ns(&self) -> i64 {
+ self.sys_timer_offset_ns
+ }
+}
+
+pub(crate) fn get_cpu_time_ns() -> i64 {
+ Instant::<Monotonic>::now().as_nanos()
+}
diff --git a/drivers/gpu/nova-core/timer/hal.rs b/drivers/gpu/nova-core/timer/hal.rs
new file mode 100644
index 000000000000..2a383cf7688c
--- /dev/null
+++ b/drivers/gpu/nova-core/timer/hal.rs
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use kernel::prelude::*;
+
+use crate::{
+ driver::Bar0,
+ gpu::{
+ Architecture,
+ Chipset, //
+ },
+};
+
+mod gh100;
+mod tu102;
+
+pub(crate) trait TimerHal {
+ /// return system timer offset ns
+ fn init(&self, chipset: Chipset, bar: Bar0<'_>) -> Result<i64>;
+
+ /// read the timer
+ #[allow(dead_code)]
+ fn timer_read(&self, bar: Bar0<'_>) -> u64;
+}
+
+pub(super) fn timer_hal(chipset: Chipset) -> &'static dyn TimerHal {
+ match chipset.arch() {
+ Architecture::Turing | Architecture::Ampere | Architecture::Ada => tu102::TU102_HAL,
+ Architecture::Hopper | Architecture::BlackwellGB10x | Architecture::BlackwellGB20x => {
+ gh100::GH100_HAL
+ }
+ }
+}
diff --git a/drivers/gpu/nova-core/timer/hal/gh100.rs b/drivers/gpu/nova-core/timer/hal/gh100.rs
new file mode 100644
index 000000000000..e917446e7b01
--- /dev/null
+++ b/drivers/gpu/nova-core/timer/hal/gh100.rs
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use super::TimerHal;
+
+use kernel::{
+ io::Io,
+ prelude::*, //
+};
+
+use crate::{
+ driver::Bar0,
+ gpu::Chipset,
+ regs,
+ timer,
+ timer::hal::tu102, //
+};
+
+struct Gh100;
+
+pub(crate) fn timer_time(bar: Bar0<'_>, chipset: Chipset, time_ns: u64) -> Result<u64> {
+ let sec_hi2 = u32::from(bar.read(regs::gh100::NV_PGC6_SCI_SEC_TIMER_TIME_1));
+ let sec_timer_ns: u64;
+ loop {
+ let sec_lo = u32::from(bar.read(regs::gh100::NV_PGC6_SCI_SEC_TIMER_TIME_0));
+ let sec_hi = u32::from(bar.read(regs::gh100::NV_PGC6_SCI_SEC_TIMER_TIME_1));
+ if sec_hi == sec_hi2 {
+ sec_timer_ns = u64::from(sec_hi) << 32 | u64::from(sec_lo);
+ break;
+ }
+ }
+
+ let sys_timer_offset_ns = time_ns - sec_timer_ns;
+
+ // kfspRequiresBug3957833WAR_HAL
+ if chipset != Chipset::GH100 {
+ bar.write_reg(
+ regs::gh100::NV_PGC6_SCI_SYS_TIMER_OFFSET_1::zeroed()
+ .try_with_nsec((sys_timer_offset_ns >> 32) as u32)?,
+ );
+ bar.write_reg(
+ regs::gh100::NV_PGC6_SCI_SYS_TIMER_OFFSET_0::zeroed()
+ .try_with_nsec((time_ns & 0xffffffff) as u32)?,
+ );
+ }
+ Ok(sys_timer_offset_ns)
+}
+
+impl TimerHal for Gh100 {
+ fn init(&self, chipset: Chipset, bar: Bar0<'_>) -> Result<i64> {
+ let cpu: i64 = timer::get_cpu_time_ns();
+ let sys_timer_offset_ns = timer_time(bar, chipset, cpu as u64)?;
+ Ok(sys_timer_offset_ns as i64)
+ }
+
+ fn timer_read(&self, bar: Bar0<'_>) -> u64 {
+ tu102::timer_read(bar)
+ }
+}
+
+const GH100: Gh100 = Gh100;
+pub(super) const GH100_HAL: &dyn TimerHal = &GH100;
diff --git a/drivers/gpu/nova-core/timer/hal/tu102.rs b/drivers/gpu/nova-core/timer/hal/tu102.rs
new file mode 100644
index 000000000000..06ef88171f58
--- /dev/null
+++ b/drivers/gpu/nova-core/timer/hal/tu102.rs
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use super::TimerHal;
+
+use kernel::{
+ io::Io,
+ prelude::*, //
+};
+
+use crate::{
+ driver::Bar0,
+ gpu::Chipset,
+ regs,
+ timer, //
+};
+struct Tu102;
+
+pub(crate) fn timer_read(bar: Bar0<'_>) -> u64 {
+ let hi2: u32 = u32::from(bar.read(regs::NV_PTIMER_TIME_1));
+ loop {
+ let lo = u32::from(bar.read(regs::NV_PTIMER_TIME_0));
+ let hi = u32::from(bar.read(regs::NV_PTIMER_TIME_1));
+ if hi == hi2 {
+ return u64::from(hi) << 32 | u64::from(lo);
+ }
+ }
+}
+
+pub(crate) fn timer_time(bar: Bar0<'_>, time_ns: u64) -> Result {
+ if bar.read(regs::NV_PTIMER_TIME_PRIV_LEVEL_MASK).level0() {
+ bar.write_reg(regs::NV_PTIMER_TIME_1::zeroed().try_with_nsec((time_ns >> 32) as u32)?);
+ bar.write_reg(
+ regs::NV_PTIMER_TIME_0::zeroed().try_with_nsec((time_ns & 0xffffffff) as u32)?,
+ );
+ Ok(())
+ } else {
+ Err(EINVAL)
+ }
+}
+
+impl TimerHal for Tu102 {
+ fn init(&self, _chipset: Chipset, bar: Bar0<'_>) -> Result<i64> {
+ let cpu = timer::get_cpu_time_ns();
+
+ timer_time(bar, cpu as u64)?;
+ Ok(0_i64)
+ }
+
+ fn timer_read(&self, bar: Bar0<'_>) -> u64 {
+ timer_read(bar)
+ }
+}
+
+const TU102: Tu102 = Tu102;
+pub(super) const TU102_HAL: &dyn TimerHal = &TU102;
--
2.56.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH 2/2] gpu: nova-core: add support for GPU timer block.
2026-10-26 2:56 ` Dave Airlie via B4 Relay
(?)
@ 2026-10-26 9:07 ` sashiko-bot
-1 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-10-26 9:07 UTC (permalink / raw)
To: Dave Airlie, Andreas Hindborg, Boqun Feng, FUJITA Tomonori,
Lyude Paul, Gary Guo, Danilo Krummrich, Alexandre Courbot
Cc: nova-gpu, ojeda
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] gpu: nova-core: infinite loop on rollover in timer_read() and timer_time()
- [High] gpu: nova-core: unshifted nsec value in timer_time() causes EOVERFLOW
- [High] gpu: nova-core: wrong value and missing update bit in gh100::timer_time()
- [High] gpu: nova-core: u64 underflow on negative offset in gh100::timer_time()
--
commit 5b1f5a3805c6ab01f8b19ff029b873428252d6b5
Author: Dave Airlie <airlied@redhat.com>
gpu: nova-core: add support for GPU timer block.
This commit adds GPU timer block support to nova-core with HAL implementations
for TU102 and GH100 to initialize the GPU timer or calculate the system timer
offset for GSP initialization.
> diff --git a/drivers/gpu/nova-core/timer/hal/gh100.rs b/drivers/gpu/nova-core/timer/hal/gh100.rs
> new file mode 100644
> index 0000000000000..e917446e7b01e
> --- /dev/null
> +++ b/drivers/gpu/nova-core/timer/hal/gh100.rs
> @@ -0,0 +1,61 @@
[ ... ]
> +pub(crate) fn timer_time(bar: Bar0<'_>, chipset: Chipset, time_ns: u64) -> Result<u64> {
> + let sec_hi2 = u32::from(bar.read(regs::gh100::NV_PGC6_SCI_SEC_TIMER_TIME_1));
> + let sec_timer_ns: u64;
> + loop {
> + let sec_lo = u32::from(bar.read(regs::gh100::NV_PGC6_SCI_SEC_TIMER_TIME_0));
> + let sec_hi = u32::from(bar.read(regs::gh100::NV_PGC6_SCI_SEC_TIMER_TIME_1));
> + if sec_hi == sec_hi2 {
> + sec_timer_ns = u64::from(sec_hi) << 32 | u64::from(sec_lo);
> + break;
> + }
> + }
[Severity: High]
Can this loop in timer_time() in drivers/gpu/nova-core/timer/hal/gh100.rs
spin forever if NV_PGC6_SCI_SEC_TIMER_TIME_0 rolls over?
During Gpu::new() -> Timer::new() -> Gh100::init() -> timer_time(), sec_hi2
is read from NV_PGC6_SCI_SEC_TIMER_TIME_1 once before the loop and is never
updated if sec_hi != sec_hi2. If the lower 32-bit register wraps around
between the initial read of sec_hi2 and the in-loop read of sec_hi, sec_hi
increments while sec_hi2 remains at its old value, causing the loop to never
terminate. Should sec_hi2 be made mutable and updated to sec_hi at the end
of each iteration?
> +
> + let sys_timer_offset_ns = time_ns - sec_timer_ns;
> +
> + // kfspRequiresBug3957833WAR_HAL
> + if chipset != Chipset::GH100 {
> + bar.write_reg(
> + regs::gh100::NV_PGC6_SCI_SYS_TIMER_OFFSET_1::zeroed()
> + .try_with_nsec((sys_timer_offset_ns >> 32) as u32)?,
> + );
[Severity: High]
What happens in timer_time() in drivers/gpu/nova-core/timer/hal/gh100.rs when
time_ns is smaller than sec_timer_ns?
In drivers/gpu/nova-core/timer.rs, get_cpu_time_ns() returns monotonic time
since OS boot via Instant::<Monotonic>::now().as_nanos(), whereas
sec_timer_ns is read from the always-on PGC6 timer which persists across warm
reboots, kexec, and guest VM restarts.
When time_ns < sec_timer_ns, the u64 subtraction time_ns - sec_timer_ns will
underflow and panic the kernel when CONFIG_RUST_OVERFLOW_CHECKS=y. Even if
wrapping subtraction is used, a negative 64-bit two's-complement offset has
its upper bits set to 1, so passing an unmasked (sys_timer_offset_ns >> 32)
as u32 to NV_PGC6_SCI_SYS_TIMER_OFFSET_1::zeroed().try_with_nsec() will
exceed the 29-bit (28:0 nsec) field and fail with EOVERFLOW.
> + bar.write_reg(
> + regs::gh100::NV_PGC6_SCI_SYS_TIMER_OFFSET_0::zeroed()
> + .try_with_nsec((time_ns & 0xffffffff) as u32)?,
> + );
> + }
> + Ok(sys_timer_offset_ns)
> +}
[Severity: High]
Are there a few issues with how NV_PGC6_SCI_SYS_TIMER_OFFSET_0 is written
here in timer_time() in drivers/gpu/nova-core/timer/hal/gh100.rs?
In drivers/gpu/nova-core/regs.rs, NV_PGC6_SCI_SYS_TIMER_OFFSET_0 is defined
as:
pub(crate) NV_PGC6_SCI_SYS_TIMER_OFFSET_0(u32) @ 0x00118df4 {
0:0 update;
31:5 nsec;
}
First, this call passes (time_ns & 0xffffffff) as u32 instead of the lower
bits of sys_timer_offset_ns, and it does not set the update bit (0:0 update)
to trigger hardware latching of the offset.
Second, because nsec is a 27-bit field at bits 31:5, try_with_nsec() checks
that the argument fits in 27 bits (< 1 << 27) and then shifts it left by 5.
Passing an unshifted 32-bit value causes try_with_nsec() to fail with
EOVERFLOW whenever any of bits 31:27 are non-zero, and shifts the value left
by an extra 5 bits when bits 31:27 happen to be zero. Should this pass
((sys_timer_offset_ns as u32) >> 5) and set update?
> diff --git a/drivers/gpu/nova-core/timer/hal/tu102.rs b/drivers/gpu/nova-core/timer/hal/tu102.rs
> new file mode 100644
> index 0000000000000..06ef88171f587
> --- /dev/null
> +++ b/drivers/gpu/nova-core/timer/hal/tu102.rs
> @@ -0,0 +1,55 @@
[ ... ]
> +pub(crate) fn timer_read(bar: Bar0<'_>) -> u64 {
> + let hi2: u32 = u32::from(bar.read(regs::NV_PTIMER_TIME_1));
> + loop {
> + let lo = u32::from(bar.read(regs::NV_PTIMER_TIME_0));
> + let hi = u32::from(bar.read(regs::NV_PTIMER_TIME_1));
> + if hi == hi2 {
> + return u64::from(hi) << 32 | u64::from(lo);
> + }
> + }
> +}
[Severity: High]
Similarly, in timer_read() in drivers/gpu/nova-core/timer/hal/tu102.rs, hi2
is read once before the loop and never updated to hi when hi != hi2. If
NV_PTIMER_TIME_0 wraps around between the initial read of hi2 and the in-loop
read of hi, won't this loop spin forever?
> +
> +pub(crate) fn timer_time(bar: Bar0<'_>, time_ns: u64) -> Result {
> + if bar.read(regs::NV_PTIMER_TIME_PRIV_LEVEL_MASK).level0() {
> + bar.write_reg(regs::NV_PTIMER_TIME_1::zeroed().try_with_nsec((time_ns >> 32) as u32)?);
> + bar.write_reg(
> + regs::NV_PTIMER_TIME_0::zeroed().try_with_nsec((time_ns & 0xffffffff) as u32)?,
> + );
[Severity: High]
In timer_time() in drivers/gpu/nova-core/timer/hal/tu102.rs, NV_PTIMER_TIME_0
also defines nsec as a 27-bit field at bits 31:5:
pub(crate) NV_PTIMER_TIME_0(u32) @ 0x00009400 {
31:5 nsec;
}
When called during probe via Gpu::new() -> Timer::new() -> Tu102::init() ->
timer_time(), won't passing the unshifted (time_ns & 0xffffffff) as u32 to
try_with_nsec() return EOVERFLOW whenever bits 31:27 of the low 32-bit
timestamp are non-zero, and otherwise shift the value left by an extra 5
bits?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261026-drm-rust-next-v1-0-14a4ae469175@redhat.com?part=2
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH 2/2] gpu: nova-core: add support for GPU timer block.
2026-10-26 2:56 ` Dave Airlie via B4 Relay
(?)
(?)
@ 2026-10-26 12:33 ` Danilo Krummrich
-1 siblings, 0 replies; 10+ messages in thread
From: Danilo Krummrich @ 2026-10-26 12:33 UTC (permalink / raw)
To: Dave Airlie via B4 Relay
Cc: airlied, Andreas Hindborg, Boqun Feng, FUJITA Tomonori,
Lyude Paul, Gary Guo, Alexandre Courbot, rust-for-linux, nova-gpu
On Mon Oct 26, 2026 at 3:56 AM CET, Dave Airlie via B4 Relay wrote:
> diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
> index 88662da634dc..d5c67625b561 100644
> --- a/drivers/gpu/nova-core/regs.rs
> +++ b/drivers/gpu/nova-core/regs.rs
> @@ -419,6 +419,24 @@ pub(crate) fn mem_scrubbing_done(self) -> bool {
> }
> }
>
> +// PTIMER
> +
> +register! {
> + base: NovaRegisters;
> +
> + pub(crate) NV_PTIMER_TIME_PRIV_LEVEL_MASK(u32) @ 0x00009430 {
> + 4:4 level0 => bool;
> + }
> +
> + pub(crate) NV_PTIMER_TIME_0(u32) @ 0x00009400 {
> + 31:5 nsec;
> + }
> +
> + pub(crate) NV_PTIMER_TIME_1(u32) @ 0x00009410 {
> + 28:0 nsec;
> + }
> +}
> +
> // The modules below provide registers that are not identical on all supported chips. They should
> // only be used in HAL modules.
>
> @@ -520,6 +538,28 @@ pub(crate) mod gh100 {
> 31:0 fsp_boot_complete;
> }
> }
> +
> + // PGC6/TIMER
> + register! {
> + base: NovaRegisters;
> +
> + pub(crate) NV_PGC6_SCI_SEC_TIMER_TIME_0(u32) @ 0x00118f54 {
> + 31:5 nsec;
> + }
> +
> + pub(crate) NV_PGC6_SCI_SEC_TIMER_TIME_1(u32) @ 0x00118f58 {
> + 28:0 nsec;
> + }
> +
> + pub(crate) NV_PGC6_SCI_SYS_TIMER_OFFSET_0(u32) @ 0x00118df4 {
> + 0:0 update;
> + 31:5 nsec;
> + }
> +
> + pub(crate) NV_PGC6_SCI_SYS_TIMER_OFFSET_1(u32) @ 0x00118df8 {
> + 28:0 nsec;
> + }
> + }
> }
Timer specific register definitions should go into the timer module.
> +#[pin_data]
Why is this #[pin_data]?
> +pub(crate) struct Timer {
> + chipset: Chipset,
Why does this carry the Chipset?
> + sys_timer_offset_ns: i64,
> +}
More generally, what's the purpose of this struct? What does it represent?
Nothing seems to tie this object to a particular GPU or prevents constructing
multiple instances for the same GPU.
It also doesn't seem to provide any access to the underlying HAL's functions?
> +impl Timer {
> + pub(crate) fn new(bar: Bar0<'_>, chipset: Chipset) -> Result<Self> {
> + Ok(Self {
> + chipset,
> + sys_timer_offset_ns: hal::timer_hal(chipset).init(chipset, bar)?,
> + })
> + }
> +
> + #[expect(dead_code)]
> + pub(crate) fn sys_timer_offset_ns(&self) -> i64 {
> + self.sys_timer_offset_ns
> + }
What do we need this method for?
> +}
> +
> +pub(crate) fn get_cpu_time_ns() -> i64 {
> + Instant::<Monotonic>::now().as_nanos()
> +}
I don't think this helper adds much value, let's just make users call
Instant::<Monotonic>::now().as_nanos() themselves.
^ permalink raw reply [flat|nested] 10+ messages in thread