lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <1506421253-21300-1-git-send-email-wanpeng.li@hotmail.com>
Date:   Tue, 26 Sep 2017 03:20:53 -0700
From:   Wanpeng Li <kernellwp@...il.com>
To:     linux-kernel@...r.kernel.org, kvm@...r.kernel.org
Cc:     Paolo Bonzini <pbonzini@...hat.com>,
        Radim Krčmář <rkrcmar@...hat.com>,
        Wanpeng Li <wanpeng.li@...mail.com>
Subject: [PATCH] x86: apic: add apic timer mode transition test

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

Add apic timer mode transition test.

Cc: Paolo Bonzini <pbonzini@...hat.com>
Cc: Radim Krčmář <rkrcmar@...hat.com>
Signed-off-by: Wanpeng Li <wanpeng.li@...mail.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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