Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Aug 2013 03:16:42 +0000 (UTC)
From:      Peter Grehan <grehan@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r253909 - head/sys/amd64/vmm/intel
Message-ID:  <201308030316.r733Ggno017718@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: grehan
Date: Sat Aug  3 03:16:42 2013
New Revision: 253909
URL: http://svnweb.freebsd.org/changeset/base/253909

Log:
  Follow-up commit to fix CR0 issues. Maintain
  architectural state on CR vmexits by guaranteeing
  that EFER, CR0 and the VMCS entry controls are
  all in sync when transitioning to IA-32e mode.
  
  Submitted by:	Tycho Nightingale (tycho.nightingale <at> plurisbusnetworks.com)

Modified:
  head/sys/amd64/vmm/intel/vmx.c

Modified: head/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- head/sys/amd64/vmm/intel/vmx.c	Sat Aug  3 00:55:18 2013	(r253908)
+++ head/sys/amd64/vmm/intel/vmx.c	Sat Aug  3 03:16:42 2013	(r253909)
@@ -1084,7 +1084,7 @@ static int
 vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual)
 {
 	int error, cr, vmcs_guest_cr, vmcs_shadow_cr;
-	uint64_t regval, ones_mask, zeros_mask;
+	uint64_t crval, regval, ones_mask, zeros_mask;
 	const struct vmxctx *vmxctx;
 
 	/* We only handle mov to %cr0 or %cr4 at this time */
@@ -1174,14 +1174,48 @@ vmx_emulate_cr_access(struct vmx *vmx, i
 		      error, cr);
 	}
 
-	regval |= ones_mask;
-	regval &= ~zeros_mask;
-	error = vmwrite(vmcs_guest_cr, regval);
+	crval = regval | ones_mask;
+	crval &= ~zeros_mask;
+	error = vmwrite(vmcs_guest_cr, crval);
 	if (error) {
 		panic("vmx_emulate_cr_access: error %d writing cr%d",
 		      error, cr);
 	}
 
+	if (cr == 0 && regval & CR0_PG) {
+		uint64_t efer, entry_ctls;
+
+		/*
+		 * If CR0.PG is 1 and EFER.LME is 1 then EFER.LMA and
+		 * the "IA-32e mode guest" bit in VM-entry control must be
+		 * equal.
+		 */
+		error = vmread(VMCS_GUEST_IA32_EFER, &efer);
+		if (error) {
+		  panic("vmx_emulate_cr_access: error %d efer read",
+			error);			
+		}
+		if (efer & EFER_LME) {
+			efer |= EFER_LMA;
+			error = vmwrite(VMCS_GUEST_IA32_EFER, efer);
+			if (error) {
+				panic("vmx_emulate_cr_access: error %d"
+				      " efer write", error);
+			}
+			error = vmread(VMCS_ENTRY_CTLS, &entry_ctls);
+			if (error) {
+				panic("vmx_emulate_cr_access: error %d"
+				      " entry ctls read", error);
+			}
+			entry_ctls |= VM_ENTRY_GUEST_LMA;
+			error = vmwrite(VMCS_ENTRY_CTLS, entry_ctls);
+			if (error) {
+				panic("vmx_emulate_cr_access: error %d"
+				      " entry ctls write", error);
+			}
+		}
+	}
+
 	return (HANDLED);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308030316.r733Ggno017718>