[kvm-unit-tests PATCH 2/2] x86: nSVM: Ensure APIC MMIO tests run with APIC in xAPIC mode

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

 



Implement prepare/restore logic for the nSVM/nNPT APIC MMIO passthrough
tests to ensure the CPU is actually running with xAPIC enabled.  As is,
the test is effectively validating KVM's KVM_X86_QUIRK_LAPIC_MMIO_HOLE,
or if x2AVIC is support, CPU behavior.

The latter (x2AVIC enabled) is especially problematic, as AMD CPUs appear
to return '0' for xAPIC reads when x2AVIC is enabled.  And because KVM
disables/inhibits AVIC and x2AVIC when running L2, the divergence in
behavior (KVM provies 0xffs, CPU provides 0s) results in test failures.

Opportunistically make the hardcoded APIC base pointer (eww) an unsigned
long literal.

Note, svm_test.finished() is invoked *before* svm_test.succeeded(), i.e.
restoring x2APIC (if it was enabled) must be done in the "check" code.

Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
 x86/svm_npt.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/x86/svm_npt.c b/x86/svm_npt.c
index b791f1ac..bd5e8f35 100644
--- a/x86/svm_npt.c
+++ b/x86/svm_npt.c
@@ -1,3 +1,4 @@
+#include "apic.h"
 #include "svm.h"
 #include "vm.h"
 #include "alloc_page.h"
@@ -134,8 +135,27 @@ static bool npt_rw_pfwalk_check(struct svm_test *test)
 	    && (vmcb->control.exit_info_2 == read_cr3());
 }
 
+static bool was_x2apic;
+
+static void npt_apic_prepare(void)
+{
+	was_x2apic = is_x2apic_enabled();
+
+	if (was_x2apic)
+		reset_apic();
+}
+
+static void npt_apic_restore(void)
+{
+	if (was_x2apic)
+		enable_x2apic();
+
+	was_x2apic = false;
+}
+
 static void npt_l1mmio_prepare(struct svm_test *test)
 {
+	npt_apic_prepare();
 }
 
 u32 nested_apic_version1;
@@ -154,6 +174,9 @@ static bool npt_l1mmio_check(struct svm_test *test)
 	volatile u32 *data = (volatile void *)(0xfee00030);
 	u32 lvr = *data;
 
+	/* Restore APIC state *after* reading LVR. */
+	npt_apic_restore();
+
 	return nested_apic_version1 == lvr && nested_apic_version2 == lvr;
 }
 
@@ -162,6 +185,8 @@ static void npt_rw_l1mmio_prepare(struct svm_test *test)
 
 	u64 *pte;
 
+	npt_apic_prepare();
+
 	pte = npt_get_pte(0xfee00080);
 
 	*pte &= ~(1ULL << 1);
@@ -180,6 +205,8 @@ static bool npt_rw_l1mmio_check(struct svm_test *test)
 
 	*pte |= (1ULL << 1);
 
+	npt_apic_restore();
+
 	return (vmcb->control.exit_code == SVM_EXIT_NPF)
 	    && (vmcb->control.exit_info_1 == 0x100000007ULL);
 }
-- 
2.48.1.711.g2feabab25a-goog





[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