svn commit: r261001 - in head/sys/amd64/vmm: . intel
Neel Natu
neel at FreeBSD.org
Wed Jan 22 04:03:12 UTC 2014
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
More information about the svn-src-head
mailing list