Blame view

tools/perf/builtin-kvm.c 38.1 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
2
3
  #include "builtin.h"
  #include "perf.h"
4a3cec849   Arnaldo Carvalho de Melo   perf dsos: Move t...
4
  #include "util/build-id.h"
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
5
  #include "util/evsel.h"
1afe1d148   David Ahern   perf kvm: Add liv...
6
  #include "util/evlist.h"
e0fcfb086   Arnaldo Carvalho de Melo   perf evlist: Adop...
7
  #include "util/mmap.h"
b0742e90f   Arnaldo Carvalho de Melo   perf tools: Don't...
8
  #include "util/term.h"
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
9
10
11
12
  #include "util/symbol.h"
  #include "util/thread.h"
  #include "util/header.h"
  #include "util/session.h"
2e73f00fe   David Ahern   perf kvm stat rep...
13
  #include "util/intlist.h"
fa0d98462   Arnaldo Carvalho de Melo   perf tools: Remov...
14
  #include <subcmd/pager.h>
4b6ab94ea   Josh Poimboeuf   perf subcmd: Crea...
15
  #include <subcmd/parse-options.h>
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
16
  #include "util/trace-event.h"
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
17
  #include "util/debug.h"
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
18
19
  #include "util/tool.h"
  #include "util/stat.h"
ea49e01cf   Arnaldo Carvalho de Melo   perf tools: Move ...
20
  #include "util/synthetic-events.h"
1afe1d148   David Ahern   perf kvm: Add liv...
21
  #include "util/top.h"
f5fc14124   Jiri Olsa   perf tools: Add d...
22
  #include "util/data.h"
d704ebdae   Arnaldo Carvalho de Melo   perf tools: tool-...
23
  #include "util/ordered-events.h"
8067b3da9   Anju T Sudhakar   perf kvm: Move kv...
24
  #include "util/kvm-stat.h"
fa0d98462   Arnaldo Carvalho de Melo   perf tools: Remov...
25
  #include "ui/ui.h"
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
26
27
  
  #include <sys/prctl.h>
87419c9af   David Ahern   perf kvm: Disable...
28
  #ifdef HAVE_TIMERFD_SUPPORT
1afe1d148   David Ahern   perf kvm: Add liv...
29
  #include <sys/timerfd.h>
87419c9af   David Ahern   perf kvm: Disable...
30
  #endif
c5e4027e0   Arnaldo Carvalho de Melo   perf tools: Move ...
31
  #include <sys/time.h>
bafae98e7   Arnaldo Carvalho de Melo   perf evlist: Remo...
32
33
34
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
35

6ef81c55a   Mamatha Inamdar   perf session: Ret...
36
  #include <linux/err.h>
877a7a110   Arnaldo Carvalho de Melo   perf tools: Add i...
37
  #include <linux/kernel.h>
fa0d98462   Arnaldo Carvalho de Melo   perf tools: Remov...
38
  #include <linux/string.h>
bd48c63eb   Arnaldo Carvalho de Melo   tools: Introduce ...
39
  #include <linux/time64.h>
7f7c536f2   Arnaldo Carvalho de Melo   tools lib: Adopt ...
40
  #include <linux/zalloc.h>
a43783aee   Arnaldo Carvalho de Melo   perf tools: Inclu...
41
  #include <errno.h>
fd20e8111   Arnaldo Carvalho de Melo   perf tools: Inclu...
42
  #include <inttypes.h>
4208735d8   Arnaldo Carvalho de Melo   perf tools: Remov...
43
  #include <poll.h>
1afe1d148   David Ahern   perf kvm: Add liv...
44
  #include <termios.h>
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
45
  #include <semaphore.h>
9607ad3a6   Arnaldo Carvalho de Melo   perf tools: Add s...
46
  #include <signal.h>
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
47
  #include <math.h>
7728fa0cf   Jiri Olsa   libperf: Adopt pe...
48
  #include <perf/mmap.h>
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
49

bb8c16db4   Arnaldo Carvalho de Melo   perf kvm: Make fu...
50
51
52
53
54
55
56
57
58
59
60
61
62
  static const char *get_filename_for_perf_kvm(void)
  {
  	const char *filename;
  
  	if (perf_host && !perf_guest)
  		filename = strdup("perf.data.host");
  	else if (!perf_host && perf_guest)
  		filename = strdup("perf.data.guest");
  	else
  		filename = strdup("perf.data.kvm");
  
  	return filename;
  }
da50ad697   Alexander Yarygin   perf kvm: Introdu...
63
  #ifdef HAVE_KVM_STAT_SUPPORT
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
64

32dcd021d   Jiri Olsa   perf evsel: Renam...
65
  void exit_event_get_key(struct evsel *evsel,
9daa81239   Alexander Yarygin   perf kvm: Move ar...
66
67
  			struct perf_sample *sample,
  			struct event_key *key)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
68
69
  {
  	key->info = 0;
efc0cdc9e   Arnaldo Carvalho de Melo   perf evsel: Renam...
70
  	key->key  = evsel__intval(evsel, sample, kvm_exit_reason);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
71
  }
32dcd021d   Jiri Olsa   perf evsel: Renam...
72
  bool kvm_exit_event(struct evsel *evsel)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
