[kvm-unit-tests PATCH 4/4] arm: timer: Take into account other wake-up events for the TVAL test

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The TVAL test programs the timer to fire into the future, waits for an
interrupt using the WFI instruction, and when the instruction completes it
checks that the timer interrupt has fired. According to ARM DDI 0487G.a
there are other wake-up events that can cause the WFI to complete (listed
on page D1-2520), among them interrupts routed to a higher exception level,
where the hypervisor is running (if running under virtualization) or
firmware (if running on baremetal).

In practice, this is unlikely to have caused a false test failure, because
for a GICv3 (which the author assumes is a lot more common than a GICv4+)
the WFI is trapped by KVM and the VCPU thread is resumed only after the
timer asserts the interrupt, as the test expects.

Signed-off-by: Alexandru Elisei <alexandru.elisei@xxxxxxx>
---
 arm/timer.c | 39 +++++++++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 6 deletions(-)

diff --git a/arm/timer.c b/arm/timer.c
index 7b2d82896c74..8a668e8adac8 100644
--- a/arm/timer.c
+++ b/arm/timer.c
@@ -278,17 +278,44 @@ static void test_timer_cval(struct timer_info *info)
 	disable_timer(info);
 }
 
-static void test_timer_tval(struct timer_info *info)
+static void timer_do_wfi(struct timer_info *info)
 {
-	s32 left;
-
-	info->write_tval(read_sysreg(cntfrq_el0) / 100);	/* 10 ms */
 	local_irq_disable();
-	info->write_ctl(ARCH_TIMER_CTL_ENABLE);
+	if (info->irq_received)
+		goto out;
 	report_info("waiting for interrupt...");
 	wfi();
+out:
 	local_irq_enable();
-	left = info->read_tval();
+}
+
+static void test_timer_tval(struct timer_info *info)
+{
+	u64 time_10ms = read_sysreg(cntfrq_el0) / 100;
+	s32 left;
+	int i;
+
+	info->write_tval(time_10ms);
+	info->write_ctl(ARCH_TIMER_CTL_ENABLE);
+
+	for (;;) {
+		timer_do_wfi(info);
+		left = info->read_tval();
+		if (info->irq_received || left <= 0)
+			break;
+	}
+
+	/* Wait one second for the GIC to update the interrupt state. */
+	if (left <= 0 && !info->irq_received) {
+		for (i = 0; i < 10; i++) {
+			timer_do_wfi(info);
+			if (info->irq_received)
+				break;
+			mdelay(100);
+		}
+		left = info->read_tval();
+	}
+
 	report(info->irq_received, "interrupt received after TVAL/WFI");
 	report(left <= 0, "timer has expired");
 	report_info("TVAL is %d ticks", left);
-- 
2.34.1




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux