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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to