Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 1 Aug 2013 19:37:11 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r253864 - projects/bhyve_npt_pmap/sys/amd64/vmm/intel
Message-ID:  <201308011937.r71JbBID015443@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Thu Aug  1 19:37:11 2013
New Revision: 253864
URL: http://svnweb.freebsd.org/changeset/base/253864

Log:
  Deal with VM exits during event injection properly by re-injecting the event
  on the next VM entry.

Modified:
  projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmcs.h
  projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmx.c

Modified: projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmcs.h
==============================================================================
--- projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmcs.h	Thu Aug  1 19:30:10 2013	(r253863)
+++ projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmcs.h	Thu Aug  1 19:37:11 2013	(r253864)
@@ -68,6 +68,8 @@ uint64_t vmcs_read(uint32_t encoding);
 #define	vmcs_guest_cr3()		vmcs_read(VMCS_GUEST_CR3)
 #define	vmcs_gpa()			vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS)
 #define	vmcs_gla()			vmcs_read(VMCS_GUEST_LINEAR_ADDRESS)
+#define	vmcs_idt_vectoring_info()	vmcs_read(VMCS_IDT_VECTORING_INFO)
+#define	vmcs_idt_vectoring_err()	vmcs_read(VMCS_IDT_VECTORING_ERROR)
 
 #endif	/* _KERNEL */
 
@@ -314,6 +316,12 @@ uint64_t vmcs_read(uint32_t encoding);
 #define	VMCS_INTERRUPTION_INFO_NMI	(2 << 8)
 
 /*
+ * VMCS IDT-Vectoring information fields
+ */
+#define	VMCS_IDT_VEC_VALID		(1 << 31)
+#define	VMCS_IDT_VEC_ERRCODE_VALID	(1 << 11)
+
+/*
  * VMCS Guest interruptibility field
  */
 #define	VMCS_INTERRUPTIBILITY_STI_BLOCKING	(1 << 0)

Modified: projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmx.c	Thu Aug  1 19:30:10 2013	(r253863)
+++ projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmx.c	Thu Aug  1 19:37:11 2013	(r253864)
@@ -167,9 +167,6 @@ static int cap_pause_exit;
 static int cap_unrestricted_guest;
 static int cap_monitor_trap;
  
-/* statistics */
-static VMM_STAT_INTEL(VMEXIT_HLT_IGNORED, "number of times hlt was ignored");
-
 #ifdef KTR
 static const char *
 exit_reason_to_str(int reason)
@@ -1239,18 +1236,47 @@ vmx_exit_process(struct vmx *vmx, int vc
 	int error, handled;
 	struct vmcs *vmcs;
 	struct vmxctx *vmxctx;
-	uint32_t eax, ecx, edx;
-	uint64_t qual, gpa, intr_info;
+	uint32_t eax, ecx, edx, idtvec_info, idtvec_err, reason;
+	uint64_t qual, gpa;
 
 	handled = 0;
 	vmcs = &vmx->vmcs[vcpu];
 	vmxctx = &vmx->ctx[vcpu];
 	qual = vmexit->u.vmx.exit_qualification;
+	reason = vmexit->u.vmx.exit_reason;
 	vmexit->exitcode = VM_EXITCODE_BOGUS;
 
 	vmm_stat_incr(vmx->vm, vcpu, VMEXIT_COUNT, 1);
 
-	switch (vmexit->u.vmx.exit_reason) {
+	/*
+	 * VM exits that could be triggered during event injection on the
+	 * previous VM entry need to be handled specially by re-injecting
+	 * the event.
+	 *
+	 * See "Information for VM Exits During Event Delivery" in Intel SDM
+	 * for details.
+	 */
+	switch (reason) {
+	case EXIT_REASON_EPT_FAULT:
+	case EXIT_REASON_EPT_MISCONFIG:
+	case EXIT_REASON_APIC:
+	case EXIT_REASON_TASK_SWITCH:
+	case EXIT_REASON_EXCEPTION:
+		idtvec_info = vmcs_idt_vectoring_info();
+		if (idtvec_info & VMCS_IDT_VEC_VALID) {
+			idtvec_info &= ~(1 << 12); /* clear undefined bit */
+			vmwrite(VMCS_ENTRY_INTR_INFO, idtvec_info);
+			if (idtvec_info & VMCS_IDT_VEC_ERRCODE_VALID) {
+				idtvec_err = vmcs_idt_vectoring_err();
+				vmwrite(VMCS_ENTRY_EXCEPTION_ERROR, idtvec_err);
+			}
+			vmwrite(VMCS_ENTRY_INST_LENGTH, vmexit->inst_length);
+		}
+	default:
+		break;
+	}
+
+	switch (reason) {
 	case EXIT_REASON_CR_ACCESS:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_CR_ACCESS, 1);
 		handled = vmx_emulate_cr_access(vmx, vcpu, qual);
@@ -1281,19 +1307,7 @@ vmx_exit_process(struct vmx *vmx, int vc
 		break;
 	case EXIT_REASON_HLT:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_HLT, 1);
-		/*
-		 * If there is an event waiting to be injected then there is
-		 * no need to 'hlt'.
-		 */
-		error = vmread(VMCS_ENTRY_INTR_INFO, &intr_info);
-		if (error)
-			panic("vmx_exit_process: vmread(intrinfo) %d", error);
-
-		if (intr_info & VMCS_INTERRUPTION_INFO_VALID) {
-			handled = 1;
-			vmm_stat_incr(vmx->vm, vcpu, VMEXIT_HLT_IGNORED, 1);
-		} else
-			vmexit->exitcode = VM_EXITCODE_HLT;
+		vmexit->exitcode = VM_EXITCODE_HLT;
 		break;
 	case EXIT_REASON_MTF:
 		vmm_stat_incr(vmx->vm, vcpu, VMEXIT_MTRAP, 1);



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