All of lore.kernel.org
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH] x86: apic: add apic timer mode transition test
@ 2017-09-29  1:06 Wanpeng Li
  0 siblings, 0 replies; only message in thread
From: Wanpeng Li @ 2017-09-29  1:06 UTC (permalink / raw)
  To: kvm; +Cc: Paolo Bonzini, Radim Krčmář, Wanpeng Li

From: Wanpeng Li <wanpeng.li@hotmail.com>

Add apic timer mode transition test.

Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
---
 lib/x86/apic-defs.h |  1 +
 x86/apic.c          | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/lib/x86/apic-defs.h b/lib/x86/apic-defs.h
index e0c3cca..a7bc6a0 100644
--- a/lib/x86/apic-defs.h
+++ b/lib/x86/apic-defs.h
@@ -91,6 +91,7 @@
 #define		APIC_TIMER_BASE_CLKIN		0x0
 #define		APIC_TIMER_BASE_TMBASE		0x1
 #define		APIC_TIMER_BASE_DIV		0x2
+#define		APIC_LVT_TIMER_MASK      	(3 << 17)
 #define		APIC_LVT_TIMER_ONESHOT		(0 << 17)
 #define		APIC_LVT_TIMER_PERIODIC		(1 << 17)
 #define		APIC_LVT_TIMER_TSCDEADLINE	(2 << 17)
diff --git a/x86/apic.c b/x86/apic.c
index eb78579..6cfb52d 100644
--- a/x86/apic.c
+++ b/x86/apic.c
@@ -458,6 +458,83 @@ static void test_physical_broadcast(void)
 	report("APIC physical broadcast shorthand", broadcast_received(ncpus));
 }
 
+void wait_until_tmcct_is_zero(uint32_t initial_count, bool stop_when_half)
+{
+	uint32_t tmcct = apic_read(APIC_TMCCT);
+
+	if (tmcct) {
+		while (tmcct > (initial_count / 2))
+			tmcct = apic_read(APIC_TMCCT);
+
+		if ( stop_when_half )
+			return;
+
+		/* Wait until the counter reach 0 or wrap-around */
+		while ( tmcct <= (initial_count / 2) && tmcct > 0 )
+			tmcct = apic_read(APIC_TMCCT);
+	}
+}
+
+static inline void apic_change_mode(unsigned long new_mode)
+{
+	uint32_t lvtt;
+
+	lvtt = apic_read(APIC_LVTT);
+	apic_write(APIC_LVTT, (lvtt & ~APIC_LVT_TIMER_MASK) | new_mode);
+}
+
+static void test_apic_change_mode()
+{
+	uint32_t tmict = 0x999999;
+
+	printf("starting apic change mode\n");
+
+	apic_write(APIC_TMICT, tmict);
+
+	apic_change_mode(APIC_LVT_TIMER_PERIODIC);
+
+	report("TMICT value reset", apic_read(APIC_TMICT) == tmict);
+
+	/* Testing one-shot */
+	apic_change_mode(APIC_LVT_TIMER_ONESHOT);
+	apic_write(APIC_TMICT, tmict);
+	report("TMCCT should have a non-zero value", apic_read(APIC_TMCCT));
+
+	wait_until_tmcct_is_zero(tmict, false);
+	report("TMCCT should have reached 0", !apic_read(APIC_TMCCT));
+
+	/*
+	 * Write TMICT before changing mode from one-shot to periodic TMCCT should
+	 * be reset to TMICT periodicly
+	 */
+	apic_write(APIC_TMICT, tmict);
+	wait_until_tmcct_is_zero(tmict, true);
+	apic_change_mode(APIC_LVT_TIMER_PERIODIC);
+	report("TMCCT should have a non-zero value", apic_read(APIC_TMCCT));
+
+	/*
+	 * After the change of mode, the counter should not be reset and continue
+	 * counting down from where it was
+	 */
+	report("TMCCT should not be reset to TMICT value", apic_read(APIC_TMCCT) < (tmict / 2));
+	wait_until_tmcct_is_zero(tmict, false);
+	report("TMCCT should be reset to the initial-count", apic_read(APIC_TMCCT) > (tmict / 2));
+
+	wait_until_tmcct_is_zero(tmict, true);
+	/*
+	 * Keep the same TMICT and change timer mode to one-shot
+	 * TMCCT should be > 0 and count-down to 0
+	 */
+	apic_change_mode(APIC_LVT_TIMER_ONESHOT);
+	report("TMCCT should not be reset to init", apic_read(APIC_TMCCT) < (tmict / 2));
+	wait_until_tmcct_is_zero(tmict, false);
+	report("TMCCT should have reach zero", !apic_read(APIC_TMCCT));
+
+	/* now tmcct == 0 and tmict != 0 */
+	apic_change_mode(APIC_LVT_TIMER_PERIODIC);
+	report("TMCCT should stay at zero", !apic_read(APIC_TMCCT));
+}
+
 int main()
 {
     setup_vm();
@@ -478,6 +555,7 @@ int main()
     test_multiple_nmi();
 
     test_apic_timer_one_shot();
+    test_apic_change_mode();
     test_tsc_deadline_timer();
 
     return report_summary();
-- 
2.7.4

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2017-09-29  1:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-29  1:06 [kvm-unit-tests PATCH] x86: apic: add apic timer mode transition test Wanpeng Li

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.