diff options
| author | Bibo Mao <maobibo@loongson.cn> | 2025-11-28 14:49:47 +0800 |
|---|---|---|
| committer | Huacai Chen <chenhuacai@loongson.cn> | 2025-11-28 14:49:47 +0800 |
| commit | 4e8824094069b04e3b3583d855c975ccb6a9bec5 (patch) | |
| tree | 43f5af1d62ce15e0e4f5e52e712b3fed68b74eb9 /tools | |
| parent | df41742343fad11fde06e085096003d64599785f (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>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/testing/selftests/kvm/loongarch/arch_timer.c | 40 |
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(); } |