From 7fd17c9d7cf9ca9bc1fd5a7655951908ce23b881 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Sun, 26 Jul 2026 17:24:57 +0200 Subject: [PATCH] arch/x86_64: do not wrap the HPET oneshot on a deadline that has passed. intel64_timer_start_absolute() computed "expected - current_us" unsigned. A watchdog started with a delay of zero asks for a deadline that is already current, the subtraction wraps to nearly 2^64, and the comparator is set so far ahead that the timer never fires. The CONFIG_INTEL64_HPET_MIN_DELAY clamp in intel64_oneshot_start() cannot help: the wrapped value is enormous, not small. Ask for the shortest delay the hardware can take instead of wrapping, and let that existing minimum-delay logic pick it. It presents as ostest hanging in wdog_test with no output and no fault. apps/testing/ostest/wdog.c:281 calls wdtest_once(&test_wdog, param, 0), and NSEC2TICK() takes the next few delays (1ns, 10ns, ...) to zero ticks as well; wdtest_once() then spins forever in its "wait until the callback is triggered exactly once" loop. Impact: runtime, ARCH_INTEL64_HPET_ALARM only. Assisted-by: Claude:claude-opus-5 Signed-off-by: Marco Casaroli --- arch/x86_64/src/intel64/intel64_oneshot_lower.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86_64/src/intel64/intel64_oneshot_lower.c b/arch/x86_64/src/intel64/intel64_oneshot_lower.c index 86e8ecdd75a..40fbeec7754 100644 --- a/arch/x86_64/src/intel64/intel64_oneshot_lower.c +++ b/arch/x86_64/src/intel64/intel64_oneshot_lower.c @@ -149,10 +149,14 @@ static void intel64_timer_start_absolute(struct oneshot_lowerhalf_s *lower, (struct intel64_oneshot_lowerhalf_s *)lower; irqstate_t flags = spin_lock_irqsave(&g_oneshotlow_spin); int ret = intel64_oneshot_current(&priv->oneshot, ¤t_us); - uint64_t delta_us = expected - current_us; + uint64_t delta_us; DEBUGASSERT(ret == OK); + /* Use the shortest delay when the deadline has passed. */ + + delta_us = expected > current_us ? expected - current_us : 0; + ts.tv_sec = delta_us / USEC_PER_SEC; ts.tv_nsec = delta_us % USEC_PER_SEC * 1000ull; ret = intel64_oneshot_start(&priv->oneshot, intel64_oneshot_handler,