73
  {
162607ea2   Hemant Kumar   perf kvm/{x86,s39...
74
  	return !strcmp(evsel->name, kvm_exit_trace);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
75
  }
32dcd021d   Jiri Olsa   perf evsel: Renam...
76
  bool exit_event_begin(struct evsel *evsel,
9daa81239   Alexander Yarygin   perf kvm: Move ar...
77
  		      struct perf_sample *sample, struct event_key *key)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
78
  {
14907e738   Arnaldo Carvalho de Melo   perf kvm: Use per...
79
80
  	if (kvm_exit_event(evsel)) {
  		exit_event_get_key(evsel, sample, key);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
81
82
83
84
85
  		return true;
  	}
  
  	return false;
  }
32dcd021d   Jiri Olsa   perf evsel: Renam...
86
  bool kvm_entry_event(struct evsel *evsel)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
87
  {
162607ea2   Hemant Kumar   perf kvm/{x86,s39...
88
  	return !strcmp(evsel->name, kvm_entry_trace);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
89
  }
32dcd021d   Jiri Olsa   perf evsel: Renam...
90
  bool exit_event_end(struct evsel *evsel,
9daa81239   Alexander Yarygin   perf kvm: Move ar...
91
92
  		    struct perf_sample *sample __maybe_unused,
  		    struct event_key *key __maybe_unused)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
93
  {
14907e738   Arnaldo Carvalho de Melo   perf kvm: Use per...
94
  	return kvm_entry_event(evsel);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
95
  }
df74c13b6   Alexander Yarygin   perf kvm: Simplif...
96
97
98
  static const char *get_exit_reason(struct perf_kvm_stat *kvm,
  				   struct exit_reasons_table *tbl,
  				   u64 exit_code)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
99
  {
df74c13b6   Alexander Yarygin   perf kvm: Simplif...
100
  	while (tbl->reason != NULL) {
de332ac40   David Ahern   perf kvm: Move gl...
101
102
103
  		if (tbl->exit_code == exit_code)
  			return tbl->reason;
  		tbl++;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
104
105
106
107
  	}
  
  	pr_err("unknown kvm exit code:%lld on %s
  ",
de332ac40   David Ahern   perf kvm: Move gl...
108
  		(unsigned long long)exit_code, kvm->exit_reasons_isa);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
109
110
  	return "UNKNOWN";
  }
9daa81239   Alexander Yarygin   perf kvm: Move ar...
111
112
113
  void exit_event_decode_key(struct perf_kvm_stat *kvm,
  			   struct event_key *key,
  			   char *decode)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
114
  {
3be8e2a0a   Alexander Yarygin   perf kvm: Add sta...
115
  	const char *exit_reason = get_exit_reason(kvm, key->exit_reasons,
df74c13b6   Alexander Yarygin   perf kvm: Simplif...
116
  						  key->key);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
117

162607ea2   Hemant Kumar   perf kvm/{x86,s39...
118
  	scnprintf(decode, decode_str_len, "%s", exit_reason);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
119
  }
9daa81239   Alexander Yarygin   perf kvm: Move ar...
120
  static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
121
  {
9daa81239   Alexander Yarygin   perf kvm: Move ar...
122
  	struct kvm_reg_events_ops *events_ops = kvm_reg_events_ops;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
123

9daa81239   Alexander Yarygin   perf kvm: Move ar...
124
125
126
127
128
  	for (events_ops = kvm_reg_events_ops; events_ops->name; events_ops++) {
  		if (!strcmp(events_ops->name, kvm->report_event)) {
  			kvm->events_ops = events_ops->ops;
  			return true;
  		}
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
129
130
131
132
  	}
  
  	return false;
  }
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
133
134
135
136
137
  struct vcpu_event_record {
  	int vcpu_id;
  	u64 start_time;
  	struct kvm_event *last_event;
  };
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
138

3786063a3   Xiao Guangrong   perf kvm: Rename ...
139
  static void init_kvm_event_record(struct perf_kvm_stat *kvm)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
140
  {
b880deeaf   David Ahern   perf kvm: Remove ...
141
  	unsigned int i;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
142

b880deeaf   David Ahern   perf kvm: Remove ...
143
  	for (i = 0; i < EVENTS_CACHE_SIZE; i++)
de332ac40   David Ahern   perf kvm: Move gl...
144
  		INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
145
  }
87419c9af   David Ahern   perf kvm: Disable...
146
  #ifdef HAVE_TIMERFD_SUPPORT
1afe1d148   David Ahern   perf kvm: Add liv...
147
148
149
150
151
  static void clear_events_cache_stats(struct list_head *kvm_events_cache)
  {
  	struct list_head *head;
  	struct kvm_event *event;
  	unsigned int i;
62d04dbf3   David Ahern   perf kvm: Add min...
152
  	int j;
1afe1d148   David Ahern   perf kvm: Add liv...
153
154
155
156
157
  
  	for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
  		head = &kvm_events_cache[i];
  		list_for_each_entry(event, head, hash_entry) {
  			/* reset stats for event */
62d04dbf3   David Ahern   perf kvm: Add min...
158
159
160
161
162
163
164
  			event->total.time = 0;
  			init_stats(&event->total.stats);
  
  			for (j = 0; j < event->max_vcpu; ++j) {
  				event->vcpu[j].time = 0;
  				init_stats(&event->vcpu[j].stats);
  			}
1afe1d148   David Ahern   perf kvm: Add liv...
165
166
167
  		}
  	}
  }
87419c9af   David Ahern   perf kvm: Disable...
168
  #endif
1afe1d148   David Ahern   perf kvm: Add liv...
169

bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
170
171
172
173
174
175
176
177
  static int kvm_events_hash_fn(u64 key)
  {
  	return key & (EVENTS_CACHE_SIZE - 1);
  }
  
  static bool kvm_event_expand(struct kvm_event *event, int vcpu_id)
  {
  	int old_max_vcpu = event->max_vcpu;
6ca5f3081   David Ahern   perf kvm: Handle ...
178
  	void *prev;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
179
180
181
182
183
184
  
  	if (vcpu_id < event->max_vcpu)
  		return true;
  
  	while (event->max_vcpu <= vcpu_id)
  		event->max_vcpu += DEFAULT_VCPU_NUM;
6ca5f3081   David Ahern   perf kvm: Handle ...
185
  	prev = event->vcpu;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
186
187
188
  	event->vcpu = realloc(event->vcpu,
  			      event->max_vcpu * sizeof(*event->vcpu));
  	if (!event->vcpu) {
6ca5f3081   David Ahern   perf kvm: Handle ...
189
  		free(prev);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  		pr_err("Not enough memory
  ");
  		return false;
  	}
  
  	memset(event->vcpu + old_max_vcpu, 0,
  	       (event->max_vcpu - old_max_vcpu) * sizeof(*event->vcpu));
  	return true;
  }
  
  static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
  {
  	struct kvm_event *event;
  
  	event = zalloc(sizeof(*event));
  	if (!event) {
  		pr_err("Not enough memory
  ");
  		return NULL;
  	}
  
  	event->key = *key;
acb61fc8e   Alexander Yarygin   perf kvm: Fix 'Mi...
212
  	init_stats(&event->total.stats);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
213
214
  	return event;
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
215
  static struct kvm_event *find_create_kvm_event(struct perf_kvm_stat *kvm,
de332ac40   David Ahern   perf kvm: Move gl...
216
  					       struct event_key *key)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
217
218
219
220
221
  {
  	struct kvm_event *event;
  	struct list_head *head;
  
  	BUG_ON(key->key == INVALID_KEY);
de332ac40   David Ahern   perf kvm: Move gl...
222
  	head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
355afe816   David Ahern   perf kvm: Add bra...
223
  	list_for_each_entry(event, head, hash_entry) {
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
224
225
  		if (event->key.key == key->key && event->key.info == key->info)
  			return event;
355afe816   David Ahern   perf kvm: Add bra...
226
  	}
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
227
228
229
230
231
232
233
234
  
  	event = kvm_alloc_init_event(key);
  	if (!event)
  		return NULL;
  
  	list_add(&event->hash_entry, head);
  	return event;
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
235
  static bool handle_begin_event(struct perf_kvm_stat *kvm,
de332ac40   David Ahern   perf kvm: Move gl...
236
  			       struct vcpu_event_record *vcpu_record,
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
237
238
239
240
241
  			       struct event_key *key, u64 timestamp)
  {
  	struct kvm_event *event = NULL;
  
  	if (key->key != INVALID_KEY)
de332ac40   David Ahern   perf kvm: Move gl...
242
  		event = find_create_kvm_event(kvm, key);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
  
  	vcpu_record->last_event = event;
  	vcpu_record->start_time = timestamp;
  	return true;
  }
  
  static void
  kvm_update_event_stats(struct kvm_event_stats *kvm_stats, u64 time_diff)
  {
  	kvm_stats->time += time_diff;
  	update_stats(&kvm_stats->stats, time_diff);
  }
  
  static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event)
  {
  	struct kvm_event_stats *kvm_stats = &event->total;
  
  	if (vcpu_id != -1)
  		kvm_stats = &event->vcpu[vcpu_id];
  
  	return rel_stddev_stats(stddev_stats(&kvm_stats->stats),
  				avg_stats(&kvm_stats->stats));
  }
  
  static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
  			     u64 time_diff)
  {
2aa8eab02   David Ahern   perf kvm: Only pr...
270
271
272
273
  	if (vcpu_id == -1) {
  		kvm_update_event_stats(&event->total, time_diff);
  		return true;
  	}
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
274
275
276
277
278
279
280
  
  	if (!kvm_event_expand(event, vcpu_id))
  		return false;
  
  	kvm_update_event_stats(&event->vcpu[vcpu_id], time_diff);
  	return true;
  }
3be8e2a0a   Alexander Yarygin   perf kvm: Add sta...
281
  static bool is_child_event(struct perf_kvm_stat *kvm,
32dcd021d   Jiri Olsa   perf evsel: Renam...
282
  			   struct evsel *evsel,
3be8e2a0a   Alexander Yarygin   perf kvm: Add sta...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  			   struct perf_sample *sample,
  			   struct event_key *key)
  {
  	struct child_event_ops *child_ops;
  
  	child_ops = kvm->events_ops->child_ops;
  
  	if (!child_ops)
  		return false;
  
  	for (; child_ops->name; child_ops++) {
  		if (!strcmp(evsel->name, child_ops->name)) {
  			child_ops->get_key(evsel, sample, key);
  			return true;
  		}
  	}
  
  	return false;
  }
  
  static bool handle_child_event(struct perf_kvm_stat *kvm,
  			       struct vcpu_event_record *vcpu_record,
  			       struct event_key *key,
  			       struct perf_sample *sample __maybe_unused)
  {
  	struct kvm_event *event = NULL;
  
  	if (key->key != INVALID_KEY)
  		event = find_create_kvm_event(kvm, key);
  
  	vcpu_record->last_event = event;
  
  	return true;
  }
54c801ff7   Alexander Yarygin   perf kvm: Add ski...
317
318
319
320
321
322
323
324
325
326
  static bool skip_event(const char *event)
  {
  	const char * const *skip_events;
  
  	for (skip_events = kvm_skip_events; *skip_events; skip_events++)
  		if (!strcmp(event, *skip_events))
  			return true;
  
  	return false;
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
327
  static bool handle_end_event(struct perf_kvm_stat *kvm,
de332ac40   David Ahern   perf kvm: Move gl...
328
329
  			     struct vcpu_event_record *vcpu_record,
  			     struct event_key *key,
70f7b4a7f   David Ahern   perf kvm: Option ...
330
  			     struct perf_sample *sample)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
331
332
333
  {
  	struct kvm_event *event;
  	u64 time_begin, time_diff;
2aa8eab02   David Ahern   perf kvm: Only pr...
334
335
336
337
338
339
  	int vcpu;
  
  	if (kvm->trace_vcpu == -1)
  		vcpu = -1;
  	else
  		vcpu = vcpu_record->vcpu_id;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  
  	event = vcpu_record->last_event;
  	time_begin = vcpu_record->start_time;
  
  	/* The begin event is not caught. */
  	if (!time_begin)
  		return true;
  
  	/*
  	 * In some case, the 'begin event' only records the start timestamp,
  	 * the actual event is recognized in the 'end event' (e.g. mmio-event).
  	 */
  
  	/* Both begin and end events did not get the key. */
  	if (!event && key->key == INVALID_KEY)
  		return true;
  
  	if (!event)
de332ac40   David Ahern   perf kvm: Move gl...
358
  		event = find_create_kvm_event(kvm, key);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
359
360
361
362
363
364
  
  	if (!event)
  		return false;
  
  	vcpu_record->last_event = NULL;
  	vcpu_record->start_time = 0;
1afe1d148   David Ahern   perf kvm: Add liv...
365
  	/* seems to happen once in a while during live mode */
70f7b4a7f   David Ahern   perf kvm: Option ...
366
  	if (sample->time < time_begin) {
1afe1d148   David Ahern   perf kvm: Add liv...
367
368
369
370
  		pr_debug("End time before begin time; skipping event.
  ");
  		return true;
  	}
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
371

70f7b4a7f   David Ahern   perf kvm: Option ...
372
373
374
  	time_diff = sample->time - time_begin;
  
  	if (kvm->duration && time_diff > kvm->duration) {
162607ea2   Hemant Kumar   perf kvm/{x86,s39...
375
  		char decode[decode_str_len];
70f7b4a7f   David Ahern   perf kvm: Option ...
376
377
  
  		kvm->events_ops->decode_key(kvm, &event->key, decode);
54c801ff7   Alexander Yarygin   perf kvm: Add ski...
378
  		if (!skip_event(decode)) {
70f7b4a7f   David Ahern   perf kvm: Option ...
379
380
381
  			pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec
  ",
  				 sample->time, sample->pid, vcpu_record->vcpu_id,
c05a6e141   Arnaldo Carvalho de Melo   perf kvm: Use NSE...
382
  				 decode, time_diff / NSEC_PER_USEC);
70f7b4a7f   David Ahern   perf kvm: Option ...
383
384
  		}
  	}
2aa8eab02   David Ahern   perf kvm: Only pr...
385
  	return update_kvm_event(event, vcpu, time_diff);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
386
  }
14907e738   Arnaldo Carvalho de Melo   perf kvm: Use per...
387
388
  static
  struct vcpu_event_record *per_vcpu_record(struct thread *thread,
32dcd021d   Jiri Olsa   perf evsel: Renam...
389
  					  struct evsel *evsel,
14907e738   Arnaldo Carvalho de Melo   perf kvm: Use per...
390
  					  struct perf_sample *sample)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
391
392
  {
  	/* Only kvm_entry records vcpu id. */
69e865c35   Namhyung Kim   perf kvm: Use thr...
393
  	if (!thread__priv(thread) && kvm_entry_event(evsel)) {
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
394
  		struct vcpu_event_record *vcpu_record;
14907e738   Arnaldo Carvalho de Melo   perf kvm: Use per...
395
  		vcpu_record = zalloc(sizeof(*vcpu_record));
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
396
  		if (!vcpu_record) {
14907e738   Arnaldo Carvalho de Melo   perf kvm: Use per...
397
398
  			pr_err("%s: Not enough memory
  ", __func__);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
399
400
  			return NULL;
  		}
efc0cdc9e   Arnaldo Carvalho de Melo   perf evsel: Renam...
401
  		vcpu_record->vcpu_id = evsel__intval(evsel, sample, vcpu_id_str);
69e865c35   Namhyung Kim   perf kvm: Use thr...
402
  		thread__set_priv(thread, vcpu_record);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
403
  	}
69e865c35   Namhyung Kim   perf kvm: Use thr...
404
  	return thread__priv(thread);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
405
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
406
  static bool handle_kvm_event(struct perf_kvm_stat *kvm,
de332ac40   David Ahern   perf kvm: Move gl...
407
  			     struct thread *thread,
32dcd021d   Jiri Olsa   perf evsel: Renam...
408
  			     struct evsel *evsel,
14907e738   Arnaldo Carvalho de Melo   perf kvm: Use per...
409
  			     struct perf_sample *sample)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
410
411
  {
  	struct vcpu_event_record *vcpu_record;
3be8e2a0a   Alexander Yarygin   perf kvm: Add sta...
412
413
  	struct event_key key = { .key = INVALID_KEY,
  				 .exit_reasons = kvm->exit_reasons };
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
414

14907e738   Arnaldo Carvalho de Melo   perf kvm: Use per...
415
  	vcpu_record = per_vcpu_record(thread, evsel, sample);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
416
417
  	if (!vcpu_record)
  		return true;
2aa8eab02   David Ahern   perf kvm: Only pr...
418
419
420
421
  	/* only process events for vcpus user cares about */
  	if ((kvm->trace_vcpu != -1) &&
  	    (kvm->trace_vcpu != vcpu_record->vcpu_id))
  		return true;
de332ac40   David Ahern   perf kvm: Move gl...
422
423
  	if (kvm->events_ops->is_begin_event(evsel, sample, &key))
  		return handle_begin_event(kvm, vcpu_record, &key, sample->time);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
424

3be8e2a0a   Alexander Yarygin   perf kvm: Add sta...
425
426
  	if (is_child_event(kvm, evsel, sample, &key))
  		return handle_child_event(kvm, vcpu_record, &key, sample);
de332ac40   David Ahern   perf kvm: Move gl...
427
  	if (kvm->events_ops->is_end_event(evsel, sample, &key))
70f7b4a7f   David Ahern   perf kvm: Option ...
428
  		return handle_end_event(kvm, vcpu_record, &key, sample);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
429
430
431
  
  	return true;
  }
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  #define GET_EVENT_KEY(func, field)					\
  static u64 get_event_ ##func(struct kvm_event *event, int vcpu)		\
  {									\
  	if (vcpu == -1)							\
  		return event->total.field;				\
  									\
  	if (vcpu >= event->max_vcpu)					\
  		return 0;						\
  									\
  	return event->vcpu[vcpu].field;					\
  }
  
  #define COMPARE_EVENT_KEY(func, field)					\
  GET_EVENT_KEY(func, field)						\
  static int compare_kvm_event_ ## func(struct kvm_event *one,		\
  					struct kvm_event *two, int vcpu)\
  {									\
  	return get_event_ ##func(one, vcpu) >				\
  				get_event_ ##func(two, vcpu);		\
  }
  
  GET_EVENT_KEY(time, time);
  COMPARE_EVENT_KEY(count, stats.n);
  COMPARE_EVENT_KEY(mean, stats.mean);
62d04dbf3   David Ahern   perf kvm: Add min...
456
457
  GET_EVENT_KEY(max, stats.max);
  GET_EVENT_KEY(min, stats.min);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
458
459
460
461
462
463
464
465
466
  
  #define DEF_SORT_NAME_KEY(name, compare_key)				\
  	{ #name, compare_kvm_event_ ## compare_key }
  
  static struct kvm_event_key keys[] = {
  	DEF_SORT_NAME_KEY(sample, count),
  	DEF_SORT_NAME_KEY(time, mean),
  	{ NULL, NULL }
  };
3786063a3   Xiao Guangrong   perf kvm: Rename ...
467
  static bool select_key(struct perf_kvm_stat *kvm)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
468
469
470
471
  {
  	int i;
  
  	for (i = 0; keys[i].name; i++) {
de332ac40   David Ahern   perf kvm: Move gl...
472
473
  		if (!strcmp(keys[i].name, kvm->sort_key)) {
  			kvm->compare = keys[i].key;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
474
475
476
  			return true;
  		}
  	}
de332ac40   David Ahern   perf kvm: Move gl...
477
478
  	pr_err("Unknown compare key:%s
  ", kvm->sort_key);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
479
480
  	return false;
  }
de332ac40   David Ahern   perf kvm: Move gl...
481
482
  static void insert_to_result(struct rb_root *result, struct kvm_event *event,
  			     key_cmp_fun bigger, int vcpu)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
483
  {
de332ac40   David Ahern   perf kvm: Move gl...
484
  	struct rb_node **rb = &result->rb_node;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
  	struct rb_node *parent = NULL;
  	struct kvm_event *p;
  
  	while (*rb) {
  		p = container_of(*rb, struct kvm_event, rb);
  		parent = *rb;
  
  		if (bigger(event, p, vcpu))
  			rb = &(*rb)->rb_left;
  		else
  			rb = &(*rb)->rb_right;
  	}
  
  	rb_link_node(&event->rb, parent, rb);
de332ac40   David Ahern   perf kvm: Move gl...
499
  	rb_insert_color(&event->rb, result);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
500
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
501
502
  static void
  update_total_count(struct perf_kvm_stat *kvm, struct kvm_event *event)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
503
  {
de332ac40   David Ahern   perf kvm: Move gl...
504
505
506
507
  	int vcpu = kvm->trace_vcpu;
  
  	kvm->total_count += get_event_count(event, vcpu);
  	kvm->total_time += get_event_time(event, vcpu);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
508
509
510
511
512
513
  }
  
  static bool event_is_valid(struct kvm_event *event, int vcpu)
  {
  	return !!get_event_count(event, vcpu);
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
514
  static void sort_result(struct perf_kvm_stat *kvm)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
515
516
  {
  	unsigned int i;
de332ac40   David Ahern   perf kvm: Move gl...
517
  	int vcpu = kvm->trace_vcpu;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
518
  	struct kvm_event *event;
355afe816   David Ahern   perf kvm: Add bra...
519
520
  	for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
  		list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry) {
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
521
  			if (event_is_valid(event, vcpu)) {
de332ac40   David Ahern   perf kvm: Move gl...
522
523
524
  				update_total_count(kvm, event);
  				insert_to_result(&kvm->result, event,
  						 kvm->compare, vcpu);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
525
  			}
355afe816   David Ahern   perf kvm: Add bra...
526
527
  		}
  	}
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
528
529
530
  }
  
  /* returns left most element of result, and erase it */
de332ac40   David Ahern   perf kvm: Move gl...
531
  static struct kvm_event *pop_from_result(struct rb_root *result)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
532
  {
de332ac40   David Ahern   perf kvm: Move gl...
533
  	struct rb_node *node = rb_first(result);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
534
535
536
  
  	if (!node)
  		return NULL;
de332ac40   David Ahern   perf kvm: Move gl...
537
  	rb_erase(node, result);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
538
539
  	return container_of(node, struct kvm_event, rb);
  }
1afe1d148   David Ahern   perf kvm: Add liv...
540
  static void print_vcpu_info(struct perf_kvm_stat *kvm)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
541
  {
1afe1d148   David Ahern   perf kvm: Add liv...
542
  	int vcpu = kvm->trace_vcpu;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
543
  	pr_info("Analyze events for ");
1f3e5b550   Alexander Yarygin   perf kvm stat rep...
544
545
546
547
548
549
  	if (kvm->opts.target.system_wide)
  		pr_info("all VMs, ");
  	else if (kvm->opts.target.pid)
  		pr_info("pid(s) %s, ", kvm->opts.target.pid);
  	else
  		pr_info("dazed and confused on what is monitored, ");
1afe1d148   David Ahern   perf kvm: Add liv...
550

bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
551
552
553
554
555
556
557
558
559
  	if (vcpu == -1)
  		pr_info("all VCPUs:
  
  ");
  	else
  		pr_info("VCPU %d:
  
  ", vcpu);
  }
1afe1d148   David Ahern   perf kvm: Add liv...
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  static void show_timeofday(void)
  {
  	char date[64];
  	struct timeval tv;
  	struct tm ltime;
  
  	gettimeofday(&tv, NULL);
  	if (localtime_r(&tv.tv_sec, &ltime)) {
  		strftime(date, sizeof(date), "%H:%M:%S", &ltime);
  		pr_info("%s.%06ld", date, tv.tv_usec);
  	} else
  		pr_info("00:00:00.000000");
  
  	return;
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
575
  static void print_result(struct perf_kvm_stat *kvm)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
576
  {
162607ea2   Hemant Kumar   perf kvm/{x86,s39...
577
  	char decode[decode_str_len];
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
578
  	struct kvm_event *event;
de332ac40   David Ahern   perf kvm: Move gl...
579
  	int vcpu = kvm->trace_vcpu;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
580

1afe1d148   David Ahern   perf kvm: Add liv...
581
582
583
584
  	if (kvm->live) {
  		puts(CONSOLE_CLEAR);
  		show_timeofday();
  	}
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
585
586
587
  	pr_info("
  
  ");
1afe1d148   David Ahern   perf kvm: Add liv...
588
  	print_vcpu_info(kvm);
162607ea2   Hemant Kumar   perf kvm/{x86,s39...
589
  	pr_info("%*s ", decode_str_len, kvm->events_ops->name);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
590
591
592
593
  	pr_info("%10s ", "Samples");
  	pr_info("%9s ", "Samples%");
  
  	pr_info("%9s ", "Time%");
b048a24cc   Christian Borntraeger   perf kvm stat: Pr...
594
595
  	pr_info("%11s ", "Min Time");
  	pr_info("%11s ", "Max Time");
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
596
597
598
599
  	pr_info("%16s ", "Avg time");
  	pr_info("
  
  ");
de332ac40   David Ahern   perf kvm: Move gl...
600
  	while ((event = pop_from_result(&kvm->result))) {
62d04dbf3   David Ahern   perf kvm: Add min...
601
  		u64 ecount, etime, max, min;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
602
603
604
  
  		ecount = get_event_count(event, vcpu);
  		etime = get_event_time(event, vcpu);
62d04dbf3   David Ahern   perf kvm: Add min...
605
606
  		max = get_event_max(event, vcpu);
  		min = get_event_min(event, vcpu);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
607

de332ac40   David Ahern   perf kvm: Move gl...
608
  		kvm->events_ops->decode_key(kvm, &event->key, decode);
162607ea2   Hemant Kumar   perf kvm/{x86,s39...
609
  		pr_info("%*s ", decode_str_len, decode);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
610
  		pr_info("%10llu ", (unsigned long long)ecount);
de332ac40   David Ahern   perf kvm: Move gl...
611
612
  		pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
  		pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
c05a6e141   Arnaldo Carvalho de Melo   perf kvm: Use NSE...
613
614
615
  		pr_info("%9.2fus ", (double)min / NSEC_PER_USEC);
  		pr_info("%9.2fus ", (double)max / NSEC_PER_USEC);
  		pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount / NSEC_PER_USEC,
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
616
617
618
619
  			kvm_event_rel_stddev(vcpu, event));
  		pr_info("
  ");
  	}
e4f7637f8   David Ahern   perf kvm: Total c...
620
621
622
623
  	pr_info("
  Total Samples:%" PRIu64 ", Total events handled time:%.2fus.
  
  ",
c05a6e141   Arnaldo Carvalho de Melo   perf kvm: Use NSE...
624
  		kvm->total_count, kvm->total_time / (double)NSEC_PER_USEC);
1afe1d148   David Ahern   perf kvm: Add liv...
625
626
627
628
629
630
631
  
  	if (kvm->lost_events)
  		pr_info("
  Lost events: %" PRIu64 "
  
  ", kvm->lost_events);
  }
87419c9af   David Ahern   perf kvm: Disable...
632
  #ifdef HAVE_TIMERFD_SUPPORT
1afe1d148   David Ahern   perf kvm: Add liv...
633
634
635
636
637
638
639
640
641
  static int process_lost_event(struct perf_tool *tool,
  			      union perf_event *event __maybe_unused,
  			      struct perf_sample *sample __maybe_unused,
  			      struct machine *machine __maybe_unused)
  {
  	struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat, tool);
  
  	kvm->lost_events++;
  	return 0;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
642
  }
87419c9af   David Ahern   perf kvm: Disable...
643
  #endif
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
644

2e73f00fe   David Ahern   perf kvm stat rep...
645
646
647
648
649
650
651
652
  static bool skip_sample(struct perf_kvm_stat *kvm,
  			struct perf_sample *sample)
  {
  	if (kvm->pid_list && intlist__find(kvm->pid_list, sample->pid) == NULL)
  		return true;
  
  	return false;
  }
de332ac40   David Ahern   perf kvm: Move gl...
653
  static int process_sample_event(struct perf_tool *tool,
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
654
655
  				union perf_event *event,
  				struct perf_sample *sample,
32dcd021d   Jiri Olsa   perf evsel: Renam...
656
  				struct evsel *evsel,
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
657
658
  				struct machine *machine)
  {
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
659
  	int err = 0;
2e73f00fe   David Ahern   perf kvm stat rep...
660
  	struct thread *thread;
3786063a3   Xiao Guangrong   perf kvm: Rename ...
661
662
  	struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat,
  						 tool);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
663

2e73f00fe   David Ahern   perf kvm stat rep...
664
665
  	if (skip_sample(kvm, sample))
  		return 0;
314add6b1   Adrian Hunter   perf tools: chang...
666
  	thread = machine__findnew_thread(machine, sample->pid, sample->tid);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
667
668
669
670
671
672
  	if (thread == NULL) {
  		pr_debug("problem processing %d event, skipping it.
  ",
  			event->header.type);
  		return -1;
  	}
de332ac40   David Ahern   perf kvm: Move gl...
673
  	if (!handle_kvm_event(kvm, thread, evsel, sample))
b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
674
  		err = -1;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
675

b91fc39f4   Arnaldo Carvalho de Melo   perf machine: Pro...
676
677
  	thread__put(thread);
  	return err;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
678
  }
1afe1d148   David Ahern   perf kvm: Add liv...
679
  static int cpu_isa_config(struct perf_kvm_stat *kvm)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
680
  {
f67001a4a   Arnaldo Carvalho de Melo   perf tools: Propa...
681
  	char buf[128], *cpuid;
65c647a65   Alexander Yarygin   perf kvm: Refacto...
682
  	int err;
1afe1d148   David Ahern   perf kvm: Add liv...
683
684
685
686
  
  	if (kvm->live) {
  		err = get_cpuid(buf, sizeof(buf));
  		if (err != 0) {
f67001a4a   Arnaldo Carvalho de Melo   perf tools: Propa...
687
688
689
690
  			pr_err("Failed to look up CPU type: %s
  ",
  			       str_error_r(err, buf, sizeof(buf)));
  			return -err;
1afe1d148   David Ahern   perf kvm: Add liv...
691
692
693
694
  		}
  		cpuid = buf;
  	} else
  		cpuid = kvm->session->header.env.cpuid;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
695

65c647a65   Alexander Yarygin   perf kvm: Refacto...
696
697
698
699
  	if (!cpuid) {
  		pr_err("Failed to look up CPU type
  ");
  		return -EINVAL;
1afe1d148   David Ahern   perf kvm: Add liv...
700
  	}
65c647a65   Alexander Yarygin   perf kvm: Refacto...
701
702
703
704
  	err = cpu_isa_init(kvm, cpuid);
  	if (err == -ENOTSUP)
  		pr_err("CPU %s is not supported.
  ", cpuid);
1afe1d148   David Ahern   perf kvm: Add liv...
705

65c647a65   Alexander Yarygin   perf kvm: Refacto...
706
  	return err;
1afe1d148   David Ahern   perf kvm: Add liv...
707
708
709
710
711
712
713
714
715
716
717
718
  }
  
  static bool verify_vcpu(int vcpu)
  {
  	if (vcpu != -1 && vcpu < 0) {
  		pr_err("Invalid vcpu:%d.
  ", vcpu);
  		return false;
  	}
  
  	return true;
  }
87419c9af   David Ahern   perf kvm: Disable...
719
  #ifdef HAVE_TIMERFD_SUPPORT
1afe1d148   David Ahern   perf kvm: Add liv...
720
721
722
723
724
725
726
727
  /* keeping the max events to a modest level to keep
   * the processing of samples per mmap smooth.
   */
  #define PERF_KVM__MAX_EVENTS_PER_MMAP  25
  
  static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
  				   u64 *mmap_time)
  {
63503dba8   Jiri Olsa   perf evlist: Rena...
728
  	struct evlist *evlist = kvm->evlist;
1afe1d148   David Ahern   perf kvm: Add liv...
729
  	union perf_event *event;
a58305329   Jiri Olsa   perf tools: Renam...
730
  	struct mmap *md;
93d10af26   Jiri Olsa   perf tools: Optim...
731
  	u64 timestamp;
1afe1d148   David Ahern   perf kvm: Add liv...
732
733
734
735
  	s64 n = 0;
  	int err;
  
  	*mmap_time = ULLONG_MAX;
53172f905   Kan Liang   perf kvm: Switch ...
736
  	md = &evlist->mmap[idx];
7c4d41824   Jiri Olsa   libperf: Adopt pe...
737
  	err = perf_mmap__read_init(&md->core);
53172f905   Kan Liang   perf kvm: Switch ...
738
739
  	if (err < 0)
  		return (err == -EAGAIN) ? 0 : -1;
151ed5d70   Jiri Olsa   libperf: Adopt pe...
740
  	while ((event = perf_mmap__read_event(&md->core)) != NULL) {
53172f905   Kan Liang   perf kvm: Switch ...
741
  		err = perf_evlist__parse_sample_timestamp(evlist, event, &timestamp);
1afe1d148   David Ahern   perf kvm: Add liv...
742
  		if (err) {
7728fa0cf   Jiri Olsa   libperf: Adopt pe...
743
  			perf_mmap__consume(&md->core);
1afe1d148   David Ahern   perf kvm: Add liv...
744
745
746
747
  			pr_err("Failed to parse sample
  ");
  			return -1;
  		}
93d10af26   Jiri Olsa   perf tools: Optim...
748
  		err = perf_session__queue_event(kvm->session, event, timestamp, 0);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
749
  		/*
b7b61cbeb   Arnaldo Carvalho de Melo   perf ordered_even...
750
  		 * FIXME: Here we can't consume the event, as perf_session__queue_event will
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
751
752
  		 *        point to it, and it'll get possibly overwritten by the kernel.
  		 */
7728fa0cf   Jiri Olsa   libperf: Adopt pe...
753
  		perf_mmap__consume(&md->core);
8e50d384c   Zhouyi Zhou   perf tools: Fixup...
754

1afe1d148   David Ahern   perf kvm: Add liv...
755
756
757
758
759
760
761
762
  		if (err) {
  			pr_err("Failed to enqueue sample: %d
  ", err);
  			return -1;
  		}
  
  		/* save time stamp of our first sample for this mmap */
  		if (n == 0)
93d10af26   Jiri Olsa   perf tools: Optim...
763
  			*mmap_time = timestamp;
1afe1d148   David Ahern   perf kvm: Add liv...
764
765
766
767
768
769
  
  		/* limit events per mmap handled all at once */
  		n++;
  		if (n == PERF_KVM__MAX_EVENTS_PER_MMAP)
  			break;
  	}
32fdc2ca7   Jiri Olsa   libperf: Adopt pe...
770
  	perf_mmap__read_done(&md->core);
1afe1d148   David Ahern   perf kvm: Add liv...
771
772
773
774
775
776
777
778
  	return n;
  }
  
  static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
  {
  	int i, err, throttled = 0;
  	s64 n, ntotal = 0;
  	u64 flush_time = ULLONG_MAX, mmap_time;
c976ee11a   Jiri Olsa   libperf: Move 'nr...
779
  	for (i = 0; i < kvm->evlist->core.nr_mmaps; i++) {
1afe1d148   David Ahern   perf kvm: Add liv...
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
  		n = perf_kvm__mmap_read_idx(kvm, i, &mmap_time);
  		if (n < 0)
  			return -1;
  
  		/* flush time is going to be the minimum of all the individual
  		 * mmap times. Essentially, we flush all the samples queued up
  		 * from the last pass under our minimal start time -- that leaves
  		 * a very small race for samples to come in with a lower timestamp.
  		 * The ioctl to return the perf_clock timestamp should close the
  		 * race entirely.
  		 */
  		if (mmap_time < flush_time)
  			flush_time = mmap_time;
  
  		ntotal += n;
  		if (n == PERF_KVM__MAX_EVENTS_PER_MMAP)
  			throttled = 1;
  	}
  
  	/* flush queue after each round in which we processed events */
  	if (ntotal) {
d704ebdae   Arnaldo Carvalho de Melo   perf tools: tool-...
801
802
803
804
  		struct ordered_events *oe = &kvm->session->ordered_events;
  
  		oe->next_flush = flush_time;
  		err = ordered_events__flush(oe, OE_FLUSH__ROUND);
1afe1d148   David Ahern   perf kvm: Add liv...
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
  		if (err) {
  			if (kvm->lost_events)
  				pr_info("
  Lost events: %" PRIu64 "
  
  ",
  					kvm->lost_events);
  			return err;
  		}
  	}
  
  	return throttled;
  }
  
  static volatile int done;
  
  static void sig_handler(int sig __maybe_unused)
  {
  	done = 1;
  }
  
  static int perf_kvm__timerfd_create(struct perf_kvm_stat *kvm)
  {
  	struct itimerspec new_value;
  	int rc = -1;
  
  	kvm->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
  	if (kvm->timerfd < 0) {
  		pr_err("timerfd_create failed
  ");
  		goto out;
  	}
  
  	new_value.it_value.tv_sec = kvm->display_time;
  	new_value.it_value.tv_nsec = 0;
  	new_value.it_interval.tv_sec = kvm->display_time;
  	new_value.it_interval.tv_nsec = 0;
  
  	if (timerfd_settime(kvm->timerfd, 0, &new_value, NULL) != 0) {
  		pr_err("timerfd_settime failed: %d
  ", errno);
  		close(kvm->timerfd);
  		goto out;
  	}
  
  	rc = 0;
  out:
  	return rc;
  }
  
  static int perf_kvm__handle_timerfd(struct perf_kvm_stat *kvm)
  {
  	uint64_t c;
  	int rc;
  
  	rc = read(kvm->timerfd, &c, sizeof(uint64_t));
  	if (rc < 0) {
  		if (errno == EAGAIN)
  			return 0;
  
  		pr_err("Failed to read timer fd: %d
  ", errno);
  		return -1;
  	}
  
  	if (rc != sizeof(uint64_t)) {
  		pr_err("Error reading timer fd - invalid size returned
  ");
  		return -1;
  	}
  
  	if (c != 1)
  		pr_debug("Missed timer beats: %" PRIu64 "
  ", c-1);
  
  	/* update display */
  	sort_result(kvm);
  	print_result(kvm);
  
  	/* reset counts */
  	clear_events_cache_stats(kvm->kvm_events_cache);
  	kvm->total_count = 0;
  	kvm->total_time = 0;
  	kvm->lost_events = 0;
  
  	return 0;
  }
  
  static int fd_set_nonblock(int fd)
  {
  	long arg = 0;
  
  	arg = fcntl(fd, F_GETFL);
  	if (arg < 0) {
  		pr_err("Failed to get current flags for fd %d
  ", fd);
  		return -1;
  	}
  
  	if (fcntl(fd, F_SETFL, arg | O_NONBLOCK) < 0) {
  		pr_err("Failed to set non-block option on fd %d
  ", fd);
  		return -1;
  	}
  
  	return 0;
  }
d5b4130ae   Jiri Olsa   perf kvm: Fix std...
912
  static int perf_kvm__handle_stdin(void)
1afe1d148   David Ahern   perf kvm: Add liv...
913
914
  {
  	int c;
1afe1d148   David Ahern   perf kvm: Add liv...
915
  	c = getc(stdin);
1afe1d148   David Ahern   perf kvm: Add liv...
916
917
918
919
920
921
922
923
  	if (c == 'q')
  		return 1;
  
  	return 0;
  }
  
  static int kvm_events_live_report(struct perf_kvm_stat *kvm)
  {
1ca72260e   Jiri Olsa   perf kvm stat liv...
924
  	int nr_stdin, ret, err = -EINVAL;
d5b4130ae   Jiri Olsa   perf kvm: Fix std...
925
  	struct termios save;
1afe1d148   David Ahern   perf kvm: Add liv...
926
927
928
929
930
931
932
933
934
935
936
937
938
  
  	/* live flag must be set first */
  	kvm->live = true;
  
  	ret = cpu_isa_config(kvm);
  	if (ret < 0)
  		return ret;
  
  	if (!verify_vcpu(kvm->trace_vcpu) ||
  	    !select_key(kvm) ||
  	    !register_kvm_events_ops(kvm)) {
  		goto out;
  	}
d5b4130ae   Jiri Olsa   perf kvm: Fix std...
939
  	set_term_quiet_input(&save);
1afe1d148   David Ahern   perf kvm: Add liv...
940
  	init_kvm_event_record(kvm);
1afe1d148   David Ahern   perf kvm: Add liv...
941
942
  	signal(SIGINT, sig_handler);
  	signal(SIGTERM, sig_handler);
1afe1d148   David Ahern   perf kvm: Add liv...
943
944
945
946
947
  	/* add timer fd */
  	if (perf_kvm__timerfd_create(kvm) < 0) {
  		err = -1;
  		goto out;
  	}
f4009e7bf   Jiri Olsa   libperf: Add perf...
948
  	if (evlist__add_pollfd(kvm->evlist, kvm->timerfd) < 0)
0a04c9e0b   Arnaldo Carvalho de Melo   perf kvm stat liv...
949
  		goto out;
f4009e7bf   Jiri Olsa   libperf: Add perf...
950
  	nr_stdin = evlist__add_pollfd(kvm->evlist, fileno(stdin));
0cae013cf   Jiri Olsa   perf kvm stat liv...
951
  	if (nr_stdin < 0)
0a04c9e0b   Arnaldo Carvalho de Melo   perf kvm stat liv...
952
  		goto out;
1afe1d148   David Ahern   perf kvm: Add liv...
953
954
955
956
  	if (fd_set_nonblock(fileno(stdin)) != 0)
  		goto out;
  
  	/* everything is good - enable the events and process */
1c87f1654   Jiri Olsa   perf evlist: Rena...
957
  	evlist__enable(kvm->evlist);
1afe1d148   David Ahern   perf kvm: Add liv...
958
959
  
  	while (!done) {
40cb2d514   Jiri Olsa   libperf: Move 'po...
960
  		struct fdarray *fda = &kvm->evlist->core.pollfd;
1afe1d148   David Ahern   perf kvm: Add liv...
961
962
963
964
965
966
967
968
969
  		int rc;
  
  		rc = perf_kvm__mmap_read(kvm);
  		if (rc < 0)
  			break;
  
  		err = perf_kvm__handle_timerfd(kvm);
  		if (err)
  			goto out;
1ca72260e   Jiri Olsa   perf kvm stat liv...
970
  		if (fda->entries[nr_stdin].revents & POLLIN)
d5b4130ae   Jiri Olsa   perf kvm: Fix std...
971
  			done = perf_kvm__handle_stdin();
1afe1d148   David Ahern   perf kvm: Add liv...
972
973
  
  		if (!rc && !done)
4bfbcf3ee   Igor Lubashev   perf kvm: Use evl...
974
  			err = evlist__poll(kvm->evlist, 100);
1afe1d148   David Ahern   perf kvm: Add liv...
975
  	}
e74676deb   Jiri Olsa   perf evlist: Rena...
976
  	evlist__disable(kvm->evlist);
1afe1d148   David Ahern   perf kvm: Add liv...
977
978
979
980
981
982
983
984
985
  
  	if (err == 0) {
  		sort_result(kvm);
  		print_result(kvm);
  	}
  
  out:
  	if (kvm->timerfd >= 0)
  		close(kvm->timerfd);
d5b4130ae   Jiri Olsa   perf kvm: Fix std...
986
  	tcsetattr(0, TCSAFLUSH, &save);
1afe1d148   David Ahern   perf kvm: Add liv...
987
988
989
990
991
992
  	return err;
  }
  
  static int kvm_live_open_events(struct perf_kvm_stat *kvm)
  {
  	int err, rc = -1;
32dcd021d   Jiri Olsa   perf evsel: Renam...
993
  	struct evsel *pos;
63503dba8   Jiri Olsa   perf evlist: Rena...
994
  	struct evlist *evlist = kvm->evlist;
f9f33fdba   Masami Hiramatsu   perf kvm: Use str...
995
  	char sbuf[STRERR_BUFSIZE];
1afe1d148   David Ahern   perf kvm: Add liv...
996

e68ae9cf7   Arnaldo Carvalho de Melo   perf evsel: Do no...
997
  	perf_evlist__config(evlist, &kvm->opts, NULL);
1afe1d148   David Ahern   perf kvm: Add liv...
998
999
1000
1001
1002
  
  	/*
  	 * Note: exclude_{guest,host} do not apply here.
  	 *       This command processes KVM tracepoints from host only
  	 */
e5cadb93d   Arnaldo Carvalho de Melo   perf evlist: Rena...
1003
  	evlist__for_each_entry(evlist, pos) {
1fc632cef   Jiri Olsa   libperf: Move per...
1004
  		struct perf_event_attr *attr = &pos->core.attr;
1afe1d148   David Ahern   perf kvm: Add liv...
1005
1006
  
  		/* make sure these *are* set */
862b2f8fb   Arnaldo Carvalho de Melo   perf evsel: Renam...
1007
1008
1009
1010
  		evsel__set_sample_bit(pos, TID);
  		evsel__set_sample_bit(pos, TIME);
  		evsel__set_sample_bit(pos, CPU);
  		evsel__set_sample_bit(pos, RAW);
1afe1d148   David Ahern   perf kvm: Add liv...
1011
  		/* make sure these are *not*; want as small a sample as possible */
862b2f8fb   Arnaldo Carvalho de Melo   perf evsel: Renam...
1012
1013
1014
1015
1016
  		evsel__reset_sample_bit(pos, PERIOD);
  		evsel__reset_sample_bit(pos, IP);
  		evsel__reset_sample_bit(pos, CALLCHAIN);
  		evsel__reset_sample_bit(pos, ADDR);
  		evsel__reset_sample_bit(pos, READ);
1afe1d148   David Ahern   perf kvm: Add liv...
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
  		attr->mmap = 0;
  		attr->comm = 0;
  		attr->task = 0;
  
  		attr->sample_period = 1;
  
  		attr->watermark = 0;
  		attr->wakeup_events = 1000;
  
  		/* will enable all once we are ready */
  		attr->disabled = 1;
  	}
474ddc4c4   Jiri Olsa   perf evlist: Rena...
1029
  	err = evlist__open(evlist);
1afe1d148   David Ahern   perf kvm: Add liv...
1030
  	if (err < 0) {
f9f33fdba   Masami Hiramatsu   perf kvm: Use str...
1031
1032
  		printf("Couldn't create the events: %s
  ",
c8b5f2c96   Arnaldo Carvalho de Melo   tools: Introduce ...
1033
  		       str_error_r(errno, sbuf, sizeof(sbuf)));
1afe1d148   David Ahern   perf kvm: Add liv...
1034
  		goto out;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1035
  	}
9521b5f2d   Jiri Olsa   perf tools: Renam...
1036
  	if (evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) {
f9f33fdba   Masami Hiramatsu   perf kvm: Use str...
1037
1038
  		ui__error("Failed to mmap the events: %s
  ",
c8b5f2c96   Arnaldo Carvalho de Melo   tools: Introduce ...
1039
  			  str_error_r(errno, sbuf, sizeof(sbuf)));
750b4edeb   Jiri Olsa   perf evlist: Rena...
1040
  		evlist__close(evlist);
1afe1d148   David Ahern   perf kvm: Add liv...
1041
1042
1043
1044
1045
1046
1047
  		goto out;
  	}
  
  	rc = 0;
  
  out:
  	return rc;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1048
  }
87419c9af   David Ahern   perf kvm: Disable...
1049
  #endif
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1050

3786063a3   Xiao Guangrong   perf kvm: Rename ...
1051
  static int read_events(struct perf_kvm_stat *kvm)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1052
  {
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1053
  	int ret;
de332ac40   David Ahern   perf kvm: Move gl...
1054
1055
1056
  	struct perf_tool eops = {
  		.sample			= process_sample_event,
  		.comm			= perf_event__process_comm,
f3b3614a2   Hari Bathini   perf tools: Add P...
1057
  		.namespaces		= perf_event__process_namespaces,
0a8cb85c2   Jiri Olsa   perf tools: Renam...
1058
  		.ordered_events		= true,
de332ac40   David Ahern   perf kvm: Move gl...
1059
  	};
8ceb41d7e   Jiri Olsa   perf tools: Renam...
1060
  	struct perf_data file = {
2d4f27999   Jiri Olsa   perf data: Add gl...
1061
1062
1063
  		.path  = kvm->file_name,
  		.mode  = PERF_DATA_MODE_READ,
  		.force = kvm->force,
f5fc14124   Jiri Olsa   perf tools: Add d...
1064
  	};
de332ac40   David Ahern   perf kvm: Move gl...
1065
1066
  
  	kvm->tool = eops;
f5fc14124   Jiri Olsa   perf tools: Add d...
1067
  	kvm->session = perf_session__new(&file, false, &kvm->tool);
6ef81c55a   Mamatha Inamdar   perf session: Ret...
1068
  	if (IS_ERR(kvm->session)) {
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1069
1070
  		pr_err("Initializing perf session failed
  ");
6ef81c55a   Mamatha Inamdar   perf session: Ret...
1071
  		return PTR_ERR(kvm->session);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1072
  	}
0a7e6d1b6   Namhyung Kim   perf tools: Check...
1073
  	symbol__init(&kvm->session->header.env);
14d37f38e   Namhyung Kim   perf kvm: Move ca...
1074

41b983609   Taeung Song   perf kvm: Fill in...
1075
1076
1077
1078
  	if (!perf_session__has_traces(kvm->session, "kvm record")) {
  		ret = -EINVAL;
  		goto out_delete;
  	}
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1079
1080
1081
1082
1083
  
  	/*
  	 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
  	 * traced in the old kernel.
  	 */
1afe1d148   David Ahern   perf kvm: Add liv...
1084
  	ret = cpu_isa_config(kvm);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1085
  	if (ret < 0)
41b983609   Taeung Song   perf kvm: Fill in...
1086
1087
1088
  		goto out_delete;
  
  	ret = perf_session__process_events(kvm->session);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1089

41b983609   Taeung Song   perf kvm: Fill in...
1090
1091
1092
  out_delete:
  	perf_session__delete(kvm->session);
  	return ret;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1093
  }
2e73f00fe   David Ahern   perf kvm stat rep...
1094
1095
  static int parse_target_str(struct perf_kvm_stat *kvm)
  {
3ae4a76ac   Alexander Yarygin   perf kvm stat rep...
1096
1097
  	if (kvm->opts.target.pid) {
  		kvm->pid_list = intlist__new(kvm->opts.target.pid);
2e73f00fe   David Ahern   perf kvm stat rep...
1098
1099
1100
1101
1102
1103
1104
1105
1106
  		if (kvm->pid_list == NULL) {
  			pr_err("Error parsing process id string
  ");
  			return -EINVAL;
  		}
  	}
  
  	return 0;
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1107
  static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1108
1109
  {
  	int ret = -EINVAL;
de332ac40   David Ahern   perf kvm: Move gl...
1110
  	int vcpu = kvm->trace_vcpu;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1111

2e73f00fe   David Ahern   perf kvm stat rep...
1112
1113
  	if (parse_target_str(kvm) != 0)
  		goto exit;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1114
1115
  	if (!verify_vcpu(vcpu))
  		goto exit;
de332ac40   David Ahern   perf kvm: Move gl...
1116
  	if (!select_key(kvm))
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1117
  		goto exit;
de332ac40   David Ahern   perf kvm: Move gl...
1118
  	if (!register_kvm_events_ops(kvm))
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1119
  		goto exit;
de332ac40   David Ahern   perf kvm: Move gl...
1120
  	init_kvm_event_record(kvm);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1121
  	setup_pager();
de332ac40   David Ahern   perf kvm: Move gl...
1122
  	ret = read_events(kvm);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1123
1124
  	if (ret)
  		goto exit;
de332ac40   David Ahern   perf kvm: Move gl...
1125
1126
  	sort_result(kvm);
  	print_result(kvm);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1127
1128
1129
  exit:
  	return ret;
  }
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1130
1131
1132
1133
1134
1135
1136
  #define STRDUP_FAIL_EXIT(s)		\
  	({	char *_p;		\
  	_p = strdup(s);		\
  		if (!_p)		\
  			return -ENOMEM;	\
  		_p;			\
  	})
066d3593e   Hemant Kumar   perf kvm/powerpc:...
1137
1138
1139
1140
  int __weak setup_kvm_events_tp(struct perf_kvm_stat *kvm __maybe_unused)
  {
  	return 0;
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1141
1142
  static int
  kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1143
  {
9daa81239   Alexander Yarygin   perf kvm: Move ar...
1144
  	unsigned int rec_argc, i, j, events_tp_size;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1145
  	const char **rec_argv;
8fdd84c44   David Ahern   perf kvm: Split o...
1146
1147
1148
  	const char * const record_args[] = {
  		"record",
  		"-R",
8fdd84c44   David Ahern   perf kvm: Split o...
1149
1150
1151
  		"-m", "1024",
  		"-c", "1",
  	};
f45d20ffb   Namhyung Kim   perf kvm: Print k...
1152
1153
1154
1155
  	const char * const kvm_stat_record_usage[] = {
  		"perf kvm stat record [<options>]",
  		NULL
  	};
9daa81239   Alexander Yarygin   perf kvm: Move ar...
1156
  	const char * const *events_tp;
066d3593e   Hemant Kumar   perf kvm/powerpc:...
1157
  	int ret;
9daa81239   Alexander Yarygin   perf kvm: Move ar...
1158
  	events_tp_size = 0;
066d3593e   Hemant Kumar   perf kvm/powerpc:...
1159
1160
1161
1162
1163
1164
  	ret = setup_kvm_events_tp(kvm);
  	if (ret < 0) {
  		pr_err("Unable to setup the kvm tracepoints
  ");
  		return ret;
  	}
9daa81239   Alexander Yarygin   perf kvm: Move ar...
1165
1166
1167
  
  	for (events_tp = kvm_events_tp; *events_tp; events_tp++)
  		events_tp_size++;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1168

8fdd84c44   David Ahern   perf kvm: Split o...
1169
  	rec_argc = ARRAY_SIZE(record_args) + argc + 2 +
9daa81239   Alexander Yarygin   perf kvm: Move ar...
1170
  		   2 * events_tp_size;
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1171
1172
1173
1174
1175
1176
1177
  	rec_argv = calloc(rec_argc + 1, sizeof(char *));
  
  	if (rec_argv == NULL)
  		return -ENOMEM;
  
  	for (i = 0; i < ARRAY_SIZE(record_args); i++)
  		rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
9daa81239   Alexander Yarygin   perf kvm: Move ar...
1178
  	for (j = 0; j < events_tp_size; j++) {
8fdd84c44   David Ahern   perf kvm: Split o...
1179
1180
1181
  		rec_argv[i++] = "-e";
  		rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp[j]);
  	}
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1182
  	rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
de332ac40   David Ahern   perf kvm: Move gl...
1183
  	rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1184
1185
1186
  
  	for (j = 1; j < (unsigned int)argc; j++, i++)
  		rec_argv[i] = argv[j];
f45d20ffb   Namhyung Kim   perf kvm: Print k...
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
  	set_option_flag(record_options, 'e', "event", PARSE_OPT_HIDDEN);
  	set_option_flag(record_options, 0, "filter", PARSE_OPT_HIDDEN);
  	set_option_flag(record_options, 'R', "raw-samples", PARSE_OPT_HIDDEN);
  
  	set_option_flag(record_options, 'F', "freq", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 0, "group", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'g', NULL, PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 0, "call-graph", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'd', "data", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'T', "timestamp", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'P', "period", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'n', "no-samples", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'N', "no-buildid-cache", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'B', "no-buildid", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'G', "cgroup", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'b', "branch-any", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'j', "branch-filter", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 'W', "weight", PARSE_OPT_DISABLED);
  	set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED);
  
  	record_usage = kvm_stat_record_usage;
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
1208
  	return cmd_record(i, rec_argv);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1209
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1210
1211
  static int
  kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
de332ac40   David Ahern   perf kvm: Move gl...
1212
1213
1214
  {
  	const struct option kvm_events_report_options[] = {
  		OPT_STRING(0, "event", &kvm->report_event, "report event",
3be8e2a0a   Alexander Yarygin   perf kvm: Add sta...
1215
1216
  			   "event for reporting: vmexit, "
  			   "mmio (x86 only), ioport (x86 only)"),
de332ac40   David Ahern   perf kvm: Move gl...
1217
1218
1219
1220
1221
  		OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
  			    "vcpu id to report"),
  		OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
  			    "key for sorting: sample(sort by samples number)"
  			    " time (sort by avg time)"),
3ae4a76ac   Alexander Yarygin   perf kvm stat rep...
1222
  		OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
2e73f00fe   David Ahern   perf kvm stat rep...
1223
  			   "analyze events only for given process id(s)"),
8cc5ec1f7   Yunlong Song   perf kvm: Support...
1224
  		OPT_BOOLEAN('f', "force", &kvm->force, "don't complain, do it"),
de332ac40   David Ahern   perf kvm: Move gl...
1225
1226
  		OPT_END()
  	};
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1227

de332ac40   David Ahern   perf kvm: Move gl...
1228
1229
1230
1231
  	const char * const kvm_events_report_usage[] = {
  		"perf kvm stat report [<options>]",
  		NULL
  	};
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1232

bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1233
1234
1235
1236
1237
1238
1239
1240
  	if (argc) {
  		argc = parse_options(argc, argv,
  				     kvm_events_report_options,
  				     kvm_events_report_usage, 0);
  		if (argc)
  			usage_with_options(kvm_events_report_usage,
  					   kvm_events_report_options);
  	}
f181957c2   Alexander Yarygin   perf kvm stat rep...
1241
1242
  	if (!kvm->opts.target.pid)
  		kvm->opts.target.system_wide = true;
de332ac40   David Ahern   perf kvm: Move gl...
1243
  	return kvm_events_report_vcpu(kvm);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1244
  }
87419c9af   David Ahern   perf kvm: Disable...
1245
  #ifdef HAVE_TIMERFD_SUPPORT
63503dba8   Jiri Olsa   perf evlist: Rena...
1246
  static struct evlist *kvm_live_event_list(void)
1afe1d148   David Ahern   perf kvm: Add liv...
1247
  {
63503dba8   Jiri Olsa   perf evlist: Rena...
1248
  	struct evlist *evlist;
1afe1d148   David Ahern   perf kvm: Add liv...
1249
  	char *tp, *name, *sys;
1afe1d148   David Ahern   perf kvm: Add liv...
1250
  	int err = -1;
9daa81239   Alexander Yarygin   perf kvm: Move ar...
1251
  	const char * const *events_tp;
1afe1d148   David Ahern   perf kvm: Add liv...
1252

0f98b11c6   Jiri Olsa   perf evlist: Rena...
1253
  	evlist = evlist__new();
1afe1d148   David Ahern   perf kvm: Add liv...
1254
1255
  	if (evlist == NULL)
  		return NULL;
9daa81239   Alexander Yarygin   perf kvm: Move ar...
1256
  	for (events_tp = kvm_events_tp; *events_tp; events_tp++) {
1afe1d148   David Ahern   perf kvm: Add liv...
1257

9daa81239   Alexander Yarygin   perf kvm: Move ar...
1258
  		tp = strdup(*events_tp);
1afe1d148   David Ahern   perf kvm: Add liv...
1259
1260
1261
1262
1263
1264
1265
1266
1267
  		if (tp == NULL)
  			goto out;
  
  		/* split tracepoint into subsystem and name */
  		sys = tp;
  		name = strchr(tp, ':');
  		if (name == NULL) {
  			pr_err("Error parsing %s tracepoint: subsystem delimiter not found
  ",
9daa81239   Alexander Yarygin   perf kvm: Move ar...
1268
  			       *events_tp);
1afe1d148   David Ahern   perf kvm: Add liv...
1269
1270
1271
1272
1273
  			free(tp);
  			goto out;
  		}
  		*name = '\0';
  		name++;
e251abee8   Arnaldo Carvalho de Melo   perf evlist: Fix ...
1274
  		if (evlist__add_newtp(evlist, sys, name, NULL)) {
9daa81239   Alexander Yarygin   perf kvm: Move ar...
1275
1276
  			pr_err("Failed to add %s tracepoint to the list
  ", *events_tp);
1afe1d148   David Ahern   perf kvm: Add liv...
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
  			free(tp);
  			goto out;
  		}
  
  		free(tp);
  	}
  
  	err = 0;
  
  out:
  	if (err) {
c12995a55   Jiri Olsa   perf evlist: Rena...
1288
  		evlist__delete(evlist);
1afe1d148   David Ahern   perf kvm: Add liv...
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
  		evlist = NULL;
  	}
  
  	return evlist;
  }
  
  static int kvm_events_live(struct perf_kvm_stat *kvm,
  			   int argc, const char **argv)
  {
  	char errbuf[BUFSIZ];
  	int err;
  
  	const struct option live_options[] = {
  		OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
  			"record events on existing process id"),
994a1f78b   Jiri Olsa   perf tools: Check...
1304
1305
1306
  		OPT_CALLBACK('m', "mmap-pages", &kvm->opts.mmap_pages, "pages",
  			"number of mmap data pages",
  			perf_evlist__parse_mmap_pages),
1afe1d148   David Ahern   perf kvm: Add liv...
1307
1308
1309
1310
1311
1312
1313
  		OPT_INCR('v', "verbose", &verbose,
  			"be more verbose (show counter open errors, etc)"),
  		OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide,
  			"system-wide collection from all CPUs"),
  		OPT_UINTEGER('d', "display", &kvm->display_time,
  			"time in seconds between display updates"),
  		OPT_STRING(0, "event", &kvm->report_event, "report event",
99d348a84   Alexander Yarygin   perf kvm stat liv...
1314
1315
  			"event for reporting: "
  			"vmexit, mmio (x86 only), ioport (x86 only)"),
1afe1d148   David Ahern   perf kvm: Add liv...
1316
1317
1318
1319
1320
  		OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
  			"vcpu id to report"),
  		OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
  			"key for sorting: sample(sort by samples number)"
  			" time (sort by avg time)"),
70f7b4a7f   David Ahern   perf kvm: Option ...
1321
  		OPT_U64(0, "duration", &kvm->duration,
3be8e2a0a   Alexander Yarygin   perf kvm: Add sta...
1322
1323
1324
  			"show events other than"
  			" HLT (x86 only) or Wait state (s390 only)"
  			" that take longer than duration usecs"),
3fcb10e49   Mark Drayton   perf tools: Allow...
1325
  		OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout,
9d9cad763   Kan Liang   perf tools: Confi...
1326
  				"per thread proc mmap processing timeout in ms"),
1afe1d148   David Ahern   perf kvm: Add liv...
1327
1328
1329
1330
1331
1332
  		OPT_END()
  	};
  	const char * const live_usage[] = {
  		"perf kvm stat live [<options>]",
  		NULL
  	};
8ceb41d7e   Jiri Olsa   perf tools: Renam...
1333
  	struct perf_data data = {
f5fc14124   Jiri Olsa   perf tools: Add d...
1334
1335
  		.mode = PERF_DATA_MODE_WRITE,
  	};
1afe1d148   David Ahern   perf kvm: Add liv...
1336
1337
1338
1339
1340
1341
1342
1343
  
  
  	/* event handling */
  	kvm->tool.sample = process_sample_event;
  	kvm->tool.comm   = perf_event__process_comm;
  	kvm->tool.exit   = perf_event__process_exit;
  	kvm->tool.fork   = perf_event__process_fork;
  	kvm->tool.lost   = process_lost_event;
f3b3614a2   Hari Bathini   perf tools: Add P...
1344
  	kvm->tool.namespaces  = perf_event__process_namespaces;
0a8cb85c2   Jiri Olsa   perf tools: Renam...
1345
  	kvm->tool.ordered_events = true;
1afe1d148   David Ahern   perf kvm: Add liv...
1346
1347
1348
1349
1350
1351
1352
1353
1354
  	perf_tool__fill_defaults(&kvm->tool);
  
  	/* set defaults */
  	kvm->display_time = 1;
  	kvm->opts.user_interval = 1;
  	kvm->opts.mmap_pages = 512;
  	kvm->opts.target.uses_mmap = false;
  	kvm->opts.target.uid_str = NULL;
  	kvm->opts.target.uid = UINT_MAX;
0a7e6d1b6   Namhyung Kim   perf tools: Check...
1355
  	symbol__init(NULL);
1afe1d148   David Ahern   perf kvm: Add liv...
1356
1357
1358
  	disable_buildid_cache();
  
  	use_browser = 0;
1afe1d148   David Ahern   perf kvm: Add liv...
1359
1360
1361
1362
1363
1364
1365
  
  	if (argc) {
  		argc = parse_options(argc, argv, live_options,
  				     live_usage, 0);
  		if (argc)
  			usage_with_options(live_usage, live_options);
  	}
70f7b4a7f   David Ahern   perf kvm: Option ...
1366
  	kvm->duration *= NSEC_PER_USEC;   /* convert usec to nsec */
1afe1d148   David Ahern   perf kvm: Add liv...
1367
1368
1369
  	/*
  	 * target related setups
  	 */
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
1370
  	err = target__validate(&kvm->opts.target);
1afe1d148   David Ahern   perf kvm: Add liv...
1371
  	if (err) {
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
1372
  		target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ);
1afe1d148   David Ahern   perf kvm: Add liv...
1373
1374
  		ui__warning("%s", errbuf);
  	}
602ad878d   Arnaldo Carvalho de Melo   perf target: Shor...
1375
  	if (target__none(&kvm->opts.target))
1afe1d148   David Ahern   perf kvm: Add liv...
1376
1377
1378
1379
1380
1381
  		kvm->opts.target.system_wide = true;
  
  
  	/*
  	 * generate the event list
  	 */
066d3593e   Hemant Kumar   perf kvm/powerpc:...
1382
1383
1384
1385
1386
1387
  	err = setup_kvm_events_tp(kvm);
  	if (err < 0) {
  		pr_err("Unable to setup the kvm tracepoints
  ");
  		return err;
  	}
1afe1d148   David Ahern   perf kvm: Add liv...
1388
1389
1390
1391
1392
  	kvm->evlist = kvm_live_event_list();
  	if (kvm->evlist == NULL) {
  		err = -1;
  		goto out;
  	}
1afe1d148   David Ahern   perf kvm: Add liv...
1393
1394
1395
1396
1397
1398
  	if (perf_evlist__create_maps(kvm->evlist, &kvm->opts.target) < 0)
  		usage_with_options(live_usage, live_options);
  
  	/*
  	 * perf session
  	 */
8ceb41d7e   Jiri Olsa   perf tools: Renam...
1399
  	kvm->session = perf_session__new(&data, false, &kvm->tool);
6ef81c55a   Mamatha Inamdar   perf session: Ret...
1400
1401
  	if (IS_ERR(kvm->session)) {
  		err = PTR_ERR(kvm->session);
1afe1d148   David Ahern   perf kvm: Add liv...
1402
1403
1404
1405
  		goto out;
  	}
  	kvm->session->evlist = kvm->evlist;
  	perf_session__set_id_hdr_size(kvm->session);
673d659f5   Alexander Yarygin   perf kvm stat liv...
1406
  	ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
a33fbd56e   Arnaldo Carvalho de Melo   perf machine: Sim...
1407
  	machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
03617c22e   Jiri Olsa   libperf: Add thre...
1408
  				    kvm->evlist->core.threads, false, 1);
1afe1d148   David Ahern   perf kvm: Add liv...
1409
1410
1411
1412
1413
1414
1415
  	err = kvm_live_open_events(kvm);
  	if (err)
  		goto out;
  
  	err = kvm_events_live_report(kvm);
  
  out:
e1446551e   Arnaldo Carvalho de Melo   perf session: Des...
1416
  	perf_session__delete(kvm->session);
1afe1d148   David Ahern   perf kvm: Add liv...
1417
  	kvm->session = NULL;
c12995a55   Jiri Olsa   perf evlist: Rena...
1418
  	evlist__delete(kvm->evlist);
1afe1d148   David Ahern   perf kvm: Add liv...
1419
1420
1421
  
  	return err;
  }
87419c9af   David Ahern   perf kvm: Disable...
1422
  #endif
1afe1d148   David Ahern   perf kvm: Add liv...
1423

bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
  static void print_kvm_stat_usage(void)
  {
  	printf("Usage: perf kvm stat <command>
  
  ");
  
  	printf("# Available commands:
  ");
  	printf("\trecord: record kvm events
  ");
  	printf("\treport: report statistical data of kvm events
  ");
1afe1d148   David Ahern   perf kvm: Add liv...
1436
1437
  	printf("\tlive:   live reporting of statistical data of kvm events
  ");
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1438
1439
1440
1441
1442
  
  	printf("
  Otherwise, it is the alias of 'perf stat':
  ");
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1443
  static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1444
  {
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1445
1446
1447
1448
1449
1450
  	struct perf_kvm_stat kvm = {
  		.file_name = file_name,
  
  		.trace_vcpu	= -1,
  		.report_event	= "vmexit",
  		.sort_key	= "sample",
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1451
  	};
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1452
1453
1454
1455
1456
1457
  	if (argc == 1) {
  		print_kvm_stat_usage();
  		goto perf_stat;
  	}
  
  	if (!strncmp(argv[1], "rec", 3))
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1458
  		return kvm_events_record(&kvm, argc - 1, argv + 1);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1459
1460
  
  	if (!strncmp(argv[1], "rep", 3))
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1461
  		return kvm_events_report(&kvm, argc - 1 , argv + 1);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1462

87419c9af   David Ahern   perf kvm: Disable...
1463
  #ifdef HAVE_TIMERFD_SUPPORT
1afe1d148   David Ahern   perf kvm: Add liv...
1464
1465
  	if (!strncmp(argv[1], "live", 4))
  		return kvm_events_live(&kvm, argc - 1 , argv + 1);
87419c9af   David Ahern   perf kvm: Disable...
1466
  #endif
1afe1d148   David Ahern   perf kvm: Add liv...
1467

bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1468
  perf_stat:
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
1469
  	return cmd_stat(argc, argv);
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1470
  }
da50ad697   Alexander Yarygin   perf kvm: Introdu...
1471
  #endif /* HAVE_KVM_STAT_SUPPORT */
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1472

124eb5f82   Anju T Sudhakar   perf kvm: Add arc...
1473
1474
1475
1476
1477
  int __weak kvm_add_default_arch_event(int *argc __maybe_unused,
  					const char **argv __maybe_unused)
  {
  	return 0;
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1478
  static int __cmd_record(const char *file_name, int argc, const char **argv)
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1479
  {
124eb5f82   Anju T Sudhakar   perf kvm: Add arc...
1480
  	int rec_argc, i = 0, j, ret;
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1481
  	const char **rec_argv;
124eb5f82   Anju T Sudhakar   perf kvm: Add arc...
1482
1483
1484
  	ret = kvm_add_default_arch_event(&argc, argv);
  	if (ret)
  		return -EINVAL;
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1485
1486
1487
1488
  	rec_argc = argc + 2;
  	rec_argv = calloc(rec_argc + 1, sizeof(char *));
  	rec_argv[i++] = strdup("record");
  	rec_argv[i++] = strdup("-o");
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1489
  	rec_argv[i++] = strdup(file_name);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1490
1491
1492
1493
  	for (j = 1; j < argc; j++, i++)
  		rec_argv[i] = argv[j];
  
  	BUG_ON(i != rec_argc);
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
1494
  	return cmd_record(i, rec_argv);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1495
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1496
  static int __cmd_report(const char *file_name, int argc, const char **argv)
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1497
1498
1499
1500
1501
1502
1503
1504
  {
  	int rec_argc, i = 0, j;
  	const char **rec_argv;
  
  	rec_argc = argc + 2;
  	rec_argv = calloc(rec_argc + 1, sizeof(char *));
  	rec_argv[i++] = strdup("report");
  	rec_argv[i++] = strdup("-i");
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1505
  	rec_argv[i++] = strdup(file_name);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1506
1507
1508
1509
  	for (j = 1; j < argc; j++, i++)
  		rec_argv[i] = argv[j];
  
  	BUG_ON(i != rec_argc);
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
1510
  	return cmd_report(i, rec_argv);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1511
  }
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1512
1513
  static int
  __cmd_buildid_list(const char *file_name, int argc, const char **argv)
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1514
1515
1516
1517
1518
1519
1520
1521
  {
  	int rec_argc, i = 0, j;
  	const char **rec_argv;
  
  	rec_argc = argc + 2;
  	rec_argv = calloc(rec_argc + 1, sizeof(char *));
  	rec_argv[i++] = strdup("buildid-list");
  	rec_argv[i++] = strdup("-i");
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1522
  	rec_argv[i++] = strdup(file_name);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1523
1524
1525
1526
  	for (j = 1; j < argc; j++, i++)
  		rec_argv[i] = argv[j];
  
  	BUG_ON(i != rec_argc);
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
1527
  	return cmd_buildid_list(i, rec_argv);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1528
  }
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
1529
  int cmd_kvm(int argc, const char **argv)
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1530
  {
20914ce5b   Arnaldo Carvalho de Melo   perf kvm: Initial...
1531
  	const char *file_name = NULL;
de332ac40   David Ahern   perf kvm: Move gl...
1532
  	const struct option kvm_options[] = {
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1533
  		OPT_STRING('i', "input", &file_name, "file",
de332ac40   David Ahern   perf kvm: Move gl...
1534
  			   "Input file name"),
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1535
  		OPT_STRING('o', "output", &file_name, "file",
de332ac40   David Ahern   perf kvm: Move gl...
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
  			   "Output file name"),
  		OPT_BOOLEAN(0, "guest", &perf_guest,
  			    "Collect guest os data"),
  		OPT_BOOLEAN(0, "host", &perf_host,
  			    "Collect host os data"),
  		OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
  			   "guest mount directory under which every guest os"
  			   " instance has a subdir"),
  		OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
  			   "file", "file saving guest os vmlinux"),
  		OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
  			   "file", "file saving guest os /proc/kallsyms"),
  		OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
  			   "file", "file saving guest os /proc/modules"),
100b90735   Dongsheng Yang   perf kvm: Introdu...
1550
1551
  		OPT_INCR('v', "verbose", &verbose,
  			    "be more verbose (show counter open errors, etc)"),
de332ac40   David Ahern   perf kvm: Move gl...
1552
1553
  		OPT_END()
  	};
09a71b97c   Ramkumar Ramachandra   perf kvm: introdu...
1554
1555
1556
  	const char *const kvm_subcommands[] = { "top", "record", "report", "diff",
  						"buildid-list", "stat", NULL };
  	const char *kvm_usage[] = { NULL, NULL };
de332ac40   David Ahern   perf kvm: Move gl...
1557

1aed26717   Joerg Roedel   perf kvm: Do gues...
1558
1559
  	perf_host  = 0;
  	perf_guest = 1;
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1560

09a71b97c   Ramkumar Ramachandra   perf kvm: introdu...
1561
1562
  	argc = parse_options_subcommand(argc, argv, kvm_options, kvm_subcommands, kvm_usage,
  					PARSE_OPT_STOP_AT_NON_OPTION);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1563
1564
1565
1566
1567
  	if (!argc)
  		usage_with_options(kvm_usage, kvm_options);
  
  	if (!perf_host)
  		perf_guest = 1;
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1568
  	if (!file_name) {
e1a2b174d   Dongsheng Yang   perf kvm: Move co...
1569
  		file_name = get_filename_for_perf_kvm();
de332ac40   David Ahern   perf kvm: Move gl...
1570

3786063a3   Xiao Guangrong   perf kvm: Rename ...
1571
  		if (!file_name) {
de332ac40   David Ahern   perf kvm: Move gl...
1572
1573
1574
1575
  			pr_err("Failed to allocate memory for filename
  ");
  			return -ENOMEM;
  		}
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1576
1577
1578
  	}
  
  	if (!strncmp(argv[0], "rec", 3))
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1579
  		return __cmd_record(file_name, argc, argv);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1580
  	else if (!strncmp(argv[0], "rep", 3))
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1581
  		return __cmd_report(file_name, argc, argv);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1582
  	else if (!strncmp(argv[0], "diff", 4))
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
1583
  		return cmd_diff(argc, argv);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1584
  	else if (!strncmp(argv[0], "top", 3))
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
1585
  		return cmd_top(argc, argv);
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1586
  	else if (!strncmp(argv[0], "buildid-list", 12))
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1587
  		return __cmd_buildid_list(file_name, argc, argv);
da50ad697   Alexander Yarygin   perf kvm: Introdu...
1588
  #ifdef HAVE_KVM_STAT_SUPPORT
bcf6edcd6   Xiao Guangrong   perf kvm: Events ...
1589
  	else if (!strncmp(argv[0], "stat", 4))
3786063a3   Xiao Guangrong   perf kvm: Rename ...
1590
  		return kvm_cmd_stat(file_name, argc, argv);
7321090f6   Xiao Guangrong   perf kvm: Fix bui...
1591
  #endif
a1645ce12   Zhang, Yanmin   perf: 'perf kvm' ...
1592
1593
1594
1595
1596
  	else
  		usage_with_options(kvm_usage, kvm_options);
  
  	return 0;
  }