Skip to content

arch/inte64: fix various issues for HPET - #20095

Open
raiden00pl wants to merge 4 commits into
apache:masterfrom
raiden00pl:nuttx-qemu-pr-hptim
Open

arch/inte64: fix various issues for HPET#20095
raiden00pl wants to merge 4 commits into
apache:masterfrom
raiden00pl:nuttx-qemu-pr-hptim

Conversation

@raiden00pl

@raiden00pl raiden00pl commented Sep 9, 2026

Copy link
Copy Markdown
Member

Summary

various issues with HPET found by NTFC with LPT tests:

  • arch/intel64: fix self-deadlock in intel64_oneshot_start()
  • arch/intel64: fix nxstyle issues in intel64_hpet.c
  • arch/intel64: keep the HPET ISR attached when the timer is stopped
  • arch/intel64: don't clear the oneshot handler from the HPET ISR

taken from #20030

Impact

required for SMP intel64 to pass LPT tests

Testing

CI pass: https://github.com/apache/nuttx/actions/runs/34236734404/job/102183306099?pr=20030

intel64_oneshot_start() takes g_oneshot_spin and then, if the timer is
already running, calls intel64_oneshot_cancel(), which takes the same
spinlock again.  Spinlocks are not recursive, so the CPU spins forever
on its own lock while holding the critical section; the HPET timer ISR
on another CPU then blocks on g_cpu_irqlock and the system hangs.

This is hit as soon as the tickless scheduler re-arms a running HPET
oneshot timer under SMP (ostest task_restart, LTP aio tests).

Stop the running timer inline instead of calling cancel: disable the
interrupt, detach the ISR so up_enable_irq() does not assert on a busy
IRQ, and clear the running flag.  The ISR, comparator and interrupt
enable are reprogrammed by the rest of the function anyway.

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
fix nxstyle issues in intel64_hpet.c

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
intel64_hpet_setisr() with a NULL handler detached the ISR with
irq_attach(irq, NULL), which installs irq_unexpected_isr().  The oneshot
driver does this every time the timer expires or is re-armed, so an HPET
interrupt already in flight to another CPU lands on the unexpected ISR
and panics the system:

  irq_unexpected_isr: ERROR irq: 34

seen under SMP with the LTP test suite.  Just mask the interrupt and keep
the ISR attached; intel64_oneshot_handler() already treats an interrupt
that arrives while the timer is not running as spurious.

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
intel64_oneshot_handler() cleared oneshot->handler and oneshot->arg
after picking them up, without holding g_oneshot_spin, while
intel64_oneshot_start() re-arms the timer under that lock from another
CPU.  Now that the HPET ISR stays attached across a re-arm, a stale
interrupt can interleave with start(): it reads the freshly installed
handler, clears it, and start() then sets running = true again, so the
genuine expiry that follows finds running == true with a NULL handler
and jumps to address zero from interrupt context (page fault at RIP 0
in the CPU0 IDLE task while the LTP lio_listio tests were running), or
the alarm is simply lost and the tickless system stops.

The handler and its argument are owned by start() and cancel(); the ISR
only needs to read them.  Leave them alone in the ISR and skip the call
if none is installed.  The remaining effect of a stale interrupt is an
early invocation of the alarm callback, which is harmless: the tickless
scheduler re-evaluates its expirations and re-arms the timer.

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
@github-actions github-actions Bot added Arch: x86_64 Issues related to the x86_64 architecture Size: S The size of the change in this PR is small labels Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: x86_64 Issues related to the x86_64 architecture Size: S The size of the change in this PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants