Module Name:    src
Committed By:   maxv
Date:           Fri Feb 22 12:24:34 UTC 2019

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

Log Message:
Fix omission: if we receive a guest trap on CR0, and if the original
instruction would have resulted in Long Mode being enabled, we need to
manually enable Long Mode ourselves. We were already doing that correctly
in setstate, but not in the CR0 trap handler.

Problem initially reported by Aymeric Vincent; ArchLinux wouldn't boot,
now it does and works correctly.

While here, add CR0_ET in the CR0 mask, for the associated shadow to
be taken into account. Normally this shadow bit shouldn't be necessary,
but for now I keep it regardless.


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 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.10 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.11
--- src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.10	Thu Feb 21 13:25:44 2019
+++ src/sys/dev/nvmm/x86/nvmm_x86_vmx.c	Fri Feb 22 12:24:34 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: nvmm_x86_vmx.c,v 1.10 2019/02/21 13:25:44 maxv Exp $	*/
+/*	$NetBSD: nvmm_x86_vmx.c,v 1.11 2019/02/22 12:24:34 maxv Exp $	*/
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.10 2019/02/21 13:25:44 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.11 2019/02/22 12:24:34 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1154,6 +1154,7 @@ vmx_inkernel_handle_cr0(struct nvmm_mach
 {
 	struct vmx_cpudata *cpudata = vcpu->cpudata;
 	uint64_t type, gpr, cr0;
+	uint64_t efer, ctls1;
 
 	type = __SHIFTOUT(qual, VMX_QUAL_CR_TYPE);
 	if (type != CR_TYPE_WRITE) {
@@ -1176,6 +1177,25 @@ vmx_inkernel_handle_cr0(struct nvmm_mach
 		return -1;
 	}
 
+	/*
+	 * XXX Handle 32bit PAE paging, need to set PDPTEs, fetched manually
+	 * from CR3.
+	 */
+
+	if (cr0 & CR0_PG) {
+		vmx_vmread(VMCS_ENTRY_CTLS, &ctls1);
+		vmx_vmread(VMCS_GUEST_IA32_EFER, &efer);
+		if (efer & EFER_LME) {
+			ctls1 |= ENTRY_CTLS_LONG_MODE;
+			efer |= EFER_LMA;
+		} else {
+			ctls1 &= ~ENTRY_CTLS_LONG_MODE;
+			efer &= ~EFER_LMA;
+		}
+		vmx_vmwrite(VMCS_GUEST_IA32_EFER, efer);
+		vmx_vmwrite(VMCS_ENTRY_CTLS, ctls1);
+	}
+
 	vmx_vmwrite(VMCS_GUEST_CR0, cr0);
 	vmx_inkernel_advance();
 	return 0;
@@ -2043,7 +2063,7 @@ vmx_vcpu_init(struct nvmm_machine *mach,
 	vmx_vmwrite(VMCS_EXIT_MSR_STORE_COUNT, VMX_MSRLIST_EXIT_NMSR);
 
 	/* Force CR0_NW and CR0_CD to zero, CR0_ET to one. */
-	vmx_vmwrite(VMCS_CR0_MASK, CR0_NW|CR0_CD);
+	vmx_vmwrite(VMCS_CR0_MASK, CR0_NW|CR0_CD|CR0_ET);
 	vmx_vmwrite(VMCS_CR0_SHADOW, CR0_ET);
 
 	/* Force CR4_VMXE to zero. */

Reply via email to