[PATCH 13/15] VMX: Rework and enhance initial feature detection/enabling

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

 



So far we ran into an unhandled GP when VMX was unavailable. Change the
logic to handle this gracefully. Rework test_vmx_capability to
test_vmx_feature_control which not only enables VMX in the feature
control MSR but also test related error behavior.

Signed-off-by: Jan Kiszka <jan.kiszka@xxxxxxxxxxx>
---
 x86/vmx.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 68 insertions(+), 14 deletions(-)

diff --git a/x86/vmx.c b/x86/vmx.c
index f6f2f59..fe950e6 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -539,22 +539,74 @@ static void init_vmx(void)
 	memset(guest_syscall_stack, 0, PAGE_SIZE);
 }
 
-static int test_vmx_capability(void)
+static bool exception;
+static void *exception_return;
+
+static void exception_handler(struct ex_regs *regs)
+{
+	exception = true;
+	regs->rip = (u64)exception_return;
+}
+
+static int test_for_exception(unsigned int ex, void (*func)(void))
+{
+	handle_exception(ex, exception_handler);
+	exception = false;
+	func();
+	handle_exception(ex, NULL);
+	return exception;
+}
+
+static void do_vmxon_off(void)
+{
+	exception_return = &&resume;
+	barrier();
+	vmx_on();
+	vmx_off();
+resume:
+	return;
+}
+
+static void do_write_feature_control(void)
+{
+	exception_return = &&resume;
+	barrier();
+	wrmsr(MSR_IA32_FEATURE_CONTROL, 0);
+resume:
+	return;
+}
+
+static int test_vmx_feature_control(void)
 {
-	struct cpuid r;
-	u64 ret1, ret2;
 	u64 ia32_feature_control;
-	r = cpuid(1);
-	ret1 = ((r.c) >> 5) & 1;
+	bool vmx_enabled;
+
 	ia32_feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL);
-	ret2 = ((ia32_feature_control & 0x5) == 0x5);
-	if ((!ret2) && ((ia32_feature_control & 0x1) == 0)) {
-		wrmsr(MSR_IA32_FEATURE_CONTROL, 0x5);
-		ia32_feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL);
-		ret2 = ((ia32_feature_control & 0x5) == 0x5);
+	vmx_enabled = ((ia32_feature_control & 0x5) == 0x5);
+	if ((ia32_feature_control & 0x5) == 0x5) {
+		printf("VMX enabled and locked by BIOS\n");
+		return 0;
+	} else if (ia32_feature_control & 0x1) {
+		printf("ERROR: VMX locked out by BIOS!?\n");
+		return 1;
 	}
-	report("test vmx capability", ret1 & ret2);
-	return !(ret1 & ret2);
+
+	wrmsr(MSR_IA32_FEATURE_CONTROL, 0);
+	report("test vmxon with FEATURE_CONTROL cleared",
+	       test_for_exception(GP_VECTOR, &do_vmxon_off));
+
+	wrmsr(MSR_IA32_FEATURE_CONTROL, 0x4);
+	report("test vmxon without FEATURE_CONTROL lock",
+	       test_for_exception(GP_VECTOR, &do_vmxon_off));
+
+	wrmsr(MSR_IA32_FEATURE_CONTROL, 0x5);
+	vmx_enabled = ((rdmsr(MSR_IA32_FEATURE_CONTROL) & 0x5) == 0x5);
+	report("test enable VMX in FEATURE_CONTROL", vmx_enabled);
+
+	report("test FEATURE_CONTROL lock bit",
+	       test_for_exception(GP_VECTOR, &do_write_feature_control));
+
+	return !vmx_enabled;
 }
 
 static int test_vmxon(void)
@@ -758,11 +810,13 @@ int main(void)
 	fails = tests = 0;
 	hypercall_field = 0;
 
-	if (test_vmx_capability() != 0) {
-		printf("ERROR : vmx not supported, check +vmx option\n");
+	if (!(cpuid(1).c & (1 << 5))) {
+		printf("WARNING: vmx not supported, add '-cpu host'\n");
 		goto exit;
 	}
 	init_vmx();
+	if (test_vmx_feature_control() != 0)
+		goto exit;
 	/* Set basic test ctxt the same as "null" */
 	current = &vmx_tests[0];
 	if (test_vmxon() != 0)
-- 
1.8.1.1.298.ge7eed54

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[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