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>