aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-09-19 10:33:57 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-09-23 18:28:25 -0400
commit84d78973993710e0964aa801d5dcf1b5c4690216 (patch)
tree410a804a6937b18162f8870c817c223ba77159ef
parentaf41ffe13947069a95dad4738da0159ebd0fe84c (diff)
plugin_kvm: Disassemble instructions for kvm_emulate_insn
Override kvm_emulate_insn formatting to use a disassembler to format the emulated instruction. If a disassembler (udis86) is not available, fall back to showing the instruction bytes in hex. Signed-off-by: Avi Kivity <avi@redhat.com> LKML-Reference: <1284906837-2431-1-git-send-email-avi@redhat.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--Makefile11
-rw-r--r--plugin_kvm.c111
2 files changed, 121 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 5282f94..fe34d1c 100644
--- a/Makefile
+++ b/Makefile
@@ -74,6 +74,14 @@ ifeq ($(shell sh -c "python-config --includes > /dev/null 2>&1 && echo y"), y)
74 PYTHON_PY_INSTALL := event-viewer.install tracecmd.install tracecmdgui.install 74 PYTHON_PY_INSTALL := event-viewer.install tracecmd.install tracecmdgui.install
75endif 75endif
76 76
77# $(call test-build, snippet, ret) -> ret if snippet compiles
78# -> empty otherwise
79test-build = $(if $(shell $(CC) -o /dev/null -c -x c - > /dev/null 2>&1 \
80 <<<'$1' && echo y), $2)
81
82# have udis86 disassembler library?
83udis86-flags := $(call test-build,\#include <udis86.h>,-DHAVE_UDIS86 -ludis86)
84
77ifeq ("$(origin O)", "command line") 85ifeq ("$(origin O)", "command line")
78 BUILD_OUTPUT := $(O) 86 BUILD_OUTPUT := $(O)
79endif 87endif
@@ -188,6 +196,7 @@ CFLAGS ?= -g -Wall
188 196
189# Append required CFLAGS 197# Append required CFLAGS
190override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) 198override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
199override CFLAGS += $(udis86-flags)
191 200
192ifeq ($(VERBOSE),1) 201ifeq ($(VERBOSE),1)
193 Q = 202 Q =
@@ -228,7 +237,7 @@ do_compile_plugin_obj = \
228 237
229do_plugin_build = \ 238do_plugin_build = \
230 ($(print_plugin_build) \ 239 ($(print_plugin_build) \
231 $(CC) -shared -nostartfiles -o $@ $<) 240 $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
232 241
233do_build_static_lib = \ 242do_build_static_lib = \
234 ($(print_static_lib_build) \ 243 ($(print_static_lib_build) \
diff --git a/plugin_kvm.c b/plugin_kvm.c
index 7217e85..00cac5a 100644
--- a/plugin_kvm.c
+++ b/plugin_kvm.c
@@ -21,9 +21,68 @@
21#include <stdio.h> 21#include <stdio.h>
22#include <stdlib.h> 22#include <stdlib.h>
23#include <string.h> 23#include <string.h>
24#include <stdint.h>
24 25
25#include "parse-events.h" 26#include "parse-events.h"
26 27
28#ifdef HAVE_UDIS86
29
30#include <udis86.h>
31
32static ud_t ud;
33
34static void init_disassembler(void)
35{
36 ud_init(&ud);
37 ud_set_syntax(&ud, UD_SYN_ATT);
38}
39
40static const char *disassemble(unsigned char *insn, int len, uint64_t rip,
41 int cr0_pe, int eflags_vm,
42 int cs_d, int cs_l)
43{
44 int mode;
45
46 if (!cr0_pe)
47 mode = 16;
48 else if (eflags_vm)
49 mode = 16;
50 else if (cs_l)
51 mode = 64;
52 else if (cs_d)
53 mode = 32;
54 else
55 mode = 16;
56
57 ud_set_pc(&ud, rip);
58 ud_set_mode(&ud, mode);
59 ud_set_input_buffer(&ud, insn, len);
60 ud_disassemble(&ud);
61 return ud_insn_asm(&ud);
62}
63
64#else
65
66static void init_disassembler(void)
67{
68}
69
70static const char *disassemble(unsigned char *insn, int len, uint64_t rip,
71 int cr0_pe, int eflags_vm,
72 int cs_d, int cs_l)
73{
74 static char out[15*3+1];
75 int i;
76
77 for (i = 0; i < len; ++i)
78 sprintf(out + i * 3, "%02x ", insn[i]);
79 out[len*3-1] = '\0';
80 return out;
81}
82
83#endif
84
85
27#define VMX_EXIT_REASONS \ 86#define VMX_EXIT_REASONS \
28 _ER(EXCEPTION_NMI, 0) \ 87 _ER(EXCEPTION_NMI, 0) \
29 _ER(EXTERNAL_INTERRUPT, 1) \ 88 _ER(EXTERNAL_INTERRUPT, 1) \
@@ -99,6 +158,53 @@ static int kvm_exit_handler(struct trace_seq *s, struct record *record,
99 return 0; 158 return 0;
100} 159}
101 160
161#define KVM_EMUL_INSN_F_CR0_PE (1 << 0)
162#define KVM_EMUL_INSN_F_EFL_VM (1 << 1)
163#define KVM_EMUL_INSN_F_CS_D (1 << 2)
164#define KVM_EMUL_INSN_F_CS_L (1 << 3)
165
166static int kvm_emulate_insn_handler(struct trace_seq *s, struct record *record,
167 struct event_format *event, void *context)
168{
169 unsigned long long rip, csbase, len, flags, failed;
170 int llen;
171 uint8_t *insn;
172 const char *disasm;
173
174 if (pevent_get_field_val(s, event, "rip", record, &rip, 1) < 0)
175 return -1;
176
177 if (pevent_get_field_val(s, event, "csbase", record, &csbase, 1) < 0)
178 return -1;
179
180 if (pevent_get_field_val(s, event, "len", record, &len, 1) < 0)
181 return -1;
182
183 if (pevent_get_field_val(s, event, "flags", record, &flags, 1) < 0)
184 return -1;
185
186 if (pevent_get_field_val(s, event, "failed", record, &failed, 1) < 0)
187 return -1;
188
189 insn = pevent_get_field_raw(s, event, "insn", record, &llen, 1);
190 if (!insn)
191 return -1;
192
193 disasm = disassemble(insn, len, rip,
194 flags & KVM_EMUL_INSN_F_CR0_PE,
195 flags & KVM_EMUL_INSN_F_EFL_VM,
196 flags & KVM_EMUL_INSN_F_CS_D,
197 flags & KVM_EMUL_INSN_F_CS_L);
198
199 trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm,
200 failed ? " FAIL" : "");
201
202 pevent_print_num_field(s, " rip %0xlx", event, "guest_rip", record, 1);
203
204 return 0;
205}
206
207
102static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct record *record, 208static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct record *record,
103 struct event_format *event, void *context) 209 struct event_format *event, void *context)
104{ 210{
@@ -199,9 +305,14 @@ static int kvm_mmu_get_page_handler(struct trace_seq *s, struct record *record,
199 305
200int PEVENT_PLUGIN_LOADER(struct pevent *pevent) 306int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
201{ 307{
308 init_disassembler();
309
202 pevent_register_event_handler(pevent, -1, "kvm", "kvm_exit", 310 pevent_register_event_handler(pevent, -1, "kvm", "kvm_exit",
203 kvm_exit_handler, NULL); 311 kvm_exit_handler, NULL);
204 312
313 pevent_register_event_handler(pevent, -1, "kvm", "kvm_emulate_insn",
314 kvm_emulate_insn_handler, NULL);
315
205 pevent_register_event_handler(pevent, -1, "kvm", "kvm_nested_vmexit", 316 pevent_register_event_handler(pevent, -1, "kvm", "kvm_nested_vmexit",
206 kvm_nested_vmexit_handler, NULL); 317 kvm_nested_vmexit_handler, NULL);
207 318