KVM: x86: Fix exception reinjection forced to true
[safe/jmp/linux-2.6] / arch / x86 / kvm / trace.h
index 7e1f08e..a6544b8 100644 (file)
@@ -5,8 +5,6 @@
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm
-#define TRACE_INCLUDE_PATH arch/x86/kvm
-#define TRACE_INCLUDE_FILE trace
 
 /*
  * Tracepoint for guest mode entry.
@@ -56,6 +54,38 @@ TRACE_EVENT(kvm_hypercall,
 );
 
 /*
+ * Tracepoint for hypercall.
+ */
+TRACE_EVENT(kvm_hv_hypercall,
+       TP_PROTO(__u16 code, bool fast, __u16 rep_cnt, __u16 rep_idx,
+                __u64 ingpa, __u64 outgpa),
+       TP_ARGS(code, fast, rep_cnt, rep_idx, ingpa, outgpa),
+
+       TP_STRUCT__entry(
+               __field(        __u16,          code            )
+               __field(        bool,           fast            )
+               __field(        __u16,          rep_cnt         )
+               __field(        __u16,          rep_idx         )
+               __field(        __u64,          ingpa           )
+               __field(        __u64,          outgpa          )
+       ),
+
+       TP_fast_assign(
+               __entry->code           = code;
+               __entry->fast           = fast;
+               __entry->rep_cnt        = rep_cnt;
+               __entry->rep_idx        = rep_idx;
+               __entry->ingpa          = ingpa;
+               __entry->outgpa         = outgpa;
+       ),
+
+       TP_printk("code 0x%x %s cnt 0x%x idx 0x%x in 0x%llx out 0x%llx",
+                 __entry->code, __entry->fast ? "fast" : "slow",
+                 __entry->rep_cnt, __entry->rep_idx,  __entry->ingpa,
+                 __entry->outgpa)
+);
+
+/*
  * Tracepoint for PIO.
  */
 TRACE_EVENT(kvm_pio,
@@ -152,8 +182,8 @@ TRACE_EVENT(kvm_apic,
  * Tracepoint for kvm guest exit:
  */
 TRACE_EVENT(kvm_exit,
-       TP_PROTO(unsigned int exit_reason, unsigned long guest_rip),
-       TP_ARGS(exit_reason, guest_rip),
+       TP_PROTO(unsigned int exit_reason, struct kvm_vcpu *vcpu),
+       TP_ARGS(exit_reason, vcpu),
 
        TP_STRUCT__entry(
                __field(        unsigned int,   exit_reason     )
@@ -162,7 +192,7 @@ TRACE_EVENT(kvm_exit,
 
        TP_fast_assign(
                __entry->exit_reason    = exit_reason;
-               __entry->guest_rip      = guest_rip;
+               __entry->guest_rip      = kvm_rip_read(vcpu);
        ),
 
        TP_printk("reason %s rip 0x%lx",
@@ -189,6 +219,38 @@ TRACE_EVENT(kvm_inj_virq,
        TP_printk("irq %u", __entry->irq)
 );
 
+#define EXS(x) { x##_VECTOR, "#" #x }
+
+#define kvm_trace_sym_exc                                              \
+       EXS(DE), EXS(DB), EXS(BP), EXS(OF), EXS(BR), EXS(UD), EXS(NM),  \
+       EXS(DF), EXS(TS), EXS(NP), EXS(SS), EXS(GP), EXS(PF),           \
+       EXS(MF), EXS(MC)
+
+/*
+ * Tracepoint for kvm interrupt injection:
+ */
+TRACE_EVENT(kvm_inj_exception,
+       TP_PROTO(unsigned exception, bool has_error, unsigned error_code),
+       TP_ARGS(exception, has_error, error_code),
+
+       TP_STRUCT__entry(
+               __field(        u8,     exception       )
+               __field(        u8,     has_error       )
+               __field(        u32,    error_code      )
+       ),
+
+       TP_fast_assign(
+               __entry->exception      = exception;
+               __entry->has_error      = has_error;
+               __entry->error_code     = error_code;
+       ),
+
+       TP_printk("%s (0x%x)",
+                 __print_symbolic(__entry->exception, kvm_trace_sym_exc),
+                 /* FIXME: don't print error_code if not present */
+                 __entry->has_error ? __entry->error_code : 0)
+);
+
 /*
  * Tracepoint for page fault.
  */
@@ -214,28 +276,33 @@ TRACE_EVENT(kvm_page_fault,
  * Tracepoint for guest MSR access.
  */
 TRACE_EVENT(kvm_msr,
-       TP_PROTO(unsigned int rw, unsigned int ecx, unsigned long data),
-       TP_ARGS(rw, ecx, data),
+       TP_PROTO(unsigned write, u32 ecx, u64 data, bool exception),
+       TP_ARGS(write, ecx, data, exception),
 
        TP_STRUCT__entry(
-               __field(        unsigned int,   rw              )
-               __field(        unsigned int,   ecx             )
-               __field(        unsigned long,  data            )
+               __field(        unsigned,       write           )
+               __field(        u32,            ecx             )
+               __field(        u64,            data            )
+               __field(        u8,             exception       )
        ),
 
        TP_fast_assign(
-               __entry->rw             = rw;
+               __entry->write          = write;
                __entry->ecx            = ecx;
                __entry->data           = data;
+               __entry->exception      = exception;
        ),
 
-       TP_printk("msr_%s %x = 0x%lx",
-                 __entry->rw ? "write" : "read",
-                 __entry->ecx, __entry->data)
+       TP_printk("msr_%s %x = 0x%llx%s",
+                 __entry->write ? "write" : "read",
+                 __entry->ecx, __entry->data,
+                 __entry->exception ? " (#GP)" : "")
 );
 
-#define trace_kvm_msr_read(ecx, data)          trace_kvm_msr(0, ecx, data)
-#define trace_kvm_msr_write(ecx, data)         trace_kvm_msr(1, ecx, data)
+#define trace_kvm_msr_read(ecx, data)      trace_kvm_msr(0, ecx, data, false)
+#define trace_kvm_msr_write(ecx, data)     trace_kvm_msr(1, ecx, data, false)
+#define trace_kvm_msr_read_ex(ecx)         trace_kvm_msr(0, ecx, 0, true)
+#define trace_kvm_msr_write_ex(ecx, data)  trace_kvm_msr(1, ecx, data, true)
 
 /*
  * Tracepoint for guest CR access.
@@ -376,12 +443,34 @@ TRACE_EVENT(kvm_nested_vmrun,
        ),
 
        TP_printk("rip: 0x%016llx vmcb: 0x%016llx nrip: 0x%016llx int_ctl: 0x%08x "
-                 "event_inj: 0x%08x npt: %s\n",
+                 "event_inj: 0x%08x npt: %s",
                __entry->rip, __entry->vmcb, __entry->nested_rip,
                __entry->int_ctl, __entry->event_inj,
                __entry->npt ? "on" : "off")
 );
 
+TRACE_EVENT(kvm_nested_intercepts,
+           TP_PROTO(__u16 cr_read, __u16 cr_write, __u32 exceptions, __u64 intercept),
+           TP_ARGS(cr_read, cr_write, exceptions, intercept),
+
+       TP_STRUCT__entry(
+               __field(        __u16,          cr_read         )
+               __field(        __u16,          cr_write        )
+               __field(        __u32,          exceptions      )
+               __field(        __u64,          intercept       )
+       ),
+
+       TP_fast_assign(
+               __entry->cr_read        = cr_read;
+               __entry->cr_write       = cr_write;
+               __entry->exceptions     = exceptions;
+               __entry->intercept      = intercept;
+       ),
+
+       TP_printk("cr_read: %04x cr_write: %04x excp: %08x intercept: %016llx",
+               __entry->cr_read, __entry->cr_write, __entry->exceptions,
+               __entry->intercept)
+);
 /*
  * Tracepoint for #VMEXIT while nested
  */
@@ -410,7 +499,7 @@ TRACE_EVENT(kvm_nested_vmexit,
                __entry->exit_int_info_err      = exit_int_info_err;
        ),
        TP_printk("rip: 0x%016llx reason: %s ext_inf1: 0x%016llx "
-                 "ext_inf2: 0x%016llx ext_int: 0x%08x ext_int_err: 0x%08x\n",
+                 "ext_inf2: 0x%016llx ext_int: 0x%08x ext_int_err: 0x%08x",
                  __entry->rip,
                  ftrace_print_symbols_seq(p, __entry->exit_code,
                                           kvm_x86_ops->exit_reasons_str),
@@ -445,7 +534,7 @@ TRACE_EVENT(kvm_nested_vmexit_inject,
        ),
 
        TP_printk("reason: %s ext_inf1: 0x%016llx "
-                 "ext_inf2: 0x%016llx ext_int: 0x%08x ext_int_err: 0x%08x\n",
+                 "ext_inf2: 0x%016llx ext_int: 0x%08x ext_int_err: 0x%08x",
                  ftrace_print_symbols_seq(p, __entry->exit_code,
                                           kvm_x86_ops->exit_reasons_str),
                __entry->exit_info1, __entry->exit_info2,
@@ -467,7 +556,7 @@ TRACE_EVENT(kvm_nested_intr_vmexit,
                __entry->rip    =       rip
        ),
 
-       TP_printk("rip: 0x%016llx\n", __entry->rip)
+       TP_printk("rip: 0x%016llx", __entry->rip)
 );
 
 /*
@@ -489,10 +578,123 @@ TRACE_EVENT(kvm_invlpga,
                __entry->address        =       address;
        ),
 
-       TP_printk("rip: 0x%016llx asid: %d address: 0x%016llx\n",
+       TP_printk("rip: 0x%016llx asid: %d address: 0x%016llx",
                  __entry->rip, __entry->asid, __entry->address)
 );
+
+/*
+ * Tracepoint for nested #vmexit because of interrupt pending
+ */
+TRACE_EVENT(kvm_skinit,
+           TP_PROTO(__u64 rip, __u32 slb),
+           TP_ARGS(rip, slb),
+
+       TP_STRUCT__entry(
+               __field(        __u64,  rip     )
+               __field(        __u32,  slb     )
+       ),
+
+       TP_fast_assign(
+               __entry->rip            =       rip;
+               __entry->slb            =       slb;
+       ),
+
+       TP_printk("rip: 0x%016llx slb: 0x%08x",
+                 __entry->rip, __entry->slb)
+);
+
+#define __print_insn(insn, ilen) ({                             \
+       int i;                                                   \
+       const char *ret = p->buffer + p->len;                    \
+                                                                \
+       for (i = 0; i < ilen; ++i)                               \
+               trace_seq_printf(p, " %02x", insn[i]);           \
+       trace_seq_printf(p, "%c", 0);                            \
+       ret;                                                     \
+       })
+
+#define KVM_EMUL_INSN_F_CR0_PE (1 << 0)
+#define KVM_EMUL_INSN_F_EFL_VM (1 << 1)
+#define KVM_EMUL_INSN_F_CS_D   (1 << 2)
+#define KVM_EMUL_INSN_F_CS_L   (1 << 3)
+
+#define kvm_trace_symbol_emul_flags                      \
+       { 0,                        "real" },             \
+       { KVM_EMUL_INSN_F_CR0_PE                          \
+         | KVM_EMUL_INSN_F_EFL_VM, "vm16" },             \
+       { KVM_EMUL_INSN_F_CR0_PE,   "prot16" },           \
+       { KVM_EMUL_INSN_F_CR0_PE                          \
+         | KVM_EMUL_INSN_F_CS_D,   "prot32" },           \
+       { KVM_EMUL_INSN_F_CR0_PE                          \
+         | KVM_EMUL_INSN_F_CS_L,   "prot64" }
+
+#define kei_decode_mode(mode) ({                       \
+       u8 flags = 0xff;                                \
+       switch (mode) {                                 \
+       case X86EMUL_MODE_REAL:                         \
+               flags = 0;                              \
+               break;                                  \
+       case X86EMUL_MODE_VM86:                         \
+               flags = KVM_EMUL_INSN_F_EFL_VM;         \
+               break;                                  \
+       case X86EMUL_MODE_PROT16:                       \
+               flags = KVM_EMUL_INSN_F_CR0_PE;         \
+               break;                                  \
+       case X86EMUL_MODE_PROT32:                       \
+               flags = KVM_EMUL_INSN_F_CR0_PE          \
+                       | KVM_EMUL_INSN_F_CS_D;         \
+               break;                                  \
+       case X86EMUL_MODE_PROT64:                       \
+               flags = KVM_EMUL_INSN_F_CR0_PE          \
+                       | KVM_EMUL_INSN_F_CS_L;         \
+               break;                                  \
+       }                                               \
+       flags;                                          \
+       })
+
+TRACE_EVENT(kvm_emulate_insn,
+       TP_PROTO(struct kvm_vcpu *vcpu, __u8 failed),
+       TP_ARGS(vcpu, failed),
+
+       TP_STRUCT__entry(
+               __field(    __u64, rip                       )
+               __field(    __u32, csbase                    )
+               __field(    __u8,  len                       )
+               __array(    __u8,  insn,    15               )
+               __field(    __u8,  flags                     )
+               __field(    __u8,  failed                    )
+               ),
+
+       TP_fast_assign(
+               __entry->rip = vcpu->arch.emulate_ctxt.decode.fetch.start;
+               __entry->csbase = kvm_x86_ops->get_segment_base(vcpu, VCPU_SREG_CS);
+               __entry->len = vcpu->arch.emulate_ctxt.decode.eip
+                              - vcpu->arch.emulate_ctxt.decode.fetch.start;
+               memcpy(__entry->insn,
+                      vcpu->arch.emulate_ctxt.decode.fetch.data,
+                      15);
+               __entry->flags = kei_decode_mode(vcpu->arch.emulate_ctxt.mode);
+               __entry->failed = failed;
+               ),
+
+       TP_printk("%x:%llx:%s (%s)%s",
+                 __entry->csbase, __entry->rip,
+                 __print_insn(__entry->insn, __entry->len),
+                 __print_symbolic(__entry->flags,
+                                  kvm_trace_symbol_emul_flags),
+                 __entry->failed ? " failed" : ""
+               )
+       );
+
+#define trace_kvm_emulate_insn_start(vcpu) trace_kvm_emulate_insn(vcpu, 0)
+#define trace_kvm_emulate_insn_failed(vcpu) trace_kvm_emulate_insn(vcpu, 1)
+
 #endif /* _TRACE_KVM_H */
 
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH arch/x86/kvm
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
 /* This part must be outside protection */
 #include <trace/define_trace.h>