Make the KTR tracepoints uniform and ensure that every VM-exit is logged.

Discussed with:	Anish Gupta (akgupt3@gmail.com)
This commit is contained in:
Neel Natu 2014-09-10 01:37:32 +00:00
parent a2901ce7ad
commit 5e467bd098
3 changed files with 61 additions and 50 deletions

View File

@ -730,6 +730,42 @@ svm_save_intinfo(struct svm_softc *svm_sc, int vcpu)
vm_exit_intinfo(svm_sc->vm, vcpu, intinfo); vm_exit_intinfo(svm_sc->vm, vcpu, intinfo);
} }
#ifdef KTR
static const char *
exit_reason_to_str(uint64_t reason)
{
static char reasonbuf[32];
switch (reason) {
case VMCB_EXIT_INVALID:
return ("invalvmcb");
case VMCB_EXIT_SHUTDOWN:
return ("shutdown");
case VMCB_EXIT_NPF:
return ("nptfault");
case VMCB_EXIT_PAUSE:
return ("pause");
case VMCB_EXIT_HLT:
return ("hlt");
case VMCB_EXIT_CPUID:
return ("cpuid");
case VMCB_EXIT_IO:
return ("inout");
case VMCB_EXIT_MC:
return ("mchk");
case VMCB_EXIT_INTR:
return ("extintr");
case VMCB_EXIT_VINTR:
return ("vintr");
case VMCB_EXIT_MSR:
return ("msr");
default:
snprintf(reasonbuf, sizeof(reasonbuf), "%#lx", reason);
return (reasonbuf);
}
}
#endif /* KTR */
/* /*
* Determine the cause of virtual cpu exit and handle VMEXIT. * Determine the cause of virtual cpu exit and handle VMEXIT.
* Return: false - Break vcpu execution loop and handle vmexit * Return: false - Break vcpu execution loop and handle vmexit
@ -760,6 +796,8 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit)
vmexit->exitcode = VM_EXITCODE_VMX; vmexit->exitcode = VM_EXITCODE_VMX;
vmexit->u.vmx.status = 0; vmexit->u.vmx.status = 0;
vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_COUNT, 1);
KASSERT((ctrl->eventinj & VMCB_EVENTINJ_VALID) == 0, ("%s: event " KASSERT((ctrl->eventinj & VMCB_EVENTINJ_VALID) == 0, ("%s: event "
"injection valid bit is set %#lx", __func__, ctrl->eventinj)); "injection valid bit is set %#lx", __func__, ctrl->eventinj));
@ -836,8 +874,6 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit)
* interrupt, local APIC will inject event in guest. * interrupt, local APIC will inject event in guest.
*/ */
update_rip = false; update_rip = false;
VCPU_CTR1(svm_sc->vm, vcpu, "SVM:VMEXIT ExtInt"
" RIP:0x%lx.\n", state->rip);
vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_EXTINT, 1); vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_EXTINT, 1);
break; break;
@ -853,29 +889,16 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit)
(uint32_t *)&ctx->sctx_rbx, (uint32_t *)&ctx->sctx_rbx,
(uint32_t *)&ctx->sctx_rcx, (uint32_t *)&ctx->sctx_rcx,
(uint32_t *)&ctx->e.g.sctx_rdx); (uint32_t *)&ctx->e.g.sctx_rdx);
VCPU_CTR0(svm_sc->vm, vcpu, "SVM:VMEXIT CPUID\n");
break; break;
case VMCB_EXIT_HLT: case VMCB_EXIT_HLT:
vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_HLT, 1); vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_HLT, 1);
if (ctrl->v_irq) { vmexit->exitcode = VM_EXITCODE_HLT;
/* Interrupt is pending, can't halt guest. */ vmexit->u.hlt.rflags = state->rflags;
vmm_stat_incr(svm_sc->vm, vcpu, loop = false;
VMEXIT_HLT_IGNORED, 1);
VCPU_CTR0(svm_sc->vm, vcpu,
"VMEXIT halt ignored.");
} else {
VCPU_CTR0(svm_sc->vm, vcpu,
"VMEXIT halted CPU.");
vmexit->exitcode = VM_EXITCODE_HLT;
vmexit->u.hlt.rflags = state->rflags;
loop = false;
}
break; break;
case VMCB_EXIT_PAUSE: case VMCB_EXIT_PAUSE:
VCPU_CTR0(svm_sc->vm, vcpu, "SVM:VMEXIT pause");
vmexit->exitcode = VM_EXITCODE_PAUSE; vmexit->exitcode = VM_EXITCODE_PAUSE;
vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_PAUSE, 1); vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_PAUSE, 1);
@ -893,36 +916,33 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit)
break; break;
} }
/* EXITINFO2 has the physical fault address (GPA). */ /* EXITINFO2 has the physical fault address (GPA). */
if(vm_mem_allocated(svm_sc->vm, info2)) { if(vm_mem_allocated(svm_sc->vm, info2)) {
VCPU_CTR3(svm_sc->vm, vcpu, "SVM:NPF-paging,"
"RIP:0x%lx INFO1:0x%lx INFO2:0x%lx .\n",
state->rip, info1, info2);
vmexit->exitcode = VM_EXITCODE_PAGING; vmexit->exitcode = VM_EXITCODE_PAGING;
vmexit->u.paging.gpa = info2; vmexit->u.paging.gpa = info2;
vmexit->u.paging.fault_type = vmexit->u.paging.fault_type =
svm_npf_paging(info1); svm_npf_paging(info1);
vmm_stat_incr(svm_sc->vm, vcpu, vmm_stat_incr(svm_sc->vm, vcpu,
VMEXIT_NESTED_FAULT, 1); VMEXIT_NESTED_FAULT, 1);
VCPU_CTR3(svm_sc->vm, vcpu, "nested page fault "
"on gpa %#lx/%#lx at rip %#lx",
info2, info1, state->rip);
} else if (svm_npf_emul_fault(info1)) { } else if (svm_npf_emul_fault(info1)) {
VCPU_CTR3(svm_sc->vm, vcpu, "SVM:NPF inst_emul,"
"RIP:0x%lx INFO1:0x%lx INFO2:0x%lx .\n",
state->rip, info1, info2);
svm_handle_inst_emul(svm_get_vmcb(svm_sc, vcpu), svm_handle_inst_emul(svm_get_vmcb(svm_sc, vcpu),
info2, vmexit); info2, vmexit);
vmm_stat_incr(svm_sc->vm, vcpu, vmm_stat_incr(svm_sc->vm, vcpu,
VMEXIT_INST_EMUL, 1); VMEXIT_INST_EMUL, 1);
VCPU_CTR3(svm_sc->vm, vcpu, "inst_emul fault "
"for gpa %#lx/%#lx at rip %#lx",
info2, info1, state->rip);
} }
break; break;
case VMCB_EXIT_SHUTDOWN: case VMCB_EXIT_SHUTDOWN:
VCPU_CTR0(svm_sc->vm, vcpu, "SVM:VMEXIT shutdown.");
loop = false; loop = false;
break; break;
case VMCB_EXIT_INVALID: case VMCB_EXIT_INVALID:
VCPU_CTR0(svm_sc->vm, vcpu, "SVM:VMEXIT INVALID.");
loop = false; loop = false;
break; break;
@ -940,6 +960,10 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit)
break; break;
} }
VCPU_CTR4(svm_sc->vm, vcpu, "%s %s vmexit at %#lx nrip %#lx",
loop ? "handled" : "unhandled", exit_reason_to_str(code),
state->rip, update_rip ? ctrl->nrip : state->rip);
vmexit->rip = state->rip; vmexit->rip = state->rip;
if (update_rip) { if (update_rip) {
if (ctrl->nrip == 0) { if (ctrl->nrip == 0) {
@ -1274,10 +1298,6 @@ svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
vmm_stat_incr(vm, vcpu, VCPU_MIGRATIONS, 1); vmm_stat_incr(vm, vcpu, VCPU_MIGRATIONS, 1);
} }
VCPU_CTR3(vm, vcpu, "SVM:Enter vmrun RIP:0x%lx"
" inst len=%d/%d\n",
rip, vmexit->inst_length,
vmexit->u.inst_emul.vie.num_valid);
/* Update Guest RIP */ /* Update Guest RIP */
state->rip = rip; state->rip = rip;
@ -1301,23 +1321,14 @@ svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
if (vcpu_rendezvous_pending(rend_cookie)) { if (vcpu_rendezvous_pending(rend_cookie)) {
enable_gintr(); enable_gintr();
vmexit->exitcode = VM_EXITCODE_RENDEZVOUS; vm_exit_rendezvous(vm, vcpu, state->rip);
vmm_stat_incr(vm, vcpu, VMEXIT_RENDEZVOUS, 1);
VCPU_CTR1(vm, vcpu,
"SVM: VCPU rendezvous, RIP:0x%lx\n",
state->rip);
vmexit->rip = state->rip;
break; break;
} }
/* We are asked to give the cpu by scheduler. */ /* We are asked to give the cpu by scheduler. */
if (curthread->td_flags & (TDF_ASTPENDING | TDF_NEEDRESCHED)) { if (curthread->td_flags & (TDF_ASTPENDING | TDF_NEEDRESCHED)) {
enable_gintr(); enable_gintr();
vmexit->exitcode = VM_EXITCODE_BOGUS; vm_exit_astpending(vm, vcpu, state->rip);
vmm_stat_incr(vm, vcpu, VMEXIT_ASTPENDING, 1);
VCPU_CTR1(vm, vcpu,
"SVM: ASTPENDING, RIP:0x%lx\n", state->rip);
vmexit->rip = state->rip;
break; break;
} }
@ -1334,8 +1345,10 @@ svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
ctrl->vmcb_clean = VMCB_CACHE_DEFAULT & ~vcpustate->dirty; ctrl->vmcb_clean = VMCB_CACHE_DEFAULT & ~vcpustate->dirty;
vcpustate->dirty = 0; vcpustate->dirty = 0;
VCPU_CTR1(vm, vcpu, "vmcb clean %#x", ctrl->vmcb_clean);
/* Launch Virtual Machine. */ /* Launch Virtual Machine. */
VCPU_CTR1(vm, vcpu, "Resume execution at %#lx", state->rip);
svm_launch(vmcb_pa, gctx, hctx); svm_launch(vmcb_pa, gctx, hctx);
CPU_CLR_ATOMIC(thiscpu, &pmap->pm_active); CPU_CLR_ATOMIC(thiscpu, &pmap->pm_active);
@ -1366,8 +1379,6 @@ svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
/* Handle #VMEXIT and if required return to user space. */ /* Handle #VMEXIT and if required return to user space. */
loop = svm_vmexit(svm_sc, vcpu, vmexit); loop = svm_vmexit(svm_sc, vcpu, vmexit);
vcpustate->loop++;
vmm_stat_incr(vm, vcpu, VMEXIT_COUNT, 1);
} while (loop); } while (loop);
return (0); return (0);

