| 2325 | } |
| 2326 | |
| 2327 | static int |
| 2328 | vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) |
| 2329 | { |
| 2330 | int error, errcode, errcode_valid, handled, in; |
| 2331 | struct vmxctx *vmxctx; |
| 2332 | struct vlapic *vlapic; |
| 2333 | struct vm_inout_str *vis; |
| 2334 | struct vm_task_switch *ts; |
| 2335 | uint32_t eax, ecx, edx, idtvec_info, idtvec_err, intr_info, inst_info; |
| 2336 | uint32_t intr_type, intr_vec, reason; |
| 2337 | uint64_t exitintinfo, qual, gpa; |
| 2338 | bool retu; |
| 2339 | |
| 2340 | CTASSERT((PINBASED_CTLS_ONE_SETTING & PINBASED_VIRTUAL_NMI) != 0); |
| 2341 | CTASSERT((PINBASED_CTLS_ONE_SETTING & PINBASED_NMI_EXITING) != 0); |
| 2342 | |
| 2343 | handled = UNHANDLED; |
| 2344 | vmxctx = &vmx->ctx[vcpu]; |
| 2345 | |
| 2346 | qual = vmexit->u.vmx.exit_qualification; |
| 2347 | reason = vmexit->u.vmx.exit_reason; |
| 2348 | vmexit->exitcode = VM_EXITCODE_BOGUS; |
| 2349 | |
| 2350 | vmm_stat_incr(vmx->vm, vcpu, VMEXIT_COUNT, 1); |
| 2351 | SDT_PROBE3(vmm, vmx, exit, entry, vmx, vcpu, vmexit); |
| 2352 | |
| 2353 | /* |
| 2354 | * VM-entry failures during or after loading guest state. |
| 2355 | * |
| 2356 | * These VM-exits are uncommon but must be handled specially |
| 2357 | * as most VM-exit fields are not populated as usual. |
| 2358 | */ |
| 2359 | if (__predict_false(reason == EXIT_REASON_MCE_DURING_ENTRY)) { |
| 2360 | VCPU_CTR0(vmx->vm, vcpu, "Handling MCE during VM-entry"); |
| 2361 | __asm __volatile("int $18"); |
| 2362 | return (1); |
| 2363 | } |
| 2364 | |
| 2365 | /* |
| 2366 | * VM exits that can be triggered during event delivery need to |
| 2367 | * be handled specially by re-injecting the event if the IDT |
| 2368 | * vectoring information field's valid bit is set. |
| 2369 | * |
| 2370 | * See "Information for VM Exits During Event Delivery" in Intel SDM |
| 2371 | * for details. |
| 2372 | */ |
| 2373 | idtvec_info = vmcs_idt_vectoring_info(); |
| 2374 | if (idtvec_info & VMCS_IDT_VEC_VALID) { |
| 2375 | idtvec_info &= ~(1 << 12); /* clear undefined bit */ |
| 2376 | exitintinfo = idtvec_info; |
| 2377 | if (idtvec_info & VMCS_IDT_VEC_ERRCODE_VALID) { |
| 2378 | idtvec_err = vmcs_idt_vectoring_err(); |
| 2379 | exitintinfo |= (uint64_t)idtvec_err << 32; |
| 2380 | } |
| 2381 | error = vm_exit_intinfo(vmx->vm, vcpu, exitintinfo); |
| 2382 | KASSERT(error == 0, ("%s: vm_set_intinfo error %d", |
| 2383 | __func__, error)); |
| 2384 |
no test coverage detected