summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBibo Mao <maobibo@loongson.cn>2025-11-28 14:49:47 +0800
committerHuacai Chen <chenhuacai@loongson.cn>2025-11-28 14:49:47 +0800
commit4e8824094069b04e3b3583d855c975ccb6a9bec5 (patch)
tree43f5af1d62ce15e0e4f5e52e712b3fed68b74eb9
parentdf41742343fad11fde06e085096003d64599785f (diff)
KVM: LoongArch: selftests: Add SW emulated timer test case
This test case setup one-shot timer and execute idle instruction immediately to indicate giving up CPU, hypervisor will emulate SW hrtimer and wakeup vCPU when SW hrtimer is fired. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
-rw-r--r--tools/testing/selftests/kvm/loongarch/arch_timer.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/tools/testing/selftests/kvm/loongarch/arch_timer.c b/tools/testing/selftests/kvm/loongarch/arch_timer.c
index 6cc671671663..baa30fd296f5 100644
--- a/tools/testing/selftests/kvm/loongarch/arch_timer.c
+++ b/tools/testing/selftests/kvm/loongarch/arch_timer.c
@@ -9,6 +9,21 @@
#include "timer_test.h"
#include "ucall_common.h"
+static void do_idle(void)
+{
+ unsigned int intid;
+ unsigned long estat;
+
+ __asm__ __volatile__("idle 0" : : : "memory");
+
+ estat = csr_read(LOONGARCH_CSR_ESTAT);
+ intid = !!(estat & BIT(INT_TI));
+
+ /* Make sure pending timer IRQ arrived */
+ GUEST_ASSERT_EQ(intid, 1);
+ csr_write(CSR_TINTCLR_TI, LOONGARCH_CSR_TINTCLR);
+}
+
static void guest_irq_handler(struct ex_regs *regs)
{
unsigned int intid;
@@ -97,6 +112,30 @@ static void guest_test_oneshot_timer(uint32_t cpu)
}
}
+static void guest_test_emulate_timer(uint32_t cpu)
+{
+ uint32_t config_iter;
+ uint64_t xcnt_diff_us, us;
+ struct test_vcpu_shared_data *shared_data = &vcpu_shared_data[cpu];
+
+ local_irq_disable();
+ shared_data->nr_iter = 0;
+ us = msecs_to_usecs(test_args.timer_period_ms);
+ for (config_iter = 0; config_iter < test_args.nr_iter; config_iter++) {
+ shared_data->xcnt = timer_get_cycles();
+
+ /* Setup the next interrupt */
+ timer_set_next_cmp_ms(test_args.timer_period_ms, false);
+ do_idle();
+
+ xcnt_diff_us = cycles_to_usec(timer_get_cycles() - shared_data->xcnt);
+ __GUEST_ASSERT(xcnt_diff_us >= us,
+ "xcnt_diff_us = 0x%lx, us = 0x%lx.\n",
+ xcnt_diff_us, us);
+ }
+ local_irq_enable();
+}
+
static void guest_code(void)
{
uint32_t cpu = guest_get_vcpuid();
@@ -105,6 +144,7 @@ static void guest_code(void)
local_irq_enable();
guest_test_period_timer(cpu);
guest_test_oneshot_timer(cpu);
+ guest_test_emulate_timer(cpu);
GUEST_DONE();
}