aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-kvm.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2012-09-21 15:10:26 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-09-24 09:17:32 -0400
commit14907e73830a256ad726a35a93789a9bc9595490 (patch)
treedf70a3c083e53d297a36ba5c9c0fc7ee29b34516 /tools/perf/builtin-kvm.c
parentbcf6edcd6fdb8965290f0b635a530fa3c6c212e1 (diff)
perf kvm: Use perf_evsel__intval
Using plain raw_field_value(evsel->tp_format) will look at the common fields as well, and since this tool doesn't need those, speed it up a bit by looking at just the event specific fields. Also in general use just evsel and sample, just like was done in 'perf sched'. v2: Fixed up test against evsel->name, that contains the subsys name too, by David Ahern. Cc: David Ahern <dsahern@gmail.com> Cc: Dong Hao <haodong@linux.vnet.ibm.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com> Cc: Runzhen Wang <runzhen@linux.vnet.ibm.com> Link: http://lkml.kernel.org/n/tip-v9x3q9rv4caxtox7wtjpchq5@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-kvm.c')
-rw-r--r--tools/perf/builtin-kvm.c130
1 files changed, 67 insertions, 63 deletions
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 1878947df5c1..3eb53e33c02b 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -33,46 +33,49 @@ struct event_key {
33}; 33};
34 34
35struct kvm_events_ops { 35struct kvm_events_ops {
36 bool (*is_begin_event)(struct event_format *event, void *data, 36 bool (*is_begin_event)(struct perf_evsel *evsel,
37 struct event_key *key); 37 struct perf_sample *sample,
38 bool (*is_end_event)(struct event_format *event, void *data, 38 struct event_key *key);
39 struct event_key *key); 39 bool (*is_end_event)(struct perf_evsel *evsel,
40 struct perf_sample *sample, struct event_key *key);
40 void (*decode_key)(struct event_key *key, char decode[20]); 41 void (*decode_key)(struct event_key *key, char decode[20]);
41 const char *name; 42 const char *name;
42}; 43};
43 44
44static void exit_event_get_key(struct event_format *event, void *data, 45static void exit_event_get_key(struct perf_evsel *evsel,
45 struct event_key *key) 46 struct perf_sample *sample,
47 struct event_key *key)
46{ 48{
47 key->info = 0; 49 key->info = 0;
48 key->key = raw_field_value(event, "exit_reason", data); 50 key->key = perf_evsel__intval(evsel, sample, "exit_reason");
49} 51}
50 52
51static bool kvm_exit_event(struct event_format *event) 53static bool kvm_exit_event(struct perf_evsel *evsel)
52{ 54{
53 return !strcmp(event->name, "kvm_exit"); 55 return !strcmp(evsel->name, "kvm:kvm_exit");
54} 56}
55 57
56static bool exit_event_begin(struct event_format *event, void *data, 58static bool exit_event_begin(struct perf_evsel *evsel,
57 struct event_key *key) 59 struct perf_sample *sample, struct event_key *key)
58{ 60{
59 if (kvm_exit_event(event)) { 61 if (kvm_exit_event(evsel)) {
60 exit_event_get_key(event, data, key); 62 exit_event_get_key(evsel, sample, key);
61 return true; 63 return true;
62 } 64 }
63 65
64 return false; 66 return false;
65} 67}
66 68
67static bool kvm_entry_event(struct event_format *event) 69static bool kvm_entry_event(struct perf_evsel *evsel)
68{ 70{
69 return !strcmp(event->name, "kvm_entry"); 71 return !strcmp(evsel->name, "kvm:kvm_entry");
70} 72}
71 73
72static bool exit_event_end(struct event_format *event, void *data __maybe_unused, 74static bool exit_event_end(struct perf_evsel *evsel,
73 struct event_key *key __maybe_unused) 75 struct perf_sample *sample __maybe_unused,
76 struct event_key *key __maybe_unused)
74{ 77{
75 return kvm_entry_event(event); 78 return kvm_entry_event(evsel);
76} 79}
77 80
78struct exit_reasons_table { 81struct exit_reasons_table {
@@ -130,45 +133,45 @@ static struct kvm_events_ops exit_events = {
130 * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry 133 * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
131 * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...). 134 * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
132 */ 135 */
133static void mmio_event_get_key(struct event_format *event, void *data, 136static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample,
134 struct event_key *key) 137 struct event_key *key)
135{ 138{
136 key->key = raw_field_value(event, "gpa", data); 139 key->key = perf_evsel__intval(evsel, sample, "gpa");
137 key->info = raw_field_value(event, "type", data); 140 key->info = perf_evsel__intval(evsel, sample, "type");
138} 141}
139 142
140#define KVM_TRACE_MMIO_READ_UNSATISFIED 0 143#define KVM_TRACE_MMIO_READ_UNSATISFIED 0
141#define KVM_TRACE_MMIO_READ 1 144#define KVM_TRACE_MMIO_READ 1
142#define KVM_TRACE_MMIO_WRITE 2 145#define KVM_TRACE_MMIO_WRITE 2
143 146
144static bool mmio_event_begin(struct event_format *event, void *data, 147static bool mmio_event_begin(struct perf_evsel *evsel,
145 struct event_key *key) 148 struct perf_sample *sample, struct event_key *key)
146{ 149{
147 /* MMIO read begin event in kernel. */ 150 /* MMIO read begin event in kernel. */
148 if (kvm_exit_event(event)) 151 if (kvm_exit_event(evsel))
149 return true; 152 return true;
150 153
151 /* MMIO write begin event in kernel. */ 154 /* MMIO write begin event in kernel. */
152 if (!strcmp(event->name, "kvm_mmio") && 155 if (!strcmp(evsel->name, "kvm:kvm_mmio") &&
153 raw_field_value(event, "type", data) == KVM_TRACE_MMIO_WRITE) { 156 perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) {
154 mmio_event_get_key(event, data, key); 157 mmio_event_get_key(evsel, sample, key);
155 return true; 158 return true;
156 } 159 }
157 160
158 return false; 161 return false;
159} 162}
160 163
161static bool mmio_event_end(struct event_format *event, void *data, 164static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
162 struct event_key *key) 165 struct event_key *key)
163{ 166{
164 /* MMIO write end event in kernel. */ 167 /* MMIO write end event in kernel. */
165 if (kvm_entry_event(event)) 168 if (kvm_entry_event(evsel))
166 return true; 169 return true;
167 170
168 /* MMIO read end event in kernel.*/ 171 /* MMIO read end event in kernel.*/
169 if (!strcmp(event->name, "kvm_mmio") && 172 if (!strcmp(evsel->name, "kvm:kvm_mmio") &&
170 raw_field_value(event, "type", data) == KVM_TRACE_MMIO_READ) { 173 perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_READ) {
171 mmio_event_get_key(event, data, key); 174 mmio_event_get_key(evsel, sample, key);
172 return true; 175 return true;
173 } 176 }
174 177
@@ -189,31 +192,31 @@ static struct kvm_events_ops mmio_events = {
189}; 192};
190 193
191 /* The time of emulation pio access is from kvm_pio to kvm_entry. */ 194 /* The time of emulation pio access is from kvm_pio to kvm_entry. */
192static void ioport_event_get_key(struct event_format *event, void *data, 195static void ioport_event_get_key(struct perf_evsel *evsel,
193 struct event_key *key) 196 struct perf_sample *sample,
197 struct event_key *key)
194{ 198{
195 key->key = raw_field_value(event, "port", data); 199 key->key = perf_evsel__intval(evsel, sample, "port");
196 key->info = raw_field_value(event, "rw", data); 200 key->info = perf_evsel__intval(evsel, sample, "rw");
197} 201}
198 202
199static bool ioport_event_begin(struct event_format *event, void *data, 203static bool ioport_event_begin(struct perf_evsel *evsel,
200 struct event_key *key) 204 struct perf_sample *sample,
205 struct event_key *key)
201{ 206{
202 if (!strcmp(event->name, "kvm_pio")) { 207 if (!strcmp(evsel->name, "kvm:kvm_pio")) {
203 ioport_event_get_key(event, data, key); 208 ioport_event_get_key(evsel, sample, key);
204 return true; 209 return true;
205 } 210 }
206 211
207 return false; 212 return false;
208} 213}
209 214
210static bool ioport_event_end(struct event_format *event, void *data __maybe_unused, 215static bool ioport_event_end(struct perf_evsel *evsel,
216 struct perf_sample *sample __maybe_unused,
211 struct event_key *key __maybe_unused) 217 struct event_key *key __maybe_unused)
212{ 218{
213 if (kvm_entry_event(event)) 219 return kvm_entry_event(evsel);
214 return true;
215
216 return false;
217} 220}
218 221
219static void ioport_event_decode_key(struct event_key *key, char decode[20]) 222static void ioport_event_decode_key(struct event_key *key, char decode[20])
@@ -430,41 +433,43 @@ static bool handle_end_event(struct vcpu_event_record *vcpu_record,
430 return update_kvm_event(event, vcpu_record->vcpu_id, time_diff); 433 return update_kvm_event(event, vcpu_record->vcpu_id, time_diff);
431} 434}
432 435
433static struct vcpu_event_record 436static
434*per_vcpu_record(struct thread *thread, struct event_format *event, void *data) 437struct vcpu_event_record *per_vcpu_record(struct thread *thread,
438 struct perf_evsel *evsel,
439 struct perf_sample *sample)
435{ 440{
436 /* Only kvm_entry records vcpu id. */ 441 /* Only kvm_entry records vcpu id. */
437 if (!thread->priv && kvm_entry_event(event)) { 442 if (!thread->priv && kvm_entry_event(evsel)) {
438 struct vcpu_event_record *vcpu_record; 443 struct vcpu_event_record *vcpu_record;
439 444
440 vcpu_record = zalloc(sizeof(struct vcpu_event_record)); 445 vcpu_record = zalloc(sizeof(*vcpu_record));
441 if (!vcpu_record) { 446 if (!vcpu_record) {
442 pr_err("Not enough memory\n"); 447 pr_err("%s: Not enough memory\n", __func__);
443 return NULL; 448 return NULL;
444 } 449 }
445 450
446 vcpu_record->vcpu_id = raw_field_value(event, "vcpu_id", data); 451 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, "vcpu_id");
447 thread->priv = vcpu_record; 452 thread->priv = vcpu_record;
448 } 453 }
449 454
450 return (struct vcpu_event_record *)thread->priv; 455 return thread->priv;
451} 456}
452 457
453static bool handle_kvm_event(struct thread *thread, struct event_format *event, 458static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel,
454 void *data, u64 timestamp) 459 struct perf_sample *sample)
455{ 460{
456 struct vcpu_event_record *vcpu_record; 461 struct vcpu_event_record *vcpu_record;
457 struct event_key key = {.key = INVALID_KEY}; 462 struct event_key key = {.key = INVALID_KEY};
458 463
459 vcpu_record = per_vcpu_record(thread, event, data); 464 vcpu_record = per_vcpu_record(thread, evsel, sample);
460 if (!vcpu_record) 465 if (!vcpu_record)
461 return true; 466 return true;
462 467
463 if (events_ops->is_begin_event(event, data, &key)) 468 if (events_ops->is_begin_event(evsel, sample, &key))
464 return handle_begin_event(vcpu_record, &key, timestamp); 469 return handle_begin_event(vcpu_record, &key, sample->time);
465 470
466 if (events_ops->is_end_event(event, data, &key)) 471 if (events_ops->is_end_event(evsel, sample, &key))
467 return handle_end_event(vcpu_record, &key, timestamp); 472 return handle_end_event(vcpu_record, &key, sample->time);
468 473
469 return true; 474 return true;
470} 475}
@@ -645,8 +650,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
645 return -1; 650 return -1;
646 } 651 }
647 652
648 if (!handle_kvm_event(thread, evsel->tp_format, sample->raw_data, 653 if (!handle_kvm_event(thread, evsel, sample))
649 sample->time))
650 return -1; 654 return -1;
651 655
652 return 0; 656 return 0;