diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-09-21 15:10:26 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-09-24 09:17:32 -0400 |
commit | 14907e73830a256ad726a35a93789a9bc9595490 (patch) | |
tree | df70a3c083e53d297a36ba5c9c0fc7ee29b34516 /tools/perf/builtin-kvm.c | |
parent | bcf6edcd6fdb8965290f0b635a530fa3c6c212e1 (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.c | 130 |
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 | ||
35 | struct kvm_events_ops { | 35 | struct 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 | ||
44 | static void exit_event_get_key(struct event_format *event, void *data, | 45 | static 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 | ||
51 | static bool kvm_exit_event(struct event_format *event) | 53 | static 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 | ||
56 | static bool exit_event_begin(struct event_format *event, void *data, | 58 | static 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 | ||
67 | static bool kvm_entry_event(struct event_format *event) | 69 | static 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 | ||
72 | static bool exit_event_end(struct event_format *event, void *data __maybe_unused, | 74 | static 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 | ||
78 | struct exit_reasons_table { | 81 | struct 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 | */ |
133 | static void mmio_event_get_key(struct event_format *event, void *data, | 136 | static 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 | ||
144 | static bool mmio_event_begin(struct event_format *event, void *data, | 147 | static 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 | ||
161 | static bool mmio_event_end(struct event_format *event, void *data, | 164 | static 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. */ |
192 | static void ioport_event_get_key(struct event_format *event, void *data, | 195 | static 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 | ||
199 | static bool ioport_event_begin(struct event_format *event, void *data, | 203 | static 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 | ||
210 | static bool ioport_event_end(struct event_format *event, void *data __maybe_unused, | 215 | static 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 | ||
219 | static void ioport_event_decode_key(struct event_key *key, char decode[20]) | 222 | static 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 | ||
433 | static struct vcpu_event_record | 436 | static |
434 | *per_vcpu_record(struct thread *thread, struct event_format *event, void *data) | 437 | struct 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 | ||
453 | static bool handle_kvm_event(struct thread *thread, struct event_format *event, | 458 | static 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; |