From owner-svn-src-projects@FreeBSD.ORG Sat Aug 4 02:06:55 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id DB6F9106566C; Sat, 4 Aug 2012 02:06:55 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C60A38FC0A; Sat, 4 Aug 2012 02:06:55 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q7426tnJ095756; Sat, 4 Aug 2012 02:06:55 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q7426twT095754; Sat, 4 Aug 2012 02:06:55 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201208040206.q7426twT095754@svn.freebsd.org> From: Neel Natu Date: Sat, 4 Aug 2012 02:06:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r239024 - projects/bhyve/sys/amd64/vmm/intel X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Aug 2012 02:06:56 -0000 Author: neel Date: Sat Aug 4 02:06:55 2012 New Revision: 239024 URL: http://svn.freebsd.org/changeset/base/239024 Log: Force certain bits in %cr4 to be hard-wired to '1' or '0' from a guest's perspective. If we don't do this some guest OSes (e.g. Linux) will reset the CR4_VMXE bit in %cr4 with disastrous consequences. Reported by: grehan Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c ============================================================================== --- projects/bhyve/sys/amd64/vmm/intel/vmx.c Sat Aug 4 00:00:30 2012 (r239023) +++ projects/bhyve/sys/amd64/vmm/intel/vmx.c Sat Aug 4 02:06:55 2012 (r239024) @@ -627,23 +627,38 @@ vmx_vpid(void) } static int -vmx_setup_cr0_shadow(struct vmcs *vmcs) +vmx_setup_cr_shadow(int which, struct vmcs *vmcs) { - int error; - uint64_t mask, shadow; + int error, mask_ident, shadow_ident; + uint64_t mask_value, shadow_value; + + if (which != 0 && which != 4) + panic("vmx_setup_cr_shadow: unknown cr%d", which); + + if (which == 0) { + mask_ident = VMCS_CR0_MASK; + mask_value = cr0_ones_mask | cr0_zeros_mask; + shadow_ident = VMCS_CR0_SHADOW; + shadow_value = cr0_ones_mask; + } else { + mask_ident = VMCS_CR4_MASK; + mask_value = cr4_ones_mask | cr4_zeros_mask; + shadow_ident = VMCS_CR4_SHADOW; + shadow_value = cr4_ones_mask; + } - mask = cr0_ones_mask | cr0_zeros_mask; - error = vmcs_setreg(vmcs, VMCS_IDENT(VMCS_CR0_MASK), mask); + error = vmcs_setreg(vmcs, VMCS_IDENT(mask_ident), mask_value); if (error) return (error); - shadow = cr0_ones_mask; - error = vmcs_setreg(vmcs, VMCS_IDENT(VMCS_CR0_SHADOW), shadow); + error = vmcs_setreg(vmcs, VMCS_IDENT(shadow_ident), shadow_value); if (error) return (error); return (0); } +#define vmx_setup_cr0_shadow(vmcs) vmx_setup_cr_shadow(0, (vmcs)) +#define vmx_setup_cr4_shadow(vmcs) vmx_setup_cr_shadow(4, (vmcs)) static void * vmx_vminit(struct vm *vm) @@ -744,6 +759,12 @@ vmx_vminit(struct vm *vm) panic("vmcs_set_msr_save error %d", error); error = vmx_setup_cr0_shadow(&vmx->vmcs[i]); + if (error != 0) + panic("vmx_setup_cr0_shadow %d", error); + + error = vmx_setup_cr4_shadow(&vmx->vmcs[i]); + if (error != 0) + panic("vmx_setup_cr4_shadow %d", error); } return (vmx); @@ -1031,12 +1052,16 @@ cantinject: static int vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual) { - int error; - uint64_t regval; + int error, cr, vmcs_guest_cr; + uint64_t regval, ones_mask, zeros_mask; const struct vmxctx *vmxctx; - /* We only handle mov to %cr0 at this time */ - if ((exitqual & 0xff) != 0x00) + /* We only handle mov to %cr0 or %cr4 at this time */ + if ((exitqual & 0xf0) != 0x00) + return (UNHANDLED); + + cr = exitqual & 0xf; + if (cr != 0 && cr != 4) return (UNHANDLED); vmxctx = &vmx->ctx[vcpu]; @@ -1100,11 +1125,22 @@ vmx_emulate_cr_access(struct vmx *vmx, i break; } - regval |= cr0_ones_mask; - regval &= ~cr0_zeros_mask; - error = vmwrite(VMCS_GUEST_CR0, regval); - if (error) - panic("vmx_emulate_cr_access: error %d writing cr0", error); + if (cr == 0) { + ones_mask = cr0_ones_mask; + zeros_mask = cr0_zeros_mask; + vmcs_guest_cr = VMCS_GUEST_CR0; + } else { + ones_mask = cr4_ones_mask; + zeros_mask = cr4_zeros_mask; + vmcs_guest_cr = VMCS_GUEST_CR4; + } + regval |= ones_mask; + regval &= ~zeros_mask; + error = vmwrite(vmcs_guest_cr, regval); + if (error) { + panic("vmx_emulate_cr_access: error %d writing cr%d", + error, cr); + } return (HANDLED); }