[kvm-unit-tests PATCH] x86: nVMX: Test VMPTRLD with operand outside of backed memory

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

 



Reads of unbacked addresses from the PCI bus should return all
ones. Since kvm's VMCS revision identifier isn't 0xffffffff, this
means that a VMPTRLD with an argument outside of backed memory should
set the VM-instruction error number to 11 (VMPTRLD with incorrect VMCS
revision identifier) if there is already a valid VMCS pointer loaded.

make_vmcs_current() has been modified to return all of the arithmetic
flags, so that the caller can distinguish VMfailInvalid from
VMfailValid.

Suggested-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
Signed-off-by: Jim Mattson <jmattson@xxxxxxxxxx>
Reviewed-by: Peter Shier <pshier@xxxxxxxxxx>
---
 x86/vmx.c | 17 ++++++++++++++---
 x86/vmx.h | 10 ++++++----
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/x86/vmx.c b/x86/vmx.c
index 79a21d8..1318548 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -31,6 +31,7 @@
 #include "libcflat.h"
 #include "processor.h"
 #include "alloc_page.h"
+#include "fwcfg.h"
 #include "vm.h"
 #include "desc.h"
 #include "vmx.h"
@@ -1374,23 +1375,33 @@ static void test_vmptrld(void)
 	/* Unaligned page access */
 	tmp_root = (struct vmcs *)((intptr_t)vmcs + 1);
 	report("test vmptrld with unaligned vmcs",
-	       make_vmcs_current(tmp_root) == 1);
+	       make_vmcs_current(tmp_root) == VM_FAIL_INVALID);
 
 	/* gpa bits beyond physical address width are set*/
 	tmp_root = (struct vmcs *)((intptr_t)vmcs |
 				   ((u64)1 << (width+1)));
 	report("test vmptrld with vmcs address bits set beyond physical address width",
-	       make_vmcs_current(tmp_root) == 1);
+	       make_vmcs_current(tmp_root) == VM_FAIL_INVALID);
 
 	/* Pass VMXON region */
 	make_vmcs_current(vmcs);
 	tmp_root = (struct vmcs *)vmxon_region;
 	report("test vmptrld with vmxon region",
-	       make_vmcs_current(tmp_root) == 1);
+	       make_vmcs_current(tmp_root) == VM_FAIL_VALID);
 	report("test vmptrld with vmxon region vm-instruction error",
 	       vmcs_read(VMX_INST_ERROR) == VMXERR_VMPTRLD_VMXON_POINTER);
 
+	tmp_root = (struct vmcs *)(fwcfg_get_u64(FW_CFG_RAM_SIZE));
+	if ((uintptr_t)tmp_root < (1ul << width)) {
+		report("test vmptrld of unbacked physical address",
+		       make_vmcs_current(tmp_root) == VM_FAIL_VALID);
+		report("test vmptrld of unbacked physical address vm-instruction error",
+		       vmcs_read(VMX_INST_ERROR) ==
+		       VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
+	}
+
 	report("test vmptrld with valid vmcs region", make_vmcs_current(vmcs) == 0);
+
 }
 
 static void test_vmptrst(void)
diff --git a/x86/vmx.h b/x86/vmx.h
index ba47455..6e3620b 100644
--- a/x86/vmx.h
+++ b/x86/vmx.h
@@ -7,6 +7,9 @@
 #include "asm/page.h"
 #include "asm/io.h"
 
+#define VM_FAIL_INVALID	X86_EFLAGS_CF
+#define VM_FAIL_VALID	X86_EFLAGS_ZF
+
 struct vmcs_hdr {
 	u32 revision_id:31;
 	u32 shadow_vmcs:1;
@@ -680,12 +683,11 @@ static int vmx_off(void)
 
 static inline int make_vmcs_current(struct vmcs *vmcs)
 {
-	bool ret;
 	u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF;
 
-	asm volatile ("push %1; popf; vmptrld %2; setbe %0"
-		      : "=q" (ret) : "q" (rflags), "m" (vmcs) : "cc");
-	return ret;
+	asm volatile ("push %1; popf; vmptrld %2; pushf; pop %0"
+		      : "=r" (rflags) : "0" (rflags), "m" (vmcs) : "cc");
+	return rflags & VMX_ENTRY_FLAGS;
 }
 
 static inline int vmcs_clear(struct vmcs *vmcs)
-- 
2.20.0.rc0.387.gc7a69e6b6c-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