diff options
-rw-r--r-- | arch/x86/kvm/trace.h | 86 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 4 |
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 | |||
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 | |||
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 | } |