Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Jan 2014 04:03:11 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r261001 - in head/sys/amd64/vmm: . intel
Message-ID:  <201401220403.s0M43B9M036090@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Wed Jan 22 04:03:11 2014
New Revision: 261001
URL: http://svnweb.freebsd.org/changeset/base/261001

Log:
  Handle a VM-exit due to a NMI properly by vectoring to the host's NMI handler
  via a software interrupt.
  
  This is safe to do because the logical processor is already cognizant of the
  NMI and further NMIs are blocked until the host's NMI handler executes "iret".

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

Modified: head/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- head/sys/amd64/vmm/intel/vmx.c	Wed Jan 22 01:57:52 2014	(r261000)
+++ head/sys/amd64/vmm/intel/vmx.c	Wed Jan 22 04:03:11 2014	(r261001)
@@ -1491,6 +1491,7 @@ vmx_exit_process(struct vmx *vmx, int vc
 	bool retu;
 
 	CTASSERT((PINBASED_CTLS_ONE_SETTING & PINBASED_VIRTUAL_NMI) != 0);
+	CTASSERT((PINBASED_CTLS_ONE_SETTING & PINBASED_NMI_EXITING) != 0);
 
 	handled = 0;
 	vmxctx = &vmx->ctx[vcpu];
@@ -1643,9 +1644,11 @@ vmx_exit_process(struct vmx *vmx, int vc
 		handled = vmx_handle_cpuid(vmx->vm, vcpu, vmxctx);
 		break;
 	case EXIT_REASON_EXCEPTION:
+		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_EXCEPTION, 1);
 		intr_info = vmcs_read(VMCS_EXIT_INTR_INFO);
 		KASSERT((intr_info & VMCS_INTR_VALID) != 0,
 		    ("VM exit interruption info invalid: %#x", intr_info));
+
 		/*
 		 * If Virtual NMIs control is 1 and the VM-exit is due to a
 		 * fault encountered during the execution of IRET then we must
@@ -1658,6 +1661,21 @@ vmx_exit_process(struct vmx *vmx, int vc
 		    (intr_info & 0xff) != IDT_DF &&
 		    (intr_info & EXIT_QUAL_NMIUDTI) != 0)
 			vmx_restore_nmi_blocking(vmx, vcpu);
+
+		/*
+		 * If the NMI-exiting VM execution control is set to '1'
+		 * then an NMI in non-root operation causes a VM-exit.
+		 * NMI blocking is in effect for this logical processor so
+		 * it is sufficient to simply vector to the NMI handler via
+		 * a software interrupt.
+		 */
+		if ((intr_info & VMCS_INTR_T_MASK) == VMCS_INTR_T_NMI) {
+			KASSERT((intr_info & 0xff) == IDT_NMI, ("VM exit due "
+			    "to NMI has invalid vector: %#x", intr_info));
+			VCPU_CTR0(vmx->vm, vcpu, "Vectoring to NMI handler");
+			__asm __volatile("int $2");
+			return (1);
+		}
 		break;
 	case EXIT_REASON_EPT_FAULT:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_EPT_FAULT, 1);
@@ -1728,6 +1746,8 @@ vmx_exit_process(struct vmx *vmx, int vc
 			 */
 			vmexit->exitcode = VM_EXITCODE_VMX;
 			vmexit->u.vmx.status = VM_SUCCESS;
+			vmexit->u.vmx.inst_type = 0;
+			vmexit->u.vmx.inst_error = 0;
 		} else {
 			/*
 			 * The exitcode and collateral have been populated.

Modified: head/sys/amd64/vmm/vmm_stat.c
==============================================================================
--- head/sys/amd64/vmm/vmm_stat.c	Wed Jan 22 01:57:52 2014	(r261000)
+++ head/sys/amd64/vmm/vmm_stat.c	Wed Jan 22 04:03:11 2014	(r261001)
@@ -151,3 +151,4 @@ VMM_STAT(VMEXIT_UNKNOWN, "number of vm e
 VMM_STAT(VMEXIT_ASTPENDING, "number of times astpending at exit");
 VMM_STAT(VMEXIT_USERSPACE, "number of vm exits handled in userspace");
 VMM_STAT(VMEXIT_RENDEZVOUS, "number of times rendezvous pending at exit");
+VMM_STAT(VMEXIT_EXCEPTION, "number of vm exits due to exceptions");

Modified: head/sys/amd64/vmm/vmm_stat.h
==============================================================================
--- head/sys/amd64/vmm/vmm_stat.h	Wed Jan 22 01:57:52 2014	(r261000)
+++ head/sys/amd64/vmm/vmm_stat.h	Wed Jan 22 04:03:11 2014	(r261001)
@@ -121,4 +121,5 @@ VMM_STAT_DECLARE(VMEXIT_UNKNOWN);
 VMM_STAT_DECLARE(VMEXIT_ASTPENDING);
 VMM_STAT_DECLARE(VMEXIT_USERSPACE);
 VMM_STAT_DECLARE(VMEXIT_RENDEZVOUS);
+VMM_STAT_DECLARE(VMEXIT_EXCEPTION);
 #endif



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