aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-04-11 06:05:16 -0400
committerAvi Kivity <avi@redhat.com>2010-05-17 05:17:35 -0400
commite46479f852adab6027e4950d69400d967bf7bc6f (patch)
tree8111480e9ae6c85ef292325d6345923f0878f0c8
parent2fb53ad811e238d5dec8716b99986c3f234e3337 (diff)
KVM: Trace emulated instructions
Log emulated instructions in ftrace, especially if they failed. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--arch/x86/kvm/trace.h86
-rw-r--r--arch/x86/kvm/x86.c4
2 files changed, 90 insertions, 0 deletions
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index 32c912c40bf8..a6544b8e7c0f 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -603,6 +603,92 @@ TRACE_EVENT(kvm_skinit,
603 __entry->rip, __entry->slb) 603 __entry->rip, __entry->slb)
604); 604);
605 605
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
655TRACE_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
606#endif /* _TRACE_KVM_H */ 692#endif /* _TRACE_KVM_H */
607 693
608#undef TRACE_INCLUDE_PATH 694#undef TRACE_INCLUDE_PATH
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 247e805a041e..33a40c544c7a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3718,6 +3718,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
3718 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; 3718 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
3719 3719
3720 r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); 3720 r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
3721 trace_kvm_emulate_insn_start(vcpu);
3721 3722
3722 /* Only allow emulation of specific instructions on #UD 3723 /* Only allow emulation of specific instructions on #UD
3723 * (namely VMMCALL, sysenter, sysexit, syscall)*/ 3724 * (namely VMMCALL, sysenter, sysexit, syscall)*/
@@ -3750,6 +3751,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
3750 ++vcpu->stat.insn_emulation; 3751 ++vcpu->stat.insn_emulation;
3751 if (r) { 3752 if (r) {
3752 ++vcpu->stat.insn_emulation_fail; 3753 ++vcpu->stat.insn_emulation_fail;
3754 trace_kvm_emulate_insn_failed(vcpu);
3753 if (kvm_mmu_unprotect_page_virt(vcpu, cr2)) 3755 if (kvm_mmu_unprotect_page_virt(vcpu, cr2))
3754 return EMULATE_DONE; 3756 return EMULATE_DONE;
3755 return EMULATE_FAIL; 3757 return EMULATE_FAIL;
@@ -3786,6 +3788,8 @@ restart:
3786 if (kvm_mmu_unprotect_page_virt(vcpu, cr2)) 3788 if (kvm_mmu_unprotect_page_virt(vcpu, cr2))
3787 goto done; 3789 goto done;
3788 if (!vcpu->mmio_needed) { 3790 if (!vcpu->mmio_needed) {
3791 ++vcpu->stat.insn_emulation_fail;
3792 trace_kvm_emulate_insn_failed(vcpu);
3789 kvm_report_emulation_failure(vcpu, "mmio"); 3793 kvm_report_emulation_failure(vcpu, "mmio");
3790 return EMULATE_FAIL; 3794 return EMULATE_FAIL;
3791 } 3795 }