diff mbox

[kvm-unit-tests,6/9] x86: nVMX: Enhance basic vmwrite/vmread test

Message ID 1529711980-32764-7-git-send-email-liran.alon@oracle.com (mailing list archive)
State New, archived
Headers show

Commit Message

Liran Alon June 22, 2018, 11:59 p.m. UTC
Check that "read-only" fields are writable when the IA32_VMX_MISC MSR
reports that software can use VMWRITE to write to any supported field in
the VMCS.

Signed-off-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Liran Alon <liran.alon@oracle.com>
---
 lib/x86/msr.h |  3 +++
 x86/vmx.c     | 62 ++++++++++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 50 insertions(+), 15 deletions(-)
diff mbox

Patch

diff --git a/lib/x86/msr.h b/lib/x86/msr.h
index 663bad034c0d..abf0d93bc58d 100644
--- a/lib/x86/msr.h
+++ b/lib/x86/msr.h
@@ -405,6 +405,9 @@ 
 #define MSR_IA32_VMX_TRUE_EXIT		0x0000048f
 #define MSR_IA32_VMX_TRUE_ENTRY		0x00000490
 
+/* MSR_IA32_VMX_MISC bits */
+#define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS	(1ULL << 29)
+
 #define MSR_IA32_TSCDEADLINE		0x000006e0
 
 /* AMD-V MSRs */
diff --git a/x86/vmx.c b/x86/vmx.c
index aa04ac68dab5..f80b155c4dae 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -125,7 +125,7 @@  static struct vmcs_field vmcs_fields[] = {
 	{ MASK(64), APIC_ACCS_ADDR },
 	{ MASK(64), EPTP },
 
-	{ 0 /* read-only */, INFO_PHYS_ADDR },
+	{ MASK(64), INFO_PHYS_ADDR },
 
 	{ MASK(64), VMCS_LINK_PTR },
 	{ MASK(64), GUEST_DEBUGCTL },
@@ -155,14 +155,14 @@  static struct vmcs_field vmcs_fields[] = {
 	{ MASK(32), TPR_THRESHOLD },
 	{ MASK(32), CPU_EXEC_CTRL1 },
 
-	{ 0 /* read-only */, VMX_INST_ERROR },
-	{ 0 /* read-only */, EXI_REASON },
-	{ 0 /* read-only */, EXI_INTR_INFO },
-	{ 0 /* read-only */, EXI_INTR_ERROR },
-	{ 0 /* read-only */, IDT_VECT_INFO },
-	{ 0 /* read-only */, IDT_VECT_ERROR },
-	{ 0 /* read-only */, EXI_INST_LEN },
-	{ 0 /* read-only */, EXI_INST_INFO },
+	{ MASK(32), VMX_INST_ERROR },
+	{ MASK(32), EXI_REASON },
+	{ MASK(32), EXI_INTR_INFO },
+	{ MASK(32), EXI_INTR_ERROR },
+	{ MASK(32), IDT_VECT_INFO },
+	{ MASK(32), IDT_VECT_ERROR },
+	{ MASK(32), EXI_INST_LEN },
+	{ MASK(32), EXI_INST_INFO },
 
 	{ MASK(32), GUEST_LIMIT_ES },
 	{ MASK(32), GUEST_LIMIT_CS },
@@ -199,12 +199,12 @@  static struct vmcs_field vmcs_fields[] = {
 	{ MASK_NATURAL, CR3_TARGET_2 },
 	{ MASK_NATURAL, CR3_TARGET_3 },
 
-	{ 0 /* read-only */, EXI_QUALIFICATION },
-	{ 0 /* read-only */, IO_RCX },
-	{ 0 /* read-only */, IO_RSI },
-	{ 0 /* read-only */, IO_RDI },
-	{ 0 /* read-only */, IO_RIP },
-	{ 0 /* read-only */, GUEST_LINEAR_ADDRESS },
+	{ MASK_NATURAL, EXI_QUALIFICATION },
+	{ MASK_NATURAL, IO_RCX },
+	{ MASK_NATURAL, IO_RSI },
+	{ MASK_NATURAL, IO_RDI },
+	{ MASK_NATURAL, IO_RIP },
+	{ MASK_NATURAL, GUEST_LINEAR_ADDRESS },
 
 	{ MASK_NATURAL, GUEST_CR0 },
 	{ MASK_NATURAL, GUEST_CR3 },
@@ -241,6 +241,28 @@  static struct vmcs_field vmcs_fields[] = {
 	{ MASK_NATURAL, HOST_RIP },
 };
 
+enum vmcs_field_type {
+	VMCS_FIELD_TYPE_CONTROL = 0,
+	VMCS_FIELD_TYPE_READ_ONLY_DATA = 1,
+	VMCS_FIELD_TYPE_GUEST = 2,
+	VMCS_FIELD_TYPE_HOST = 3,
+	VMCS_FIELD_TYPES,
+};
+
+static inline int vmcs_field_type(struct vmcs_field *f)
+{
+	return (f->encoding >> VMCS_FIELD_TYPE_SHIFT) & 0x3;
+}
+
+static int vmcs_field_readonly(struct vmcs_field *f)
+{
+	u64 ia32_vmx_misc;
+
+	ia32_vmx_misc = rdmsr(MSR_IA32_VMX_MISC);
+	return !(ia32_vmx_misc & MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS) &&
+		(vmcs_field_type(f) == VMCS_FIELD_TYPE_READ_ONLY_DATA);
+}
+
 static inline u64 vmcs_field_value(struct vmcs_field *f, u8 cookie)
 {
 	u64 value;
@@ -264,6 +286,16 @@  static bool check_vmcs_field(struct vmcs_field *f, u8 cookie)
 	u64 actual;
 	int ret;
 
+	if (f->encoding == VMX_INST_ERROR) {
+		printf("Skipping volatile field %lx\n", f->encoding);
+		return true;
+	}
+
+	if (vmcs_field_readonly(f)) {
+		printf("Skipping read-only field %lx\n", f->encoding);
+		return true;
+	}
+
 	ret = vmcs_read_checking(f->encoding, &actual);
 	assert(!(ret & X86_EFLAGS_CF));
 	/* Skip VMCS fields that aren't recognized by the CPU */