Module Name:    src
Committed By:   maxv
Date:           Wed Aug 26 16:30:50 UTC 2020

Modified Files:
        src/sys/dev/nvmm/x86: nvmm_x86_vmx.c

Log Message:
nvmm-x86-vmx: improve the handling of CR4

 - Filter out certain features we don't want the guest to enable. This is
   for general correctness, and future-proofness.
 - Flush the guest TLB when certain flags change.


To generate a diff of this commit:
cvs rdiff -u -r1.72 -r1.73 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/nvmm/x86/nvmm_x86_vmx.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.72 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.73
--- src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.72	Sat Aug 22 11:01:10 2020
+++ src/sys/dev/nvmm/x86/nvmm_x86_vmx.c	Wed Aug 26 16:30:50 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: nvmm_x86_vmx.c,v 1.72 2020/08/22 11:01:10 maxv Exp $	*/
+/*	$NetBSD: nvmm_x86_vmx.c,v 1.73 2020/08/26 16:30:50 maxv Exp $	*/
 
 /*
  * Copyright (c) 2018-2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.72 2020/08/22 11:01:10 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.73 2020/08/26 16:30:50 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -729,6 +729,33 @@ static uint64_t vmx_xcr0_mask __read_mos
 #define MSRBM_NPAGES	1
 #define MSRBM_SIZE	(MSRBM_NPAGES * PAGE_SIZE)
 
+#define CR4_VALID \
+	(CR4_VME |			\
+	 CR4_PVI |			\
+	 CR4_TSD |			\
+	 CR4_DE |			\
+	 CR4_PSE |			\
+	 CR4_PAE |			\
+	 CR4_MCE |			\
+	 CR4_PGE |			\
+	 CR4_PCE |			\
+	 CR4_OSFXSR |			\
+	 CR4_OSXMMEXCPT |		\
+	 CR4_UMIP |			\
+	 /* CR4_LA57 excluded */	\
+	 /* CR4_VMXE excluded */	\
+	 /* CR4_SMXE excluded */	\
+	 CR4_FSGSBASE |			\
+	 CR4_PCIDE |			\
+	 CR4_OSXSAVE |			\
+	 CR4_SMEP |			\
+	 CR4_SMAP			\
+	 /* CR4_PKE excluded */		\
+	 /* CR4_CET excluded */		\
+	 /* CR4_PKS excluded */)
+#define CR4_INVALID \
+	(0xFFFFFFFFFFFFFFFFULL & ~CR4_VALID)
+
 #define EFER_TLB_FLUSH \
 	(EFER_NXE|EFER_LMA|EFER_LME)
 #define CR0_TLB_FLUSH \
@@ -1589,12 +1616,18 @@ vmx_inkernel_handle_cr4(struct nvmm_mach
 		gpr = cpudata->gprs[gpr];
 	}
 
+	if (gpr & CR4_INVALID) {
+		return -1;
+	}
 	cr4 = gpr | CR4_VMXE;
-
 	if (vmx_check_cr(cr4, vmx_cr4_fixed0, vmx_cr4_fixed1) == -1) {
 		return -1;
 	}
 
+	if ((vmx_vmread(VMCS_GUEST_CR4) ^ cr4) & CR4_TLB_FLUSH) {
+		cpudata->gtlb_want_flush = true;
+	}
+
 	vmx_vmwrite(VMCS_GUEST_CR4, cr4);
 	vmx_inkernel_advance();
 	return 0;
@@ -2514,7 +2547,7 @@ vmx_vcpu_setstate(struct nvmm_cpu *vcpu)
 		cpudata->gcr2 = state->crs[NVMM_X64_CR_CR2];
 		vmx_vmwrite(VMCS_GUEST_CR3, state->crs[NVMM_X64_CR_CR3]); // XXX PDPTE?
 		vmx_vmwrite(VMCS_GUEST_CR4,
-		    state->crs[NVMM_X64_CR_CR4] | CR4_VMXE);
+		    (state->crs[NVMM_X64_CR_CR4] & CR4_VALID) | CR4_VMXE);
 		cpudata->gcr8 = state->crs[NVMM_X64_CR_CR8];
 
 		if (vmx_xcr0_mask != 0) {
@@ -2839,8 +2872,9 @@ vmx_vcpu_init(struct nvmm_machine *mach,
 	vmx_vmwrite(VMCS_CR0_MASK, CR0_NW|CR0_CD|CR0_ET);
 	vmx_vmwrite(VMCS_CR0_SHADOW, CR0_ET);
 
-	/* Force CR4_VMXE to zero. */
-	vmx_vmwrite(VMCS_CR4_MASK, CR4_VMXE);
+	/* Force unsupported CR4 fields to zero. */
+	vmx_vmwrite(VMCS_CR4_MASK, CR4_INVALID);
+	vmx_vmwrite(VMCS_CR4_SHADOW, 0);
 
 	/* Set the Host state for resuming. */
 	vmx_vmwrite(VMCS_HOST_RIP, (uint64_t)&vmx_resume_rip);

Reply via email to