Skip to content

Commit e46479f

Browse files
committed
KVM: Trace emulated instructions
Log emulated instructions in ftrace, especially if they failed. Signed-off-by: Avi Kivity <[email protected]> Signed-off-by: Marcelo Tosatti <[email protected]>
1 parent 2fb53ad commit e46479f

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

arch/x86/kvm/trace.h

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,92 @@ TRACE_EVENT(kvm_skinit,
603603
__entry->rip, __entry->slb)
604604
);
605605

606+
#define __print_insn(insn, ilen) ({ \
607+
int i; \
608+
const char *ret = p->buffer + p->len; \
609+
\
610+
for (i = 0; i < ilen; ++i) \
611+
trace_seq_printf(p, " %02x", insn[i]); \
612+
trace_seq_printf(p, "%c", 0); \
613+
ret; \
614+
})
615+
616+
#define KVM_EMUL_INSN_F_CR0_PE (1 << 0)
617+
#define KVM_EMUL_INSN_F_EFL_VM (1 << 1)
618+
#define KVM_EMUL_INSN_F_CS_D (1 << 2)
619+
#define KVM_EMUL_INSN_F_CS_L (1 << 3)
620+
621+
#define kvm_trace_symbol_emul_flags \
622+
{ 0, "real" }, \
623+
{ KVM_EMUL_INSN_F_CR0_PE \
624+
| KVM_EMUL_INSN_F_EFL_VM, "vm16" }, \
625+
{ KVM_EMUL_INSN_F_CR0_PE, "prot16" }, \
626+
{ KVM_EMUL_INSN_F_CR0_PE \
627+
| KVM_EMUL_INSN_F_CS_D, "prot32" }, \
628+
{ KVM_EMUL_INSN_F_CR0_PE \
629+
| KVM_EMUL_INSN_F_CS_L, "prot64" }
630+
631+
#define kei_decode_mode(mode) ({ \
632+
u8 flags = 0xff; \
633+
switch (mode) { \
634+
case X86EMUL_MODE_REAL: \
635+
flags = 0; \
636+
break; \
637+
case X86EMUL_MODE_VM86: \
638+
flags = KVM_EMUL_INSN_F_EFL_VM; \
639+
break; \
640+
case X86EMUL_MODE_PROT16: \
641+
flags = KVM_EMUL_INSN_F_CR0_PE; \
642+
break; \
643+
case X86EMUL_MODE_PROT32: \
644+
flags = KVM_EMUL_INSN_F_CR0_PE \
645+
| KVM_EMUL_INSN_F_CS_D; \
646+
break; \
647+
case X86EMUL_MODE_PROT64: \
648+
flags = KVM_EMUL_INSN_F_CR0_PE \
649+
| KVM_EMUL_INSN_F_CS_L; \
650+
break; \
651+
} \
652+
flags; \
653+
})
654+
655+
TRACE_EVENT(kvm_emulate_insn,
656+
TP_PROTO(struct kvm_vcpu *vcpu, __u8 failed),
657+
TP_ARGS(vcpu, failed),
658+
659+
TP_STRUCT__entry(
660+
__field( __u64, rip )
661+
__field( __u32, csbase )
662+
__field( __u8, len )
663+
__array( __u8, insn, 15 )
664+
__field( __u8, flags )
665+
__field( __u8, failed )
666+
),
667+
668+
TP_fast_assign(
669+
__entry->rip = vcpu->arch.emulate_ctxt.decode.fetch.start;
670+
__entry->csbase = kvm_x86_ops->get_segment_base(vcpu, VCPU_SREG_CS);
671+
__entry->len = vcpu->arch.emulate_ctxt.decode.eip
672+
- vcpu->arch.emulate_ctxt.decode.fetch.start;
673+
memcpy(__entry->insn,
674+
vcpu->arch.emulate_ctxt.decode.fetch.data,
675+
15);
676+
__entry->flags = kei_decode_mode(vcpu->arch.emulate_ctxt.mode);
677+
__entry->failed = failed;
678+
),
679+
680+
TP_printk("%x:%llx:%s (%s)%s",
681+
__entry->csbase, __entry->rip,
682+
__print_insn(__entry->insn, __entry->len),
683+
__print_symbolic(__entry->flags,
684+
kvm_trace_symbol_emul_flags),
685+
__entry->failed ? " failed" : ""
686+
)
687+
);
688+
689+
#define trace_kvm_emulate_insn_start(vcpu) trace_kvm_emulate_insn(vcpu, 0)
690+
#define trace_kvm_emulate_insn_failed(vcpu) trace_kvm_emulate_insn(vcpu, 1)
691+
606692
#endif /* _TRACE_KVM_H */
607693

608694
#undef TRACE_INCLUDE_PATH

arch/x86/kvm/x86.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3718,6 +3718,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
37183718
? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
37193719

37203720
r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
3721+
trace_kvm_emulate_insn_start(vcpu);
37213722

37223723
/* Only allow emulation of specific instructions on #UD
37233724
* (namely VMMCALL, sysenter, sysexit, syscall)*/
@@ -3750,6 +3751,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
37503751
++vcpu->stat.insn_emulation;
37513752
if (r) {
37523753
++vcpu->stat.insn_emulation_fail;
3754+
trace_kvm_emulate_insn_failed(vcpu);
37533755
if (kvm_mmu_unprotect_page_virt(vcpu, cr2))
37543756
return EMULATE_DONE;
37553757
return EMULATE_FAIL;
@@ -3786,6 +3788,8 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
37863788
if (kvm_mmu_unprotect_page_virt(vcpu, cr2))
37873789
goto done;
37883790
if (!vcpu->mmio_needed) {
3791+
++vcpu->stat.insn_emulation_fail;
3792+
trace_kvm_emulate_insn_failed(vcpu);
37893793
kvm_report_emulation_failure(vcpu, "mmio");
37903794
return EMULATE_FAIL;
37913795
}

0 commit comments

Comments
 (0)