From: sashiko-bot@kernel.org
To: "Dave Airlie" <airlied@redhat.com>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Boqun Feng" <boqun@kernel.org>,
"FUJITA Tomonori" <fujita.tomonori@gmail.com>,
"Lyude Paul" <lyude@redhat.com>, "Gary Guo" <gary@garyguo.net>,
"Danilo Krummrich" <dakr@kernel.org>,
"Alexandre Courbot" <acourbot@nvidia.com>
Cc: nova-gpu@lists.linux.dev, ojeda@kernel.org
Subject: Re: [PATCH 2/2] gpu: nova-core: add support for GPU timer block.
Date: Mon, 26 Oct 2026 09:07:16 +0000 [thread overview]
Message-ID: <sashiko-outbox-184734@kernel.org> (raw)
In-Reply-To: <20261026-drm-rust-next-v1-2-14a4ae469175@redhat.com>
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
next prev parent reply other threads:[~2026-10-26 9:07 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-26 2:56 [PATCH 0/2] nova-core: add initial support for gpu timer Dave Airlie
2026-10-26 2:56 ` Dave Airlie via B4 Relay
2026-10-26 2:56 ` [PATCH 1/2] rust/timer: expose as_nanos for clock sources Dave Airlie
2026-10-26 2:56 ` Dave Airlie via B4 Relay
2026-10-26 10:09 ` Andreas Hindborg
2026-10-26 19:04 ` Danilo Krummrich
2026-10-26 2:56 ` [PATCH 2/2] gpu: nova-core: add support for GPU timer block Dave Airlie
2026-10-26 2:56 ` Dave Airlie via B4 Relay
2026-10-26 9:07 ` sashiko-bot [this message]
2026-10-26 12:33 ` Danilo Krummrich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-184734@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=airlied@redhat.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=fujita.tomonori@gmail.com \
--cc=gary@garyguo.net \
--cc=lyude@redhat.com \
--cc=nova-gpu@lists.linux.dev \
--cc=ojeda@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.