View File

@ -44,7 +44,6 @@ struct svm_vcpu {
struct vmcb vmcb; /* hardware saved vcpu context */ struct vmcb vmcb; /* hardware saved vcpu context */
struct svm_regctx swctx; /* software saved vcpu context */ struct svm_regctx swctx; /* software saved vcpu context */
uint64_t vmcb_pa; /* VMCB physical address */ uint64_t vmcb_pa; /* VMCB physical address */
uint64_t loop; /* loop count for vcpu */
int lastcpu; /* host cpu that the vcpu last ran on */ int lastcpu; /* host cpu that the vcpu last ran on */
uint32_t dirty; /* state cache bits that must be cleared */ uint32_t dirty; /* state cache bits that must be cleared */
long eptgen; /* pmap->pm_eptgen when the vcpu last ran */ long eptgen; /* pmap->pm_eptgen when the vcpu last ran */

View File

@ -117,6 +117,7 @@
/* VMCB exit code, APM vol2 Appendix C */ /* VMCB exit code, APM vol2 Appendix C */
#define VMCB_EXIT_MC 0x52 #define VMCB_EXIT_MC 0x52
#define VMCB_EXIT_INTR 0x60 #define VMCB_EXIT_INTR 0x60
#define VMCB_EXIT_VINTR 0x64
#define VMCB_EXIT_PUSHF 0x70 #define VMCB_EXIT_PUSHF 0x70
#define VMCB_EXIT_POPF 0x71 #define VMCB_EXIT_POPF 0x71
#define VMCB_EXIT_CPUID 0x72 #define VMCB_EXIT_CPUID 0x72