diff options
author | Avi Kivity <avi@redhat.com> | 2010-11-23 05:58:26 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-11-23 12:03:10 -0500 |
commit | 8cadc3e20fe7da3d49a8e2e57d6564bf4fff3dc8 (patch) | |
tree | ad3f344125150f586e5a122612adf87036ffc5d5 | |
parent | 112b5bb4a69dddf88a7d4607566e67ff80910083 (diff) |
kvm: Parse svm exit reason
svm exit reasons use different code than vmx; use the new "isa" trace field
to select the instruction set and display the strings accordingly.
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | plugin_kvm.c | 114 |
1 files changed, 107 insertions, 7 deletions
diff --git a/plugin_kvm.c b/plugin_kvm.c index 724143d..c8e8b8c 100644 --- a/plugin_kvm.c +++ b/plugin_kvm.c | |||
@@ -120,6 +120,80 @@ static const char *disassemble(unsigned char *insn, int len, uint64_t rip, | |||
120 | _ER(EPT_MISCONFIG, 49) \ | 120 | _ER(EPT_MISCONFIG, 49) \ |
121 | _ER(WBINVD, 54) | 121 | _ER(WBINVD, 54) |
122 | 122 | ||
123 | #define SVM_EXIT_REASONS \ | ||
124 | _ER(EXIT_READ_CR0, 0x000) \ | ||
125 | _ER(EXIT_READ_CR3, 0x003) \ | ||
126 | _ER(EXIT_READ_CR4, 0x004) \ | ||
127 | _ER(EXIT_READ_CR8, 0x008) \ | ||
128 | _ER(EXIT_WRITE_CR0, 0x010) \ | ||
129 | _ER(EXIT_WRITE_CR3, 0x013) \ | ||
130 | _ER(EXIT_WRITE_CR4, 0x014) \ | ||
131 | _ER(EXIT_WRITE_CR8, 0x018) \ | ||
132 | _ER(EXIT_READ_DR0, 0x020) \ | ||
133 | _ER(EXIT_READ_DR1, 0x021) \ | ||
134 | _ER(EXIT_READ_DR2, 0x022) \ | ||
135 | _ER(EXIT_READ_DR3, 0x023) \ | ||
136 | _ER(EXIT_READ_DR4, 0x024) \ | ||
137 | _ER(EXIT_READ_DR5, 0x025) \ | ||
138 | _ER(EXIT_READ_DR6, 0x026) \ | ||
139 | _ER(EXIT_READ_DR7, 0x027) \ | ||
140 | _ER(EXIT_WRITE_DR0, 0x030) \ | ||
141 | _ER(EXIT_WRITE_DR1, 0x031) \ | ||
142 | _ER(EXIT_WRITE_DR2, 0x032) \ | ||
143 | _ER(EXIT_WRITE_DR3, 0x033) \ | ||
144 | _ER(EXIT_WRITE_DR4, 0x034) \ | ||
145 | _ER(EXIT_WRITE_DR5, 0x035) \ | ||
146 | _ER(EXIT_WRITE_DR6, 0x036) \ | ||
147 | _ER(EXIT_WRITE_DR7, 0x037) \ | ||
148 | _ER(EXIT_EXCP_BASE, 0x040) \ | ||
149 | _ER(EXIT_INTR, 0x060) \ | ||
150 | _ER(EXIT_NMI, 0x061) \ | ||
151 | _ER(EXIT_SMI, 0x062) \ | ||
152 | _ER(EXIT_INIT, 0x063) \ | ||
153 | _ER(EXIT_VINTR, 0x064) \ | ||
154 | _ER(EXIT_CR0_SEL_WRITE, 0x065) \ | ||
155 | _ER(EXIT_IDTR_READ, 0x066) \ | ||
156 | _ER(EXIT_GDTR_READ, 0x067) \ | ||
157 | _ER(EXIT_LDTR_READ, 0x068) \ | ||
158 | _ER(EXIT_TR_READ, 0x069) \ | ||
159 | _ER(EXIT_IDTR_WRITE, 0x06a) \ | ||
160 | _ER(EXIT_GDTR_WRITE, 0x06b) \ | ||
161 | _ER(EXIT_LDTR_WRITE, 0x06c) \ | ||
162 | _ER(EXIT_TR_WRITE, 0x06d) \ | ||
163 | _ER(EXIT_RDTSC, 0x06e) \ | ||
164 | _ER(EXIT_RDPMC, 0x06f) \ | ||
165 | _ER(EXIT_PUSHF, 0x070) \ | ||
166 | _ER(EXIT_POPF, 0x071) \ | ||
167 | _ER(EXIT_CPUID, 0x072) \ | ||
168 | _ER(EXIT_RSM, 0x073) \ | ||
169 | _ER(EXIT_IRET, 0x074) \ | ||
170 | _ER(EXIT_SWINT, 0x075) \ | ||
171 | _ER(EXIT_INVD, 0x076) \ | ||
172 | _ER(EXIT_PAUSE, 0x077) \ | ||
173 | _ER(EXIT_HLT, 0x078) \ | ||
174 | _ER(EXIT_INVLPG, 0x079) \ | ||
175 | _ER(EXIT_INVLPGA, 0x07a) \ | ||
176 | _ER(EXIT_IOIO, 0x07b) \ | ||
177 | _ER(EXIT_MSR, 0x07c) \ | ||
178 | _ER(EXIT_TASK_SWITCH, 0x07d) \ | ||
179 | _ER(EXIT_FERR_FREEZE, 0x07e) \ | ||
180 | _ER(EXIT_SHUTDOWN, 0x07f) \ | ||
181 | _ER(EXIT_VMRUN, 0x080) \ | ||
182 | _ER(EXIT_VMMCALL, 0x081) \ | ||
183 | _ER(EXIT_VMLOAD, 0x082) \ | ||
184 | _ER(EXIT_VMSAVE, 0x083) \ | ||
185 | _ER(EXIT_STGI, 0x084) \ | ||
186 | _ER(EXIT_CLGI, 0x085) \ | ||
187 | _ER(EXIT_SKINIT, 0x086) \ | ||
188 | _ER(EXIT_RDTSCP, 0x087) \ | ||
189 | _ER(EXIT_ICEBP, 0x088) \ | ||
190 | _ER(EXIT_WBINVD, 0x089) \ | ||
191 | _ER(EXIT_MONITOR, 0x08a) \ | ||
192 | _ER(EXIT_MWAIT, 0x08b) \ | ||
193 | _ER(EXIT_MWAIT_COND, 0x08c) \ | ||
194 | _ER(EXIT_NPF, 0x400) \ | ||
195 | _ER(EXIT_ERR, -1) | ||
196 | |||
123 | #define _ER(reason, val) { #reason, val }, | 197 | #define _ER(reason, val) { #reason, val }, |
124 | struct str_values { | 198 | struct str_values { |
125 | const char *str; | 199 | const char *str; |
@@ -131,27 +205,53 @@ static struct str_values vmx_exit_reasons[] = { | |||
131 | { NULL, -1} | 205 | { NULL, -1} |
132 | }; | 206 | }; |
133 | 207 | ||
134 | static const char *find_vmx_reason(int val) | 208 | static struct str_values svm_exit_reasons[] = { |
209 | SVM_EXIT_REASONS | ||
210 | { NULL, -1} | ||
211 | }; | ||
212 | |||
213 | static struct isa_exit_reasons { | ||
214 | unsigned isa; | ||
215 | struct str_values *strings; | ||
216 | } isa_exit_reasons[] = { | ||
217 | { .isa = 1, .strings = vmx_exit_reasons }, | ||
218 | { .isa = 2, .strings = svm_exit_reasons }, | ||
219 | { } | ||
220 | }; | ||
221 | |||
222 | static const char *find_exit_reason(unsigned isa, int val) | ||
135 | { | 223 | { |
224 | struct str_values *strings = NULL; | ||
136 | int i; | 225 | int i; |
137 | 226 | ||
138 | for (i = 0; vmx_exit_reasons[i].val >= 0; i++) | 227 | for (i = 0; isa_exit_reasons[i].strings; ++i) |
139 | if (vmx_exit_reasons[i].val == val) | 228 | if (isa_exit_reasons[i].isa == isa) { |
229 | strings = isa_exit_reasons[i].strings; | ||
140 | break; | 230 | break; |
141 | if (vmx_exit_reasons[i].str) | 231 | } |
142 | return vmx_exit_reasons[i].str; | 232 | if (!strings) |
233 | return "UNKNOWN-ISA"; | ||
234 | for (i = 0; strings[i].val >= 0; i++) | ||
235 | if (strings[i].val == val) | ||
236 | break; | ||
237 | if (strings[i].str) | ||
238 | return strings[i].str; | ||
143 | return "UNKOWN"; | 239 | return "UNKOWN"; |
144 | } | 240 | } |
145 | 241 | ||
146 | static int kvm_exit_handler(struct trace_seq *s, struct record *record, | 242 | static int kvm_exit_handler(struct trace_seq *s, struct record *record, |
147 | struct event_format *event, void *context) | 243 | struct event_format *event, void *context) |
148 | { | 244 | { |
245 | unsigned long long isa; | ||
149 | unsigned long long val; | 246 | unsigned long long val; |
150 | 247 | ||
151 | if (pevent_get_field_val(s, event, "exit_reason", record, &val, 1) < 0) | 248 | if (pevent_get_field_val(s, event, "exit_reason", record, &val, 1) < 0) |
152 | return -1; | 249 | return -1; |
153 | 250 | ||
154 | trace_seq_printf(s, "reason %s", find_vmx_reason(val)); | 251 | if (pevent_get_field_val(s, event, "isa", record, &isa, 1) < 0) |
252 | isa = 1; | ||
253 | |||
254 | trace_seq_printf(s, "reason %s", find_exit_reason(isa, val)); | ||
155 | 255 | ||
156 | pevent_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1); | 256 | pevent_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1); |
157 | 257 | ||
@@ -213,7 +313,7 @@ static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct record * | |||
213 | if (pevent_get_field_val(s, event, "exit_code", record, &val, 1) < 0) | 313 | if (pevent_get_field_val(s, event, "exit_code", record, &val, 1) < 0) |
214 | return -1; | 314 | return -1; |
215 | 315 | ||
216 | trace_seq_printf(s, "reason %s", find_vmx_reason(val)); | 316 | trace_seq_printf(s, "reason %s", find_exit_reason(2, val)); |
217 | 317 | ||
218 | pevent_print_num_field(s, " ext_inf1: %0x016llx", event, "exit_info1", record, 1); | 318 | pevent_print_num_field(s, " ext_inf1: %0x016llx", event, "exit_info1", record, 1); |
219 | pevent_print_num_field(s, " ext_inf2: %0x016llx", event, "exit_info2", record, 1); | 319 | pevent_print_num_field(s, " ext_inf2: %0x016llx", event, "exit_info2", record, 1); |