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:
parent
a2901ce7ad
commit
5e467bd098
@ -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));
|
||||||
|
|
||||||
@ -776,7 +814,7 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit)
|
|||||||
eax = state->rax;
|
eax = state->rax;
|
||||||
ecx = ctx->sctx_rcx;
|
ecx = ctx->sctx_rcx;
|
||||||
edx = ctx->e.g.sctx_rdx;
|
edx = ctx->e.g.sctx_rdx;
|
||||||
|
|
||||||
if (ecx == MSR_EFER) {
|
if (ecx == MSR_EFER) {
|
||||||
KASSERT(info1 != 0, ("rdmsr(MSR_EFER) is not "
|
KASSERT(info1 != 0, ("rdmsr(MSR_EFER) is not "
|
||||||
"emulated: info1(%#lx) info2(%#lx)",
|
"emulated: info1(%#lx) info2(%#lx)",
|
||||||
@ -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,10 +1379,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user