KVM: arm64: selftests: Test a timer set past the counter's wrap

Program an unmasked timer whose cval sits within long_wait_ms of the
counter's wrap while the guest's counter is at wait_ms, and expect no
interrupt. The guest's counter can't reach it, but a host that applies
the timer's offset by adding it to cval wraps the sum into the past,
and the timer fires at once. The one existing case with a cval past the
wrap, in the sanity checks, runs with the timer masked, so it gets no
interrupt either way.

Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
Link: https://patch.msgid.link/20261007074343.324269-4-fuad.tabba@linux.dev
Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
Fuad Tabba 2026-10-07 08:43:43 +01:00 committed by Marc Zyngier
parent 1dbb5a2b5a
commit 46e0f2c9d7

View File

@ -787,6 +787,30 @@ static void test_timers_in_the_past(enum arch_timer timer)
}
}
/*
* A cval within long_wait_ms of the counter's wrap while the counter sits at
* wait_ms: a deadline further away than the counter can reach. Unmasked, so
* an early ISTATUS shows up as an IRQ.
*/
static void test_timers_past_counter_wrap(enum arch_timer timer)
{
u64 cval = -msec_to_cycles(test_args.long_wait_ms);
int i;
for (i = 0; i < ARRAY_SIZE(sleep_method); i++) {
sleep_method_t sm = sleep_method[i];
local_irq_disable();
set_counter(timer, msec_to_cycles(test_args.wait_ms));
set_cval_irq(timer, cval, CTL_ENABLE);
sm(timer, msecs_to_usecs(test_args.wait_ms) + TIMEOUT_NO_IRQ_US);
local_irq_enable();
isb();
assert_irqs_handled(0);
timer_set_ctl(timer, CTL_IMASK);
}
}
static void test_long_timer_delays(enum arch_timer timer)
{
s32 tval = (s32)msec_to_cycles(test_args.long_wait_ms);
@ -806,6 +830,7 @@ static void guest_run_iteration(enum arch_timer timer)
test_basic_functionality(timer);
test_timers_sanity_checks(timer);
test_timers_past_counter_wrap(timer);
test_timers_above_tval_max(timer);
test_timers_in_the_past(timer);