From owner-svn-src-all@freebsd.org Thu Oct 11 18:27:20 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 825B010C33F0; Thu, 11 Oct 2018 18:27:20 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 353FF7BD3F; Thu, 11 Oct 2018 18:27:20 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 16059141D9; Thu, 11 Oct 2018 18:27:20 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w9BIRJNG040677; Thu, 11 Oct 2018 18:27:19 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w9BIRJla040675; Thu, 11 Oct 2018 18:27:19 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201810111827.w9BIRJla040675@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Thu, 11 Oct 2018 18:27:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r339312 - in head/sys/amd64: include vmm/intel X-SVN-Group: head X-SVN-Commit-Author: jhb X-SVN-Commit-Paths: in head/sys/amd64: include vmm/intel X-SVN-Commit-Revision: 339312 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Oct 2018 18:27:20 -0000 Author: jhb Date: Thu Oct 11 18:27:19 2018 New Revision: 339312 URL: https://svnweb.freebsd.org/changeset/base/339312 Log: Fully restore the GDTR, IDTR, and LDTR after VT-x VM exits. The VT-x VMCS only stores the base address of the GDTR and IDTR. As a result, VM exits use a fixed limit of 0xffff for the host GDTR and IDTR losing the smaller limits set in when the initial GDT is loaded on each CPU during boot. Explicitly save and restore the full GDTR and IDTR contents around VM entries and exits to restore the correct limit. Similarly, explicitly save and restore the LDT selector. VM exits always clear the host LDTR as if the LDT was loaded with a NULL selector and a userspace hypervisor is probably using a NULL selector anyway, but save and restore the LDT explicitly just to be safe. PR: 230773 Reported by: John Levon Reviewed by: kib Tested by: araujo Approved by: re (rgrimes) MFC after: 1 week Modified: head/sys/amd64/include/cpufunc.h head/sys/amd64/vmm/intel/vmx.c Modified: head/sys/amd64/include/cpufunc.h ============================================================================== --- head/sys/amd64/include/cpufunc.h Thu Oct 11 18:26:18 2018 (r339311) +++ head/sys/amd64/include/cpufunc.h Thu Oct 11 18:27:19 2018 (r339312) @@ -730,6 +730,15 @@ lldt(u_short sel) __asm __volatile("lldt %0" : : "r" (sel)); } +static __inline u_short +sldt(void) +{ + u_short sel; + + __asm __volatile("sldt %0" : "=r" (sel)); + return (sel); +} + static __inline void ltr(u_short sel) { Modified: head/sys/amd64/vmm/intel/vmx.c ============================================================================== --- head/sys/amd64/vmm/intel/vmx.c Thu Oct 11 18:26:18 2018 (r339311) +++ head/sys/amd64/vmm/intel/vmx.c Thu Oct 11 18:27:19 2018 (r339312) @@ -2833,6 +2833,8 @@ vmx_run(void *arg, int vcpu, register_t rip, pmap_t pm struct vm_exit *vmexit; struct vlapic *vlapic; uint32_t exit_reason; + struct region_descriptor gdtr, idtr; + uint16_t ldt_sel; vmx = arg; vm = vmx->vm; @@ -2924,10 +2926,30 @@ vmx_run(void *arg, int vcpu, register_t rip, pmap_t pm break; } + /* + * VM exits restore the base address but not the + * limits of GDTR and IDTR. The VMCS only stores the + * base address, so VM exits set the limits to 0xffff. + * Save and restore the full GDTR and IDTR to restore + * the limits. + * + * The VMCS does not save the LDTR at all, and VM + * exits clear LDTR as if a NULL selector were loaded. + * The userspace hypervisor probably doesn't use a + * LDT, but save and restore it to be safe. + */ + sgdt(&gdtr); + sidt(&idtr); + ldt_sel = sldt(); + vmx_run_trace(vmx, vcpu); vmx_dr_enter_guest(vmxctx); rc = vmx_enter_guest(vmxctx, vmx, launched); vmx_dr_leave_guest(vmxctx); + + bare_lgdt(&gdtr); + lidt(&idtr); + lldt(ldt_sel); /* Collect some information for VM exit processing */ vmexit->rip = rip = vmcs_guest_rip();