0001
0002
0003
0004
0005 #include <stdio.h>
0006 #include <stdlib.h>
0007 #include <string.h>
0008 #include <stdint.h>
0009
0010 #include "event-parse.h"
0011 #include "trace-seq.h"
0012
0013 #ifdef HAVE_UDIS86
0014
0015 #include <udis86.h>
0016
0017 static ud_t ud;
0018
0019 static void init_disassembler(void)
0020 {
0021 ud_init(&ud);
0022 ud_set_syntax(&ud, UD_SYN_ATT);
0023 }
0024
0025 static const char *disassemble(unsigned char *insn, int len, uint64_t rip,
0026 int cr0_pe, int eflags_vm,
0027 int cs_d, int cs_l)
0028 {
0029 int mode;
0030
0031 if (!cr0_pe)
0032 mode = 16;
0033 else if (eflags_vm)
0034 mode = 16;
0035 else if (cs_l)
0036 mode = 64;
0037 else if (cs_d)
0038 mode = 32;
0039 else
0040 mode = 16;
0041
0042 ud_set_pc(&ud, rip);
0043 ud_set_mode(&ud, mode);
0044 ud_set_input_buffer(&ud, insn, len);
0045 ud_disassemble(&ud);
0046 return ud_insn_asm(&ud);
0047 }
0048
0049 #else
0050
0051 static void init_disassembler(void)
0052 {
0053 }
0054
0055 static const char *disassemble(unsigned char *insn, int len, uint64_t rip,
0056 int cr0_pe, int eflags_vm,
0057 int cs_d, int cs_l)
0058 {
0059 static char out[15*3+1];
0060 int i;
0061
0062 for (i = 0; i < len; ++i)
0063 sprintf(out + i * 3, "%02x ", insn[i]);
0064 out[len*3-1] = '\0';
0065 return out;
0066 }
0067
0068 #endif
0069
0070
0071 #define VMX_EXIT_REASONS \
0072 _ER(EXCEPTION_NMI, 0) \
0073 _ER(EXTERNAL_INTERRUPT, 1) \
0074 _ER(TRIPLE_FAULT, 2) \
0075 _ER(PENDING_INTERRUPT, 7) \
0076 _ER(NMI_WINDOW, 8) \
0077 _ER(TASK_SWITCH, 9) \
0078 _ER(CPUID, 10) \
0079 _ER(HLT, 12) \
0080 _ER(INVD, 13) \
0081 _ER(INVLPG, 14) \
0082 _ER(RDPMC, 15) \
0083 _ER(RDTSC, 16) \
0084 _ER(VMCALL, 18) \
0085 _ER(VMCLEAR, 19) \
0086 _ER(VMLAUNCH, 20) \
0087 _ER(VMPTRLD, 21) \
0088 _ER(VMPTRST, 22) \
0089 _ER(VMREAD, 23) \
0090 _ER(VMRESUME, 24) \
0091 _ER(VMWRITE, 25) \
0092 _ER(VMOFF, 26) \
0093 _ER(VMON, 27) \
0094 _ER(CR_ACCESS, 28) \
0095 _ER(DR_ACCESS, 29) \
0096 _ER(IO_INSTRUCTION, 30) \
0097 _ER(MSR_READ, 31) \
0098 _ER(MSR_WRITE, 32) \
0099 _ER(MWAIT_INSTRUCTION, 36) \
0100 _ER(MONITOR_INSTRUCTION, 39) \
0101 _ER(PAUSE_INSTRUCTION, 40) \
0102 _ER(MCE_DURING_VMENTRY, 41) \
0103 _ER(TPR_BELOW_THRESHOLD, 43) \
0104 _ER(APIC_ACCESS, 44) \
0105 _ER(EOI_INDUCED, 45) \
0106 _ER(EPT_VIOLATION, 48) \
0107 _ER(EPT_MISCONFIG, 49) \
0108 _ER(INVEPT, 50) \
0109 _ER(PREEMPTION_TIMER, 52) \
0110 _ER(WBINVD, 54) \
0111 _ER(XSETBV, 55) \
0112 _ER(APIC_WRITE, 56) \
0113 _ER(INVPCID, 58) \
0114 _ER(PML_FULL, 62) \
0115 _ER(XSAVES, 63) \
0116 _ER(XRSTORS, 64)
0117
0118 #define SVM_EXIT_REASONS \
0119 _ER(EXIT_READ_CR0, 0x000) \
0120 _ER(EXIT_READ_CR3, 0x003) \
0121 _ER(EXIT_READ_CR4, 0x004) \
0122 _ER(EXIT_READ_CR8, 0x008) \
0123 _ER(EXIT_WRITE_CR0, 0x010) \
0124 _ER(EXIT_WRITE_CR3, 0x013) \
0125 _ER(EXIT_WRITE_CR4, 0x014) \
0126 _ER(EXIT_WRITE_CR8, 0x018) \
0127 _ER(EXIT_READ_DR0, 0x020) \
0128 _ER(EXIT_READ_DR1, 0x021) \
0129 _ER(EXIT_READ_DR2, 0x022) \
0130 _ER(EXIT_READ_DR3, 0x023) \
0131 _ER(EXIT_READ_DR4, 0x024) \
0132 _ER(EXIT_READ_DR5, 0x025) \
0133 _ER(EXIT_READ_DR6, 0x026) \
0134 _ER(EXIT_READ_DR7, 0x027) \
0135 _ER(EXIT_WRITE_DR0, 0x030) \
0136 _ER(EXIT_WRITE_DR1, 0x031) \
0137 _ER(EXIT_WRITE_DR2, 0x032) \
0138 _ER(EXIT_WRITE_DR3, 0x033) \
0139 _ER(EXIT_WRITE_DR4, 0x034) \
0140 _ER(EXIT_WRITE_DR5, 0x035) \
0141 _ER(EXIT_WRITE_DR6, 0x036) \
0142 _ER(EXIT_WRITE_DR7, 0x037) \
0143 _ER(EXIT_EXCP_DE, 0x040) \
0144 _ER(EXIT_EXCP_DB, 0x041) \
0145 _ER(EXIT_EXCP_BP, 0x043) \
0146 _ER(EXIT_EXCP_OF, 0x044) \
0147 _ER(EXIT_EXCP_BR, 0x045) \
0148 _ER(EXIT_EXCP_UD, 0x046) \
0149 _ER(EXIT_EXCP_NM, 0x047) \
0150 _ER(EXIT_EXCP_DF, 0x048) \
0151 _ER(EXIT_EXCP_TS, 0x04a) \
0152 _ER(EXIT_EXCP_NP, 0x04b) \
0153 _ER(EXIT_EXCP_SS, 0x04c) \
0154 _ER(EXIT_EXCP_GP, 0x04d) \
0155 _ER(EXIT_EXCP_PF, 0x04e) \
0156 _ER(EXIT_EXCP_MF, 0x050) \
0157 _ER(EXIT_EXCP_AC, 0x051) \
0158 _ER(EXIT_EXCP_MC, 0x052) \
0159 _ER(EXIT_EXCP_XF, 0x053) \
0160 _ER(EXIT_INTR, 0x060) \
0161 _ER(EXIT_NMI, 0x061) \
0162 _ER(EXIT_SMI, 0x062) \
0163 _ER(EXIT_INIT, 0x063) \
0164 _ER(EXIT_VINTR, 0x064) \
0165 _ER(EXIT_CR0_SEL_WRITE, 0x065) \
0166 _ER(EXIT_IDTR_READ, 0x066) \
0167 _ER(EXIT_GDTR_READ, 0x067) \
0168 _ER(EXIT_LDTR_READ, 0x068) \
0169 _ER(EXIT_TR_READ, 0x069) \
0170 _ER(EXIT_IDTR_WRITE, 0x06a) \
0171 _ER(EXIT_GDTR_WRITE, 0x06b) \
0172 _ER(EXIT_LDTR_WRITE, 0x06c) \
0173 _ER(EXIT_TR_WRITE, 0x06d) \
0174 _ER(EXIT_RDTSC, 0x06e) \
0175 _ER(EXIT_RDPMC, 0x06f) \
0176 _ER(EXIT_PUSHF, 0x070) \
0177 _ER(EXIT_POPF, 0x071) \
0178 _ER(EXIT_CPUID, 0x072) \
0179 _ER(EXIT_RSM, 0x073) \
0180 _ER(EXIT_IRET, 0x074) \
0181 _ER(EXIT_SWINT, 0x075) \
0182 _ER(EXIT_INVD, 0x076) \
0183 _ER(EXIT_PAUSE, 0x077) \
0184 _ER(EXIT_HLT, 0x078) \
0185 _ER(EXIT_INVLPG, 0x079) \
0186 _ER(EXIT_INVLPGA, 0x07a) \
0187 _ER(EXIT_IOIO, 0x07b) \
0188 _ER(EXIT_MSR, 0x07c) \
0189 _ER(EXIT_TASK_SWITCH, 0x07d) \
0190 _ER(EXIT_FERR_FREEZE, 0x07e) \
0191 _ER(EXIT_SHUTDOWN, 0x07f) \
0192 _ER(EXIT_VMRUN, 0x080) \
0193 _ER(EXIT_VMMCALL, 0x081) \
0194 _ER(EXIT_VMLOAD, 0x082) \
0195 _ER(EXIT_VMSAVE, 0x083) \
0196 _ER(EXIT_STGI, 0x084) \
0197 _ER(EXIT_CLGI, 0x085) \
0198 _ER(EXIT_SKINIT, 0x086) \
0199 _ER(EXIT_RDTSCP, 0x087) \
0200 _ER(EXIT_ICEBP, 0x088) \
0201 _ER(EXIT_WBINVD, 0x089) \
0202 _ER(EXIT_MONITOR, 0x08a) \
0203 _ER(EXIT_MWAIT, 0x08b) \
0204 _ER(EXIT_MWAIT_COND, 0x08c) \
0205 _ER(EXIT_XSETBV, 0x08d) \
0206 _ER(EXIT_NPF, 0x400) \
0207 _ER(EXIT_AVIC_INCOMPLETE_IPI, 0x401) \
0208 _ER(EXIT_AVIC_UNACCELERATED_ACCESS, 0x402) \
0209 _ER(EXIT_ERR, -1)
0210
0211 #define _ER(reason, val) { #reason, val },
0212 struct str_values {
0213 const char *str;
0214 int val;
0215 };
0216
0217 static struct str_values vmx_exit_reasons[] = {
0218 VMX_EXIT_REASONS
0219 { NULL, -1}
0220 };
0221
0222 static struct str_values svm_exit_reasons[] = {
0223 SVM_EXIT_REASONS
0224 { NULL, -1}
0225 };
0226
0227 static struct isa_exit_reasons {
0228 unsigned isa;
0229 struct str_values *strings;
0230 } isa_exit_reasons[] = {
0231 { .isa = 1, .strings = vmx_exit_reasons },
0232 { .isa = 2, .strings = svm_exit_reasons },
0233 { }
0234 };
0235
0236 static const char *find_exit_reason(unsigned isa, int val)
0237 {
0238 struct str_values *strings = NULL;
0239 int i;
0240
0241 for (i = 0; isa_exit_reasons[i].strings; ++i)
0242 if (isa_exit_reasons[i].isa == isa) {
0243 strings = isa_exit_reasons[i].strings;
0244 break;
0245 }
0246 if (!strings)
0247 return "UNKNOWN-ISA";
0248 for (i = 0; strings[i].str; i++)
0249 if (strings[i].val == val)
0250 break;
0251
0252 return strings[i].str;
0253 }
0254
0255 static int print_exit_reason(struct trace_seq *s, struct tep_record *record,
0256 struct tep_event *event, const char *field)
0257 {
0258 unsigned long long isa;
0259 unsigned long long val;
0260 const char *reason;
0261
0262 if (tep_get_field_val(s, event, field, record, &val, 1) < 0)
0263 return -1;
0264
0265 if (tep_get_field_val(s, event, "isa", record, &isa, 0) < 0)
0266 isa = 1;
0267
0268 reason = find_exit_reason(isa, val);
0269 if (reason)
0270 trace_seq_printf(s, "reason %s", reason);
0271 else
0272 trace_seq_printf(s, "reason UNKNOWN (%llu)", val);
0273 return 0;
0274 }
0275
0276 static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record,
0277 struct tep_event *event, void *context)
0278 {
0279 unsigned long long info1 = 0, info2 = 0;
0280
0281 if (print_exit_reason(s, record, event, "exit_reason") < 0)
0282 return -1;
0283
0284 tep_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1);
0285
0286 if (tep_get_field_val(s, event, "info1", record, &info1, 0) >= 0
0287 && tep_get_field_val(s, event, "info2", record, &info2, 0) >= 0)
0288 trace_seq_printf(s, " info %llx %llx", info1, info2);
0289
0290 return 0;
0291 }
0292
0293 #define KVM_EMUL_INSN_F_CR0_PE (1 << 0)
0294 #define KVM_EMUL_INSN_F_EFL_VM (1 << 1)
0295 #define KVM_EMUL_INSN_F_CS_D (1 << 2)
0296 #define KVM_EMUL_INSN_F_CS_L (1 << 3)
0297
0298 static int kvm_emulate_insn_handler(struct trace_seq *s,
0299 struct tep_record *record,
0300 struct tep_event *event, void *context)
0301 {
0302 unsigned long long rip, csbase, len, flags, failed;
0303 int llen;
0304 uint8_t *insn;
0305 const char *disasm;
0306
0307 if (tep_get_field_val(s, event, "rip", record, &rip, 1) < 0)
0308 return -1;
0309
0310 if (tep_get_field_val(s, event, "csbase", record, &csbase, 1) < 0)
0311 return -1;
0312
0313 if (tep_get_field_val(s, event, "len", record, &len, 1) < 0)
0314 return -1;
0315
0316 if (tep_get_field_val(s, event, "flags", record, &flags, 1) < 0)
0317 return -1;
0318
0319 if (tep_get_field_val(s, event, "failed", record, &failed, 1) < 0)
0320 return -1;
0321
0322 insn = tep_get_field_raw(s, event, "insn", record, &llen, 1);
0323 if (!insn)
0324 return -1;
0325
0326 disasm = disassemble(insn, len, rip,
0327 flags & KVM_EMUL_INSN_F_CR0_PE,
0328 flags & KVM_EMUL_INSN_F_EFL_VM,
0329 flags & KVM_EMUL_INSN_F_CS_D,
0330 flags & KVM_EMUL_INSN_F_CS_L);
0331
0332 trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm,
0333 failed ? " FAIL" : "");
0334 return 0;
0335 }
0336
0337
0338 static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_record *record,
0339 struct tep_event *event, void *context)
0340 {
0341 if (print_exit_reason(s, record, event, "exit_code") < 0)
0342 return -1;
0343
0344 tep_print_num_field(s, " info1 %llx", event, "exit_info1", record, 1);
0345 tep_print_num_field(s, " info2 %llx", event, "exit_info2", record, 1);
0346 tep_print_num_field(s, " int_info %llx", event, "exit_int_info", record, 1);
0347 tep_print_num_field(s, " int_info_err %llx", event, "exit_int_info_err", record, 1);
0348
0349 return 0;
0350 }
0351
0352 static int kvm_nested_vmexit_handler(struct trace_seq *s, struct tep_record *record,
0353 struct tep_event *event, void *context)
0354 {
0355 tep_print_num_field(s, "rip %llx ", event, "rip", record, 1);
0356
0357 return kvm_nested_vmexit_inject_handler(s, record, event, context);
0358 }
0359
0360 union kvm_mmu_page_role {
0361 unsigned word;
0362 struct {
0363 unsigned level:4;
0364 unsigned cr4_pae:1;
0365 unsigned quadrant:2;
0366 unsigned direct:1;
0367 unsigned access:3;
0368 unsigned invalid:1;
0369 unsigned efer_nx:1;
0370 unsigned cr0_wp:1;
0371 unsigned smep_and_not_wp:1;
0372 unsigned smap_and_not_wp:1;
0373 unsigned pad_for_nice_hex_output:8;
0374 unsigned smm:8;
0375 };
0376 };
0377
0378 static int kvm_mmu_print_role(struct trace_seq *s, struct tep_record *record,
0379 struct tep_event *event, void *context)
0380 {
0381 unsigned long long val;
0382 static const char *access_str[] = {
0383 "---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux"
0384 };
0385 union kvm_mmu_page_role role;
0386
0387 if (tep_get_field_val(s, event, "role", record, &val, 1) < 0)
0388 return -1;
0389
0390 role.word = (int)val;
0391
0392
0393
0394
0395
0396 if (tep_is_file_bigendian(event->tep) ==
0397 tep_is_local_bigendian(event->tep)) {
0398
0399 trace_seq_printf(s, "%u q%u%s %s%s %spae %snxe %swp%s%s%s",
0400 role.level,
0401 role.quadrant,
0402 role.direct ? " direct" : "",
0403 access_str[role.access],
0404 role.invalid ? " invalid" : "",
0405 role.cr4_pae ? "" : "!",
0406 role.efer_nx ? "" : "!",
0407 role.cr0_wp ? "" : "!",
0408 role.smep_and_not_wp ? " smep" : "",
0409 role.smap_and_not_wp ? " smap" : "",
0410 role.smm ? " smm" : "");
0411 } else
0412 trace_seq_printf(s, "WORD: %08x", role.word);
0413
0414 tep_print_num_field(s, " root %u ", event,
0415 "root_count", record, 1);
0416
0417 if (tep_get_field_val(s, event, "unsync", record, &val, 1) < 0)
0418 return -1;
0419
0420 trace_seq_printf(s, "%s%c", val ? "unsync" : "sync", 0);
0421 return 0;
0422 }
0423
0424 static int kvm_mmu_get_page_handler(struct trace_seq *s,
0425 struct tep_record *record,
0426 struct tep_event *event, void *context)
0427 {
0428 unsigned long long val;
0429
0430 if (tep_get_field_val(s, event, "created", record, &val, 1) < 0)
0431 return -1;
0432
0433 trace_seq_printf(s, "%s ", val ? "new" : "existing");
0434
0435 if (tep_get_field_val(s, event, "gfn", record, &val, 1) < 0)
0436 return -1;
0437
0438 trace_seq_printf(s, "sp gfn %llx ", val);
0439 return kvm_mmu_print_role(s, record, event, context);
0440 }
0441
0442 #define PT_WRITABLE_SHIFT 1
0443 #define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT)
0444
0445 static unsigned long long
0446 process_is_writable_pte(struct trace_seq *s, unsigned long long *args)
0447 {
0448 unsigned long pte = args[0];
0449 return pte & PT_WRITABLE_MASK;
0450 }
0451
0452 int TEP_PLUGIN_LOADER(struct tep_handle *tep)
0453 {
0454 init_disassembler();
0455
0456 tep_register_event_handler(tep, -1, "kvm", "kvm_exit",
0457 kvm_exit_handler, NULL);
0458
0459 tep_register_event_handler(tep, -1, "kvm", "kvm_emulate_insn",
0460 kvm_emulate_insn_handler, NULL);
0461
0462 tep_register_event_handler(tep, -1, "kvm", "kvm_nested_vmexit",
0463 kvm_nested_vmexit_handler, NULL);
0464
0465 tep_register_event_handler(tep, -1, "kvm", "kvm_nested_vmexit_inject",
0466 kvm_nested_vmexit_inject_handler, NULL);
0467
0468 tep_register_event_handler(tep, -1, "kvmmmu", "kvm_mmu_get_page",
0469 kvm_mmu_get_page_handler, NULL);
0470
0471 tep_register_event_handler(tep, -1, "kvmmmu", "kvm_mmu_sync_page",
0472 kvm_mmu_print_role, NULL);
0473
0474 tep_register_event_handler(tep, -1,
0475 "kvmmmu", "kvm_mmu_unsync_page",
0476 kvm_mmu_print_role, NULL);
0477
0478 tep_register_event_handler(tep, -1, "kvmmmu", "kvm_mmu_zap_page",
0479 kvm_mmu_print_role, NULL);
0480
0481 tep_register_event_handler(tep, -1, "kvmmmu",
0482 "kvm_mmu_prepare_zap_page", kvm_mmu_print_role,
0483 NULL);
0484
0485 tep_register_print_function(tep,
0486 process_is_writable_pte,
0487 TEP_FUNC_ARG_INT,
0488 "is_writable_pte",
0489 TEP_FUNC_ARG_LONG,
0490 TEP_FUNC_ARG_VOID);
0491 return 0;
0492 }
0493
0494 void TEP_PLUGIN_UNLOADER(struct tep_handle *tep)
0495 {
0496 tep_unregister_event_handler(tep, -1, "kvm", "kvm_exit",
0497 kvm_exit_handler, NULL);
0498
0499 tep_unregister_event_handler(tep, -1, "kvm", "kvm_emulate_insn",
0500 kvm_emulate_insn_handler, NULL);
0501
0502 tep_unregister_event_handler(tep, -1, "kvm", "kvm_nested_vmexit",
0503 kvm_nested_vmexit_handler, NULL);
0504
0505 tep_unregister_event_handler(tep, -1, "kvm", "kvm_nested_vmexit_inject",
0506 kvm_nested_vmexit_inject_handler, NULL);
0507
0508 tep_unregister_event_handler(tep, -1, "kvmmmu", "kvm_mmu_get_page",
0509 kvm_mmu_get_page_handler, NULL);
0510
0511 tep_unregister_event_handler(tep, -1, "kvmmmu", "kvm_mmu_sync_page",
0512 kvm_mmu_print_role, NULL);
0513
0514 tep_unregister_event_handler(tep, -1,
0515 "kvmmmu", "kvm_mmu_unsync_page",
0516 kvm_mmu_print_role, NULL);
0517
0518 tep_unregister_event_handler(tep, -1, "kvmmmu", "kvm_mmu_zap_page",
0519 kvm_mmu_print_role, NULL);
0520
0521 tep_unregister_event_handler(tep, -1, "kvmmmu",
0522 "kvm_mmu_prepare_zap_page", kvm_mmu_print_role,
0523 NULL);
0524
0525 tep_unregister_print_function(tep, process_is_writable_pte,
0526 "is_writable_pte");
0527 }