All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] perf kvm: Add live mode for analyzing events
@ 2012-10-08 17:17 David Ahern
  2012-10-08 17:17 ` [PATCH 01/12] perf evlist: restore some methods removed in an earlier cleanup David Ahern
                   ` (11 more replies)
  0 siblings, 12 replies; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

perf kvm stat currently requires back to back record and report
commands to see stats. e.g.,

  perf kvm stat record -p $pid -- sleep 1
  perf kvm stat report

This is rather inconvenvient for on box monitoring of a VM. This
patch introduces a 'live' mode that in effect combines the record
plus report into one command. e.g., to monitor a single VM:
 
  perf kvm stat live -p $pid

Same stats options for the record+report path work with the live mode.
Display rate defaults to 1 and can be changed using the -d option.

The command works fine for low event rates, but as the number of events
increases (e.g., building a kernel in a 4-vcpu VM or nested virtualization)
the ordered samples code is failing. e.g,

  ...
  Total Samples:76309, Total events handled time:1121314.04us.

  Warning: Timestamp below last timeslice flush
  Failed to process event

This is on a 16-cpu server. For the kernel build in a 4 vcpu VM I am seeing on
the order of 50,000+ events per second and in the case of nested virtualization
(at least this one use case) I am seeing on the order of 100,000+ events per
second. Not surprising it's having problems keeping up.

I'll continue poking around the ordered samples code, but wanted to kick
this out in case someone has ideas or objections to the approach.

David Ahern (12):
  perf evlist: restore some methods removed in an earlier cleanup
  perf evlist: move tracepoint processing code to evlist.c
  perf evlist: add initialzation function for tracepoints
  perf session: export a few functions for event processing
  perf top: move CONSOLE_CLEAR to header file
  perf kvm: remove typecast in init_kvm_event_record
  perf kvm: handle realloc failures
  perf kvm: add braces around multi-line statements
  perf kvm: split out tracepoints from record args
  perf kvm: total count is a u64, print as so
  perf kvm: only process events for vcpus of interest
  perf kvm: add live mode

 tools/perf/builtin-kvm.c  |  717 ++++++++++++++++++++++++++++++++++++++++++---
 tools/perf/builtin-top.c  |    2 -
 tools/perf/util/evlist.c  |  120 ++++++++
 tools/perf/util/evlist.h  |   10 +
 tools/perf/util/header.c  |   39 ---
 tools/perf/util/session.c |   15 +-
 tools/perf/util/session.h |    9 +
 tools/perf/util/top.h     |    2 +
 8 files changed, 819 insertions(+), 95 deletions(-)

-- 
1.7.10.1


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 01/12] perf evlist: restore some methods removed in an earlier cleanup
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-08 17:17 ` [PATCH 02/12] perf evlist: move tracepoint processing code to evlist.c David Ahern
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

e60fc847 removed the perf_evlist__add_tracepoints and helpers, but
they are useful for kvm's upcoming live mode.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/util/evlist.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/evlist.h |    3 +++
 2 files changed, 57 insertions(+)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a41dc4a..a409b25 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -189,6 +189,60 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
 	return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
 }
 
+static int trace_event__id(const char *evname)
+{
+	char *filename, *colon;
+	int err = -1, fd;
+
+	if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
+		return -1;
+
+	colon = strrchr(filename, ':');
+	if (colon != NULL)
+		*colon = '/';
+
+	fd = open(filename, O_RDONLY);
+	if (fd >= 0) {
+		char id[16];
+		if (read(fd, id, sizeof(id)) > 0)
+			err = atoi(id);
+		close(fd);
+	}
+
+	free(filename);
+	return err;
+}
+
+int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
+				 const char * const tracepoints[],
+				 size_t nr_tracepoints)
+{
+	int err;
+	size_t i;
+	struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
+
+	if (attrs == NULL)
+		return -1;
+
+	for (i = 0; i < nr_tracepoints; i++) {
+		err = trace_event__id(tracepoints[i]);
+
+		if (err < 0)
+			goto out_free_attrs;
+
+		attrs[i].type	       = PERF_TYPE_TRACEPOINT;
+		attrs[i].config	       = err;
+		attrs[i].sample_type   = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
+					  PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
+		attrs[i].sample_period = 1;
+	}
+
+	err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
+out_free_attrs:
+	free(attrs);
+	return err;
+}
+
 struct perf_evsel *
 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
 {
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 56003f7..be85147 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -53,6 +53,9 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
 int perf_evlist__add_default(struct perf_evlist *evlist);
 int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
 				     struct perf_event_attr *attrs, size_t nr_attrs);
+int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
+				 const char * const tracepoints[],
+				 size_t nr_tracepoints);
 
 #define perf_evlist__add_default_attrs(evlist, array) \
 	__perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 02/12] perf evlist: move tracepoint processing code to evlist.c
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
  2012-10-08 17:17 ` [PATCH 01/12] perf evlist: restore some methods removed in an earlier cleanup David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-08 17:17 ` [PATCH 03/12] perf evlist: add initialzation function for tracepoints David Ahern
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

Code move only; no functional changes.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/util/evlist.c  |   39 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/evlist.h  |    4 ++++
 tools/perf/util/header.c  |   39 ---------------------------------------
 tools/perf/util/session.c |    1 -
 4 files changed, 43 insertions(+), 40 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a409b25..7fff06f 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -189,6 +189,45 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
 	return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
 }
 
+static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
+						struct pevent *pevent)
+{
+	struct event_format *event;
+	char bf[128];
+
+	/* already prepared */
+	if (evsel->tp_format)
+		return 0;
+
+	event = pevent_find_event(pevent, evsel->attr.config);
+	if (event == NULL)
+		return -1;
+
+	if (!evsel->name) {
+		snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
+		evsel->name = strdup(bf);
+		if (evsel->name == NULL)
+			return -1;
+	}
+
+	evsel->tp_format = event;
+	return 0;
+}
+
+int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
+						  struct pevent *pevent)
+{
+	struct perf_evsel *pos;
+
+	list_for_each_entry(pos, &evlist->entries, node) {
+		if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
+		    perf_evsel__prepare_tracepoint_event(pos, pevent))
+			return -1;
+	}
+
+	return 0;
+}
+
 static int trace_event__id(const char *evname)
 {
 	char *filename, *colon;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index be85147..9959954 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -5,6 +5,7 @@
 #include <stdio.h>
 #include "../perf.h"
 #include "event.h"
+#include "event-parse.h"
 #include "evsel.h"
 #include "util.h"
 #include <unistd.h>
@@ -53,6 +54,9 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
 int perf_evlist__add_default(struct perf_evlist *evlist);
 int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
 				     struct perf_event_attr *attrs, size_t nr_attrs);
+int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
+					   struct pevent *pevent);
+
 int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
 				 const char * const tracepoints[],
 				 size_t nr_tracepoints);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 7daad23..42f8ec9 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2553,45 +2553,6 @@ static int read_attr(int fd, struct perf_header *ph,
 	return ret <= 0 ? -1 : 0;
 }
 
-static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
-						struct pevent *pevent)
-{
-	struct event_format *event;
-	char bf[128];
-
-	/* already prepared */
-	if (evsel->tp_format)
-		return 0;
-
-	event = pevent_find_event(pevent, evsel->attr.config);
-	if (event == NULL)
-		return -1;
-
-	if (!evsel->name) {
-		snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
-		evsel->name = strdup(bf);
-		if (evsel->name == NULL)
-			return -1;
-	}
-
-	evsel->tp_format = event;
-	return 0;
-}
-
-static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
-						  struct pevent *pevent)
-{
-	struct perf_evsel *pos;
-
-	list_for_each_entry(pos, &evlist->entries, node) {
-		if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
-		    perf_evsel__prepare_tracepoint_event(pos, pevent))
-			return -1;
-	}
-
-	return 0;
-}
-
 int perf_session__read_header(struct perf_session *session, int fd)
 {
 	struct perf_header *header = &session->header;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 15abe40..23d2ea3 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,7 +14,6 @@
 #include "sort.h"
 #include "util.h"
 #include "cpumap.h"
-#include "event-parse.h"
 #include "perf_regs.h"
 #include "unwind.h"
 #include "vdso.h"
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 03/12] perf evlist: add initialzation function for tracepoints
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
  2012-10-08 17:17 ` [PATCH 01/12] perf evlist: restore some methods removed in an earlier cleanup David Ahern
  2012-10-08 17:17 ` [PATCH 02/12] perf evlist: move tracepoint processing code to evlist.c David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-08 17:17 ` [PATCH 04/12] perf session: export a few functions for event processing David Ahern
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

Handles initializations typically done as part of processing the file
header and HEADER_TRACING_DATA event.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/util/evlist.c |   27 +++++++++++++++++++++++++++
 tools/perf/util/evlist.h |    3 +++
 2 files changed, 30 insertions(+)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 7fff06f..d77135b 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -14,6 +14,7 @@
 #include "target.h"
 #include "evlist.h"
 #include "evsel.h"
+#include "trace-event.h"
 #include <unistd.h>
 
 #include "parse-events.h"
@@ -228,6 +229,32 @@ int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
 	return 0;
 }
 
+int perf_evlist__trace_init(struct perf_evlist *evlist,
+			    struct perf_session *session)
+{
+	struct tracing_data *tdata;
+	char temp_file[] = "/tmp/perf-XXXXXXXX";
+	int fd;
+
+	fd = mkstemp(temp_file);
+	if (fd < 0) {
+		pr_err("mkstemp failed\n");
+		return -1;
+	}
+	unlink(temp_file);
+
+	tdata = tracing_data_get(&evlist->entries, fd, false);
+	if (!tdata)
+		return -1;
+
+	lseek(fd, 0, SEEK_SET);
+	(void) trace_report(fd, &session->pevent, false);
+	tracing_data_put(tdata);
+
+	return perf_evlist__prepare_tracepoint_events(evlist, session->pevent);
+}
+
+
 static int trace_event__id(const char *evname)
 {
 	char *filename, *colon;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 9959954..e375a18 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -8,6 +8,7 @@
 #include "event-parse.h"
 #include "evsel.h"
 #include "util.h"
+#include "session.h"
 #include <unistd.h>
 
 struct pollfd;
@@ -60,6 +61,8 @@ int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
 int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
 				 const char * const tracepoints[],
 				 size_t nr_tracepoints);
+int perf_evlist__trace_init(struct perf_evlist *evlist,
+			    struct perf_session *session);
 
 #define perf_evlist__add_default_attrs(evlist, array) \
 	__perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 04/12] perf session: export a few functions for event processing
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
                   ` (2 preceding siblings ...)
  2012-10-08 17:17 ` [PATCH 03/12] perf evlist: add initialzation function for tracepoints David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-08 17:17 ` [PATCH 05/12] perf top: move CONSOLE_CLEAR to header file David Ahern
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

Allows kvm live mode to reuse the event processing and ordered samples
processing used by the perf-report path.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/util/session.c |   14 +++++++-------
 tools/perf/util/session.h |    9 +++++++++
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 23d2ea3..576ab8b 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -456,7 +456,7 @@ static int process_finished_round(struct perf_tool *tool,
 				  union perf_event *event,
 				  struct perf_session *session);
 
-static void perf_tool__fill_defaults(struct perf_tool *tool)
+void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
 		tool->sample = process_event_sample_stub;
@@ -702,8 +702,8 @@ static int perf_session_deliver_event(struct perf_session *session,
 				      struct perf_tool *tool,
 				      u64 file_offset);
 
-static int flush_sample_queue(struct perf_session *s,
-			       struct perf_tool *tool)
+int flush_sample_queue(struct perf_session *s,
+		       struct perf_tool *tool)
 {
 	struct ordered_samples *os = &s->ordered_samples;
 	struct list_head *head = &os->samples;
@@ -1150,10 +1150,10 @@ static void event_swap(union perf_event *event, bool sample_id_all)
 		swap(event, sample_id_all);
 }
 
-static int perf_session__process_event(struct perf_session *session,
-				       union perf_event *event,
-				       struct perf_tool *tool,
-				       u64 file_offset)
+int perf_session__process_event(struct perf_session *session,
+				union perf_event *event,
+				struct perf_tool *tool,
+				u64 file_offset)
 {
 	struct perf_sample sample;
 	int ret;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index aab414f..3fb5049 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -63,6 +63,15 @@ int __perf_session__process_events(struct perf_session *self,
 int perf_session__process_events(struct perf_session *self,
 				 struct perf_tool *tool);
 
+int perf_session__process_event(struct perf_session *session,
+				union perf_event *event,
+				struct perf_tool *tool,
+				u64 file_offset);
+
+int flush_sample_queue(struct perf_session *s, struct perf_tool *tool);
+
+void perf_tool__fill_defaults(struct perf_tool *tool);
+
 int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
 				    struct thread *thread,
 				    struct ip_callchain *chain,
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 05/12] perf top: move CONSOLE_CLEAR to header file
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
                   ` (3 preceding siblings ...)
  2012-10-08 17:17 ` [PATCH 04/12] perf session: export a few functions for event processing David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-08 17:17 ` [PATCH 06/12] perf kvm: remove typecast in init_kvm_event_record David Ahern
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel; +Cc: mingo, peterz, fweisbec, David Ahern

For use with kvm-live mode.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 tools/perf/builtin-top.c |    2 --
 tools/perf/util/top.h    |    2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index fb9da71..a053812 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -263,8 +263,6 @@ out_unlock:
 	pthread_mutex_unlock(&notes->lock);
 }
 
-static const char		CONSOLE_CLEAR[] = "^[[H^[[2J";
-
 static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
 						     struct addr_location *al,
 						     struct perf_sample *sample)
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 86ff1b1..8630570 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -47,6 +47,8 @@ struct perf_top {
 	const char	   *sym_filter;
 };
 
+#define CONSOLE_CLEAR "^[[H^[[2J"
+
 size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
 void perf_top__reset_sample_counters(struct perf_top *top);
 #endif /* __PERF_TOP_H */
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 06/12] perf kvm: remove typecast in init_kvm_event_record
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
                   ` (4 preceding siblings ...)
  2012-10-08 17:17 ` [PATCH 05/12] perf top: move CONSOLE_CLEAR to header file David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-09 17:38   ` [tip:perf/core] perf kvm: Remove " tip-bot for David Ahern
  2012-10-08 17:17 ` [PATCH 07/12] perf kvm: handle realloc failures David Ahern
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel
  Cc: mingo, peterz, fweisbec, David Ahern, Xiao Guangrong, Dong Hao

Not needed after changing i to unsigned int.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
---
 tools/perf/builtin-kvm.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 260abc5..a23db89 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -313,9 +313,9 @@ struct vcpu_event_record {
 
 static void init_kvm_event_record(struct perf_kvm *kvm)
 {
-	int i;
+	unsigned int i;
 
-	for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
+	for (i = 0; i < EVENTS_CACHE_SIZE; i++)
 		INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
 }
 
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 07/12] perf kvm: handle realloc failures
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
                   ` (5 preceding siblings ...)
  2012-10-08 17:17 ` [PATCH 06/12] perf kvm: remove typecast in init_kvm_event_record David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-08 20:19   ` Arnaldo Carvalho de Melo
  2012-10-08 17:17 ` [PATCH 08/12] perf kvm: add braces around multi-line statements David Ahern
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel
  Cc: mingo, peterz, fweisbec, David Ahern, Xiao Guangrong, Dong Hao

Save previous pointer and free on failure.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
---
 tools/perf/builtin-kvm.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index a23db89..af74a97 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -327,6 +327,7 @@ static int kvm_events_hash_fn(u64 key)
 static bool kvm_event_expand(struct kvm_event *event, int vcpu_id)
 {
 	int old_max_vcpu = event->max_vcpu;
+	void *prev;
 
 	if (vcpu_id < event->max_vcpu)
 		return true;
@@ -334,9 +335,11 @@ static bool kvm_event_expand(struct kvm_event *event, int vcpu_id)
 	while (event->max_vcpu <= vcpu_id)
 		event->max_vcpu += DEFAULT_VCPU_NUM;
 
+	prev = event->vcpu;
 	event->vcpu = realloc(event->vcpu,
 			      event->max_vcpu * sizeof(*event->vcpu));
 	if (!event->vcpu) {
+		free(prev);
 		pr_err("Not enough memory\n");
 		return false;
 	}
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 08/12] perf kvm: add braces around multi-line statements
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
                   ` (6 preceding siblings ...)
  2012-10-08 17:17 ` [PATCH 07/12] perf kvm: handle realloc failures David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-09 17:40   ` [tip:perf/core] perf kvm: Add " tip-bot for David Ahern
  2012-10-08 17:17 ` [PATCH 09/12] perf kvm: split out tracepoints from record args David Ahern
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel
  Cc: mingo, peterz, fweisbec, David Ahern, Xiao Guangrong, Dong Hao

Multi-line statements should have braces. Improves readability.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
---
 tools/perf/builtin-kvm.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index af74a97..43fd71c 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -372,9 +372,10 @@ static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
 	BUG_ON(key->key == INVALID_KEY);
 
 	head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
-	list_for_each_entry(event, head, hash_entry)
+	list_for_each_entry(event, head, hash_entry) {
 		if (event->key.key == key->key && event->key.info == key->info)
 			return event;
+	}
 
 	event = kvm_alloc_init_event(key);
 	if (!event)
@@ -599,13 +600,15 @@ static void sort_result(struct perf_kvm *kvm)
 	int vcpu = kvm->trace_vcpu;
 	struct kvm_event *event;
 
-	for (i = 0; i < EVENTS_CACHE_SIZE; i++)
-		list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry)
+	for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
+		list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry) {
 			if (event_is_valid(event, vcpu)) {
 				update_total_count(kvm, event);
 				insert_to_result(&kvm->result, event,
 						 kvm->compare, vcpu);
 			}
+		}
+	}
 }
 
 /* returns left most element of result, and erase it */
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 09/12] perf kvm: split out tracepoints from record args
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
                   ` (7 preceding siblings ...)
  2012-10-08 17:17 ` [PATCH 08/12] perf kvm: add braces around multi-line statements David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-17  8:19   ` Xiao Guangrong
  2012-10-08 17:17 ` [PATCH 10/12] perf kvm: total count is a u64, print as so David Ahern
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel
  Cc: mingo, peterz, fweisbec, David Ahern, Xiao Guangrong, Dong Hao

Needed by kvm live command. Make record_args a local while we are
messing with the args.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
---
 tools/perf/builtin-kvm.c |   30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 43fd71c..f6091d2 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -784,16 +784,11 @@ exit:
 	return ret;
 }
 
-static const char * const record_args[] = {
-	"record",
-	"-R",
-	"-f",
-	"-m", "1024",
-	"-c", "1",
-	"-e", "kvm:kvm_entry",
-	"-e", "kvm:kvm_exit",
-	"-e", "kvm:kvm_mmio",
-	"-e", "kvm:kvm_pio",
+static const char * const kvm_events_tp[] = {
+	"kvm:kvm_entry",
+	"kvm:kvm_exit",
+	"kvm:kvm_mmio",
+	"kvm:kvm_pio",
 };
 
 #define STRDUP_FAIL_EXIT(s)		\
@@ -808,8 +803,16 @@ static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
 {
 	unsigned int rec_argc, i, j;
 	const char **rec_argv;
+	const char * const record_args[] = {
+		"record",
+		"-R",
+		"-f",
+		"-m", "1024",
+		"-c", "1",
+	};
 
-	rec_argc = ARRAY_SIZE(record_args) + argc + 2;
+	rec_argc = ARRAY_SIZE(record_args) + argc + 2 +
+		   ARRAY_SIZE(kvm_events_tp);
 	rec_argv = calloc(rec_argc + 1, sizeof(char *));
 
 	if (rec_argv == NULL)
@@ -818,6 +821,11 @@ static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
 	for (i = 0; i < ARRAY_SIZE(record_args); i++)
 		rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
 
+	for (j = 0; j < ARRAY_SIZE(kvm_events_tp); j++) {
+		rec_argv[i++] = "-e";
+		rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp[j]);
+	}
+
 	rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
 	rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name);
 
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 10/12] perf kvm: total count is a u64, print as so
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
                   ` (8 preceding siblings ...)
  2012-10-08 17:17 ` [PATCH 09/12] perf kvm: split out tracepoints from record args David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-09 17:39   ` [tip:perf/core] perf kvm: Total " tip-bot for David Ahern
  2012-10-08 17:17 ` [PATCH 11/12] perf kvm: only process events for vcpus of interest David Ahern
  2012-10-08 17:17 ` [PATCH 12/12] perf kvm: add live mode David Ahern
  11 siblings, 1 reply; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel
  Cc: mingo, peterz, fweisbec, David Ahern, Xiao Guangrong, Dong Hao

remove cast and use proper type in format.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
---
 tools/perf/builtin-kvm.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index f6091d2..6412694 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -665,8 +665,8 @@ static void print_result(struct perf_kvm *kvm)
 		pr_info("\n");
 	}
 
-	pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
-		(unsigned long long)kvm->total_count, kvm->total_time / 1e3);
+	pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
+		kvm->total_count, kvm->total_time / 1e3);
 }
 
 static int process_sample_event(struct perf_tool *tool,
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 11/12] perf kvm: only process events for vcpus of interest
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
                   ` (9 preceding siblings ...)
  2012-10-08 17:17 ` [PATCH 10/12] perf kvm: total count is a u64, print as so David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-09 17:37   ` [tip:perf/core] perf kvm: Only " tip-bot for David Ahern
  2012-10-08 17:17 ` [PATCH 12/12] perf kvm: add live mode David Ahern
  11 siblings, 1 reply; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel
  Cc: mingo, peterz, fweisbec, David Ahern, Xiao Guangrong, Dong Hao

Minimizing processing overhead for each sample - which becomes important
for the upcoming live mode when it has to deal with 100+k events per
second.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
---
 tools/perf/builtin-kvm.c |   18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 6412694..dcbbcc7 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -420,7 +420,10 @@ static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event)
 static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
 			     u64 time_diff)
 {
-	kvm_update_event_stats(&event->total, time_diff);
+	if (vcpu_id == -1) {
+		kvm_update_event_stats(&event->total, time_diff);
+		return true;
+	}
 
 	if (!kvm_event_expand(event, vcpu_id))
 		return false;
@@ -436,6 +439,12 @@ static bool handle_end_event(struct perf_kvm *kvm,
 {
 	struct kvm_event *event;
 	u64 time_begin, time_diff;
+	int vcpu;
+
+	if (kvm->trace_vcpu == -1)
+		vcpu = -1;
+	else
+		vcpu = vcpu_record->vcpu_id;
 
 	event = vcpu_record->last_event;
 	time_begin = vcpu_record->start_time;
@@ -465,7 +474,7 @@ static bool handle_end_event(struct perf_kvm *kvm,
 	BUG_ON(timestamp < time_begin);
 
 	time_diff = timestamp - time_begin;
-	return update_kvm_event(event, vcpu_record->vcpu_id, time_diff);
+	return update_kvm_event(event, vcpu, time_diff);
 }
 
 static
@@ -502,6 +511,11 @@ static bool handle_kvm_event(struct perf_kvm *kvm,
 	if (!vcpu_record)
 		return true;
 
+	/* only process events for vcpus user cares about */
+	if ((kvm->trace_vcpu != -1) &&
+	    (kvm->trace_vcpu != vcpu_record->vcpu_id))
+		return true;
+
 	if (kvm->events_ops->is_begin_event(evsel, sample, &key))
 		return handle_begin_event(kvm, vcpu_record, &key, sample->time);
 
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 12/12] perf kvm: add live mode
  2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
                   ` (10 preceding siblings ...)
  2012-10-08 17:17 ` [PATCH 11/12] perf kvm: only process events for vcpus of interest David Ahern
@ 2012-10-08 17:17 ` David Ahern
  2012-10-08 20:35   ` Arnaldo Carvalho de Melo
  11 siblings, 1 reply; 26+ messages in thread
From: David Ahern @ 2012-10-08 17:17 UTC (permalink / raw)
  To: acme, linux-kernel
  Cc: mingo, peterz, fweisbec, David Ahern, Xiao Guangrong, Dong Hao

perf kvm stat currently requires back to back record and report
commands to see stats. e.g,.

  perf kvm stat record -p $pid -- sleep 1
  perf kvm stat report

This is rather inconvenvient for on box monitoring of a VM. This
patch introduces a 'live' mode that in effect combines the record
plus report into one command. e.g., to monitor a single VM:

  perf kvm stat live -p $pid

Same stats options for the record+report path work with the live mode.
Display rate defaults to 1 and can be changed using the -d option.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
---
 tools/perf/builtin-kvm.c |  649 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 623 insertions(+), 26 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index dcbbcc7..9dd1921 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -2,6 +2,7 @@
 #include "perf.h"
 
 #include "util/evsel.h"
+#include "util/evlist.h"
 #include "util/util.h"
 #include "util/cache.h"
 #include "util/symbol.h"
@@ -15,9 +16,12 @@
 #include "util/debugfs.h"
 #include "util/tool.h"
 #include "util/stat.h"
+#include "util/top.h"
 
 #include <sys/prctl.h>
+#include <sys/timerfd.h>
 
+#include <termios.h>
 #include <semaphore.h>
 #include <pthread.h>
 #include <math.h>
@@ -81,6 +85,8 @@ struct exit_reasons_table {
 
 struct perf_kvm {
 	struct perf_tool    tool;
+	struct perf_record_opts opts;
+	struct perf_evlist  *evlist;
 	struct perf_session *session;
 
 	const char *file_name;
@@ -95,10 +101,16 @@ struct perf_kvm {
 	struct kvm_events_ops *events_ops;
 	key_cmp_fun compare;
 	struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
+
 	u64 total_time;
 	u64 total_count;
+	u64 lost_events;
 
 	struct rb_root result;
+
+	int timerfd;
+	unsigned int display_time;
+	bool live;
 };
 
 
@@ -319,6 +331,23 @@ static void init_kvm_event_record(struct perf_kvm *kvm)
 		INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
 }
 
+static void clear_events_cache_stats(struct list_head *kvm_events_cache)
+{
+	struct list_head *head;
+	struct kvm_event *event;
+	unsigned int i;
+
+	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 */
+			memset(&event->total, 0, sizeof(event->total));
+			memset(event->vcpu, 0,
+			       event->max_vcpu * sizeof(*event->vcpu));
+		}
+	}
+}
+
 static int kvm_events_hash_fn(u64 key)
 {
 	return key & (EVENTS_CACHE_SIZE - 1);
@@ -471,7 +500,11 @@ static bool handle_end_event(struct perf_kvm *kvm,
 	vcpu_record->last_event = NULL;
 	vcpu_record->start_time = 0;
 
-	BUG_ON(timestamp < time_begin);
+	/* seems to happen once in a while during live mode */
+	if (timestamp < time_begin) {
+		pr_debug("End time before begin time; skipping event.\n");
+		return true;
+	}
 
 	time_diff = timestamp - time_begin;
 	return update_kvm_event(event, vcpu, time_diff);
@@ -637,24 +670,60 @@ static struct kvm_event *pop_from_result(struct rb_root *result)
 	return container_of(node, struct kvm_event, rb);
 }
 
-static void print_vcpu_info(int vcpu)
+static void print_vcpu_info(struct perf_kvm *kvm)
 {
+	int vcpu = kvm->trace_vcpu;
+
 	pr_info("Analyze events for ");
 
+	if (kvm->live) {
+		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 if (kvm->opts.target.tid)
+			pr_info("tid(s) %s, ", kvm->opts.target.tid);
+		else if (kvm->opts.target.cpu_list)
+			pr_info("host cpu(s) %s, ", kvm->opts.target.cpu_list);
+		else
+			pr_info("dazed and confused on what is monitored, ");
+	}
+
 	if (vcpu == -1)
 		pr_info("all VCPUs:\n\n");
 	else
 		pr_info("VCPU %d:\n\n", vcpu);
 }
 
+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;
+}
+
 static void print_result(struct perf_kvm *kvm)
 {
 	char decode[20];
 	struct kvm_event *event;
 	int vcpu = kvm->trace_vcpu;
 
+	if (kvm->live) {
+		puts(CONSOLE_CLEAR);
+		show_timeofday();
+	}
+
 	pr_info("\n\n");
-	print_vcpu_info(vcpu);
+	print_vcpu_info(kvm);
 	pr_info("%20s ", kvm->events_ops->name);
 	pr_info("%10s ", "Samples");
 	pr_info("%9s ", "Samples%");
@@ -681,6 +750,20 @@ static void print_result(struct perf_kvm *kvm)
 
 	pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
 		kvm->total_count, kvm->total_time / 1e3);
+
+	if (kvm->lost_events)
+		pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events);
+}
+
+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 *kvm = container_of(tool, struct perf_kvm, tool);
+
+	kvm->lost_events++;
+	return 0;
 }
 
 static int process_sample_event(struct perf_tool *tool,
@@ -704,10 +787,20 @@ static int process_sample_event(struct perf_tool *tool,
 	return 0;
 }
 
-static int get_cpu_isa(struct perf_session *session)
+static int cpu_isa_config(struct perf_kvm *kvm)
 {
-	char *cpuid = session->header.env.cpuid;
-	int isa;
+	char buf[64], *cpuid;
+	int err, isa;
+
+	if (kvm->live) {
+		err = get_cpuid(buf, sizeof(buf));
+		if (err != 0) {
+			pr_err("Failed to look up CPU type (Intel or AMD)\n");
+			return err;
+		}
+		cpuid = buf;
+	} else
+		cpuid = kvm->session->header.env.cpuid;
 
 	if (strstr(cpuid, "Intel"))
 		isa = 1;
@@ -715,10 +808,374 @@ static int get_cpu_isa(struct perf_session *session)
 		isa = 0;
 	else {
 		pr_err("CPU %s is not supported.\n", cpuid);
-		isa = -ENOTSUP;
+		return -ENOTSUP;
+	}
+
+	if (isa == 1) {
+		kvm->exit_reasons = vmx_exit_reasons;
+		kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
+		kvm->exit_reasons_isa = "VMX";
+	}
+
+	return 0;
+}
+
+static bool verify_vcpu(int vcpu)
+{
+	if (vcpu != -1 && vcpu < 0) {
+		pr_err("Invalid vcpu:%d.\n", vcpu);
+		return false;
+	}
+
+	return true;
+}
+
+#define PERF_KVM__MAX_EVENTS_PER_MMAP  1000
+
+static s64 perf_kvm__mmap_read_idx(struct perf_kvm *kvm, int idx)
+{
+	union perf_event *event;
+	s64 n = 0;
+	int err;
+
+	while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) {
+		err = perf_session__process_event(kvm->session, event,
+						  &kvm->tool, 0);
+		if (err) {
+			pr_err("Failed to process event\n");
+			return err;
+		}
+		n++;
+
+		/* limit events per mmap handled all at once */
+		if (n == PERF_KVM__MAX_EVENTS_PER_MMAP)
+			break;
+	}
+
+	return n;
+}
+
+static int perf_kvm__mmap_read(struct perf_kvm *kvm)
+{
+	int i, err, throttled = 0;
+	s64 n, ntotal = 0;
+
+	for (i = 0; i < kvm->evlist->nr_mmaps; i++) {
+		n = perf_kvm__mmap_read_idx(kvm, i);
+		if (n < 0)
+			return -1;
+		ntotal += n;
+		if (n == PERF_KVM__MAX_EVENTS_PER_MMAP)
+			throttled = 1;
+	}
+
+	/* flush queue after each round in which we processed events */
+	if (ntotal) {
+		err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session);
+		if (err) {
+			if (kvm->lost_events)
+				pr_info("\nLost events: %" PRIu64 "\n\n",
+					kvm->lost_events);
+			return err;
+		}
+	}
+
+	return throttled;
+}
+
+static volatile int done;
+
+static void sig_handler(int sig)
+{
+	if (sig == SIGINT)
+		done = 1;
+}
+
+static int perf_kvm__timerfd_create(struct perf_kvm *kvm)
+{
+	struct itimerspec new_value;
+	struct timespec now;
+	int rc = -1;
+
+	kvm->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
+	if (kvm->timerfd < 0) {
+		pr_err("timerfd_create failed\n");
+		goto out;
+	}
+
+	if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) {
+		pr_err("clock_gettime failed: %d\n", errno);
+		close(kvm->timerfd);
+		goto out;
+	}
+
+	new_value.it_value.tv_sec = now.tv_sec + kvm->display_time;
+	new_value.it_value.tv_nsec = now.tv_nsec;
+	new_value.it_interval.tv_sec = kvm->display_time;
+	new_value.it_interval.tv_nsec = 0;
+
+	if (timerfd_settime(kvm->timerfd, TFD_TIMER_ABSTIME,
+			    &new_value, NULL) != 0) {
+		pr_err("timerfd_settime failed: %d\n", errno);
+		close(kvm->timerfd);
+		goto out;
+	}
+
+	rc = 0;
+out:
+	return rc;
+}
+
+static int perf_kvm__handle_timerfd(struct perf_kvm *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\n", errno);
+		return -1;
+	}
+
+	if (rc != sizeof(uint64_t)) {
+		pr_err("Error reading timer fd - invalid size returned\n");
+		return -1;
+	}
+
+	if (c != 1)
+		pr_debug("Missed timer beats: %" PRIu64 "\n", 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\n", fd);
+		return -1;
+	}
+
+	if (fcntl(fd, F_SETFL, arg | O_NONBLOCK) < 0) {
+		pr_err("Failed to set non-block option on fd %d\n", fd);
+		return -1;
 	}
 
-	return isa;
+	return 0;
+}
+
+static
+int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save)
+{
+	int c;
+
+	tcsetattr(0, TCSANOW, tc_now);
+	c = getc(stdin);
+	tcsetattr(0, TCSAFLUSH, tc_save);
+
+	if (c == 'q')
+		return 1;
+
+	/* TO-DO: add hook for 'd' to change display rate
+	 *        needs an update to timerfd too
+	 */
+
+	return 0;
+}
+
+static int kvm_events_live_report(struct perf_kvm *kvm)
+{
+	struct pollfd *pollfds = NULL;
+	int nr_fds, ret, err = -EINVAL;
+	struct termios tc, save;
+
+	/* 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;
+	}
+
+	init_kvm_event_record(kvm);
+
+
+	tcgetattr(0, &save);
+	tc = save;
+	tc.c_lflag &= ~(ICANON | ECHO);
+	tc.c_cc[VMIN] = 0;
+	tc.c_cc[VTIME] = 0;
+
+	signal(SIGINT, sig_handler);
+
+
+	/* copy pollfds -- need to add timerfd and stdin */
+	nr_fds = kvm->evlist->nr_fds;
+	pollfds = zalloc(sizeof(struct pollfd) * (nr_fds + 2));
+	if (!pollfds) {
+		err = -ENOMEM;
+		goto out;
+	}
+	memcpy(pollfds, kvm->evlist->pollfd,
+		sizeof(struct pollfd) * kvm->evlist->nr_fds);
+
+	/* add timer fd */
+	if (perf_kvm__timerfd_create(kvm) < 0) {
+		err = -1;
+		goto out;
+	}
+
+	pollfds[nr_fds].fd = kvm->timerfd;
+	pollfds[nr_fds].events = POLLIN;
+	nr_fds++;
+
+	pollfds[nr_fds].fd = fileno(stdin);
+	pollfds[nr_fds].events = POLLIN;
+	nr_fds++;
+	if (fd_set_nonblock(fileno(stdin)) != 0)
+		goto out;
+
+	/* everything is good - enable the events and process */
+	perf_evlist__enable(kvm->evlist);
+
+	while (!done) {
+		int rc;
+
+		rc = perf_kvm__mmap_read(kvm);
+		if (rc < 0)
+			break;
+
+		err = perf_kvm__handle_timerfd(kvm);
+		if (err)
+			goto out;
+
+		done = perf_kvm__handle_stdin(&tc, &save);
+
+		if (!rc && !done)
+			err = poll(pollfds, nr_fds, 100);
+	}
+
+	perf_evlist__disable(kvm->evlist);
+
+	if (err == 0) {
+		sort_result(kvm);
+		print_result(kvm);
+	}
+
+out:
+	if (kvm->timerfd >= 0)
+		close(kvm->timerfd);
+
+	if (pollfds)
+		free(pollfds);
+
+	return err;
+}
+
+
+/* TO-DO: how to merge this with perf-stat */
+static int perf_kvm__open_counters(struct perf_kvm *kvm)
+{
+	struct perf_evsel *pos;
+	struct perf_evlist *evlist = kvm->evlist;
+	int err = 0;
+
+	/*
+	 * Note: exclude_{guest,host} do not apply here.
+	 *       This command processes KVM tracepoints form host only
+	 */
+	list_for_each_entry(pos, &evlist->entries, node) {
+		struct perf_event_attr *attr = &pos->attr;
+
+		attr->sample_type = 0;
+		attr->read_format = 0;
+
+		attr->sample_type |= PERF_SAMPLE_TID;
+		attr->sample_type |= PERF_SAMPLE_TIME;
+		attr->sample_type |= PERF_SAMPLE_CPU;
+		attr->sample_type |= PERF_SAMPLE_RAW;
+
+		if (evlist->nr_entries > 1) {
+			attr->sample_type |= PERF_SAMPLE_ID;
+			attr->read_format |= PERF_FORMAT_ID;
+		}
+
+		attr->sample_id_all = kvm->opts.sample_id_all_missing ? 0 : 1;
+		attr->sample_period = 1;
+		attr->comm = !pos->idx;
+
+		attr->watermark = 0;
+		attr->wakeup_events = 100;
+
+		/* will enable all once we are ready */
+		attr->disabled = 1;
+
+retry_sample_id:
+		attr->sample_id_all = kvm->opts.sample_id_all_missing ? 0 : 1;
+		if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
+			err = errno;
+
+			if (err == EPERM || err == EACCES) {
+				ui__error_paranoid();
+				goto out_err;
+			} else if ((err == EINVAL) &&
+				   !kvm->opts.sample_id_all_missing) {
+				/*
+				 * Old kernel, no attr->sample_id_type_all field
+				 */
+				kvm->opts.sample_id_all_missing = true;
+				goto retry_sample_id;
+			}
+
+			/*
+			 * should never happen since the event is validated
+			 * before adding to evlist.
+			 */
+			if (err == ENOENT) {
+				ui__error("The %s event is not supported.\n",
+					  perf_evsel__name(pos));
+				goto out_err;
+			} else if (err == EMFILE) {
+				ui__error("Too many events need to be opened.\n");
+				goto out_err;
+			}
+
+			ui__error("The sys_perf_event_open() syscall "
+				  "returned with %d (%s).  /bin/dmesg "
+				  "may provide additional information.\n",
+				  err, strerror(err));
+			goto out_err;
+		}
+	}
+
+	if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
+		ui__error("Failed to mmap with %d (%s)\n",
+			  errno, strerror(errno));
+		goto out_err;
+	}
+
+out_err:
+	return err;
 }
 
 static int read_events(struct perf_kvm *kvm)
@@ -746,30 +1203,13 @@ static int read_events(struct perf_kvm *kvm)
 	 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
 	 * traced in the old kernel.
 	 */
-	ret = get_cpu_isa(kvm->session);
-
+	ret = cpu_isa_config(kvm);
 	if (ret < 0)
 		return ret;
 
-	if (ret == 1) {
-		kvm->exit_reasons = vmx_exit_reasons;
-		kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
-		kvm->exit_reasons_isa = "VMX";
-	}
-
 	return perf_session__process_events(kvm->session, &kvm->tool);
 }
 
-static bool verify_vcpu(int vcpu)
-{
-	if (vcpu != -1 && vcpu < 0) {
-		pr_err("Invalid vcpu:%d.\n", vcpu);
-		return false;
-	}
-
-	return true;
-}
-
 static int kvm_events_report_vcpu(struct perf_kvm *kvm)
 {
 	int ret = -EINVAL;
@@ -881,6 +1321,159 @@ static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv)
 	return kvm_events_report_vcpu(kvm);
 }
 
+static int kvm_events_live(struct perf_kvm *kvm, int argc, const char **argv)
+{
+	struct perf_session *session = NULL;
+	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"),
+		OPT_STRING('t', "tid", &kvm->opts.target.tid, "tid",
+			"record events on existing thread id"),
+		OPT_STRING('C', "cpu", &kvm->opts.target.cpu_list, "cpu",
+			"list of host cpus to monitor"),
+		OPT_UINTEGER('m', "mmap-pages", &kvm->opts.mmap_pages,
+			"number of mmap data pages"),
+		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",
+			"event for reporting: vmexit, mmio, ioport"),
+		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)"),
+		OPT_END()
+	};
+	const char * const live_usage[] = {
+		"perf kvm stat live [<options>]",
+		NULL
+	};
+
+
+	/* 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;
+	kvm->tool.ordered_samples = true;
+	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 = true;
+
+	kvm->evlist = perf_evlist__new(NULL, NULL);
+	if (kvm->evlist == NULL)
+		return -ENOMEM;
+
+	symbol__init();
+	disable_buildid_cache();
+
+	if (argc) {
+		argc = parse_options(argc, argv, live_options,
+				     live_usage, 0);
+		if (argc)
+			usage_with_options(live_usage, live_options);
+	}
+
+	use_browser = 0;
+	setup_browser(false);
+
+	/*
+	 * target related setups
+	 */
+	if (perf_target__none(&kvm->opts.target))
+		kvm->opts.target.system_wide = true;
+
+	err = perf_target__validate(&kvm->opts.target);
+	if (err) {
+		perf_target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ);
+		ui__warning("%s", errbuf);
+	}
+
+	err = perf_target__parse_uid(&kvm->opts.target);
+	if (err) {
+		int saved_errno = errno;
+
+		perf_target__strerror(&kvm->opts.target, err,
+				      errbuf, BUFSIZ);
+		ui__error("%s", errbuf);
+
+		err = -saved_errno;
+		goto out;
+	}
+
+	/*
+	 * generate the event list
+	 */
+	err = perf_evlist__add_tracepoints(kvm->evlist,
+					   kvm_events_tp,
+					   ARRAY_SIZE(kvm_events_tp));
+	if (err != 0)
+		goto out;
+
+	symbol_conf.nr_events = kvm->evlist->nr_entries;
+
+	if (perf_evlist__create_maps(kvm->evlist, &kvm->opts.target) < 0)
+		usage_with_options(live_usage, live_options);
+
+	/*
+	 * perf session
+	 */
+	session = perf_session__new(NULL, O_WRONLY, false, false, &kvm->tool);
+	if (session == NULL) {
+		err = -ENOMEM;
+		goto out;
+	}
+	session->evlist = kvm->evlist;
+	kvm->session = session;
+	perf_session__set_id_hdr_size(session);
+
+
+	/*
+	 * need to get pevent initialized
+	 */
+	err = perf_evlist__trace_init(kvm->evlist, session);
+	if (err != 0)
+		goto out;
+
+	if (perf_target__has_task(&kvm->opts.target))
+		perf_event__synthesize_thread_map(&kvm->tool,
+						  kvm->evlist->threads,
+						  perf_event__process,
+						  &session->host_machine);
+	else
+		perf_event__synthesize_threads(&kvm->tool, perf_event__process,
+					       &session->host_machine);
+
+
+	err = perf_kvm__open_counters(kvm);
+	if (err != 0)
+		goto out;
+
+	err = kvm_events_live_report(kvm);
+
+out:
+	exit_browser(0);
+
+	if (session)
+		perf_session__delete(session);
+	kvm->session = NULL;
+	perf_evlist__delete_maps(kvm->evlist);
+	perf_evlist__delete(kvm->evlist);
+
+	return err;
+}
+
 static void print_kvm_stat_usage(void)
 {
 	printf("Usage: perf kvm stat <command>\n\n");
@@ -888,6 +1481,7 @@ static void print_kvm_stat_usage(void)
 	printf("# Available commands:\n");
 	printf("\trecord: record kvm events\n");
 	printf("\treport: report statistical data of kvm events\n");
+	printf("\tlive:   live reporting of statistical data of kvm events\n");
 
 	printf("\nOtherwise, it is the alias of 'perf stat':\n");
 }
@@ -905,6 +1499,9 @@ static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv)
 	if (!strncmp(argv[1], "rep", 3))
 		return kvm_events_report(kvm, argc - 1 , argv + 1);
 
+	if (!strncmp(argv[1], "live", 4))
+		return kvm_events_live(kvm, argc - 1 , argv + 1);
+
 perf_stat:
 	return cmd_stat(argc, argv, NULL);
 }
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 07/12] perf kvm: handle realloc failures
  2012-10-08 17:17 ` [PATCH 07/12] perf kvm: handle realloc failures David Ahern
@ 2012-10-08 20:19   ` Arnaldo Carvalho de Melo
  2012-10-08 20:34     ` David Ahern
  0 siblings, 1 reply; 26+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-10-08 20:19 UTC (permalink / raw)
  To: David Ahern
  Cc: linux-kernel, mingo, peterz, fweisbec, Xiao Guangrong, Dong Hao

Em Mon, Oct 08, 2012 at 11:17:31AM -0600, David Ahern escreveu:
> Save previous pointer and free on failure.

<SNIP>
 
> +	prev = event->vcpu;
>  	event->vcpu = realloc(event->vcpu,
>  			      event->max_vcpu * sizeof(*event->vcpu));
>  	if (!event->vcpu) {
> +		free(prev);
>  		pr_err("Not enough memory\n");

Unfamiliar way of doing it, usually we do it like:

  	vcpu = realloc(event->vcpu, event->max_vcpu * sizeof(*event->vcpu));

	if (!vcpu) {
  		pr_err("Not enough memory\n");
		return -1;
	}

	event->vcpu = vcpu;

I.e. we don't trow away the old value of event->vcpu.

- Arnaldo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 07/12] perf kvm: handle realloc failures
  2012-10-08 20:19   ` Arnaldo Carvalho de Melo
@ 2012-10-08 20:34     ` David Ahern
  2012-10-08 21:38       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 26+ messages in thread
From: David Ahern @ 2012-10-08 20:34 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, mingo, peterz, fweisbec, Xiao Guangrong, Dong Hao

On 10/8/12 2:19 PM, Arnaldo Carvalho de Melo wrote:
> Em Mon, Oct 08, 2012 at 11:17:31AM -0600, David Ahern escreveu:
>> Save previous pointer and free on failure.
>
> <SNIP>
>
>> +	prev = event->vcpu;
>>   	event->vcpu = realloc(event->vcpu,
>>   			      event->max_vcpu * sizeof(*event->vcpu));
>>   	if (!event->vcpu) {
>> +		free(prev);
>>   		pr_err("Not enough memory\n");
>
> Unfamiliar way of doing it, usually we do it like:
>
>    	vcpu = realloc(event->vcpu, event->max_vcpu * sizeof(*event->vcpu));
>
> 	if (!vcpu) {
>    		pr_err("Not enough memory\n");
> 		return -1;
> 	}
>
> 	event->vcpu = vcpu;
>
> I.e. we don't trow away the old value of event->vcpu.

right. Command is going to exit on a failure, so leaving the old value 
does not have any impact. I can leave the old if you want it for 
consistency.

David


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 12/12] perf kvm: add live mode
  2012-10-08 17:17 ` [PATCH 12/12] perf kvm: add live mode David Ahern
@ 2012-10-08 20:35   ` Arnaldo Carvalho de Melo
  2012-10-08 20:54     ` David Ahern
  0 siblings, 1 reply; 26+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-10-08 20:35 UTC (permalink / raw)
  To: David Ahern
  Cc: linux-kernel, mingo, peterz, fweisbec, Xiao Guangrong, Dong Hao

Em Mon, Oct 08, 2012 at 11:17:36AM -0600, David Ahern escreveu:
> perf kvm stat currently requires back to back record and report
> commands to see stats. e.g,.
> 
>   perf kvm stat record -p $pid -- sleep 1
>   perf kvm stat report
> 
> This is rather inconvenvient for on box monitoring of a VM. This
> patch introduces a 'live' mode that in effect combines the record
> plus report into one command. e.g., to monitor a single VM:
> 
>   perf kvm stat live -p $pid
> 
> Same stats options for the record+report path work with the live mode.
> Display rate defaults to 1 and can be changed using the -d option.

Overall it looks good, I like the fact you're not doing it the way perf
script does, i.e. that "pipe mode" thing, more or less like I'm doing on
'perf trace', but I think this is the time to get rid of 'perf_session'
too for this specific "live mode" tools.

I'm almost getting there for 'trace' and 'top', just need to move the
ordered_samples code to evlist, then session, top, trace, kvm live and
script will not need to use 'perf_session' at all.

Also that 'perf_kvm__open_counters' really is just a third copy of code
in 'record' and 'top', right? You could move it to
'perf_ev{list,open}__open' and solve this dup :-)

I applied the cleanups/simple stuff, will try to do some of the prep
work on ordered_samples to use on top and trace and then I think you
could look there so that we get to something that is useful for all
these !perf.data tools.

- Arnaldo
 
> Signed-off-by: David Ahern <dsahern@gmail.com>
> Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Frederic Weisbecker <fweisbec@gmail.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
> Cc: Dong Hao <haodong@linux.vnet.ibm.com>
> ---
>  tools/perf/builtin-kvm.c |  649 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 623 insertions(+), 26 deletions(-)
> 
> diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
> index dcbbcc7..9dd1921 100644
> --- a/tools/perf/builtin-kvm.c
> +++ b/tools/perf/builtin-kvm.c
> @@ -2,6 +2,7 @@
>  #include "perf.h"
>  
>  #include "util/evsel.h"
> +#include "util/evlist.h"
>  #include "util/util.h"
>  #include "util/cache.h"
>  #include "util/symbol.h"
> @@ -15,9 +16,12 @@
>  #include "util/debugfs.h"
>  #include "util/tool.h"
>  #include "util/stat.h"
> +#include "util/top.h"
>  
>  #include <sys/prctl.h>
> +#include <sys/timerfd.h>
>  
> +#include <termios.h>
>  #include <semaphore.h>
>  #include <pthread.h>
>  #include <math.h>
> @@ -81,6 +85,8 @@ struct exit_reasons_table {
>  
>  struct perf_kvm {
>  	struct perf_tool    tool;
> +	struct perf_record_opts opts;
> +	struct perf_evlist  *evlist;
>  	struct perf_session *session;
>  
>  	const char *file_name;
> @@ -95,10 +101,16 @@ struct perf_kvm {
>  	struct kvm_events_ops *events_ops;
>  	key_cmp_fun compare;
>  	struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
> +
>  	u64 total_time;
>  	u64 total_count;
> +	u64 lost_events;
>  
>  	struct rb_root result;
> +
> +	int timerfd;
> +	unsigned int display_time;
> +	bool live;
>  };
>  
>  
> @@ -319,6 +331,23 @@ static void init_kvm_event_record(struct perf_kvm *kvm)
>  		INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
>  }
>  
> +static void clear_events_cache_stats(struct list_head *kvm_events_cache)
> +{
> +	struct list_head *head;
> +	struct kvm_event *event;
> +	unsigned int i;
> +
> +	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 */
> +			memset(&event->total, 0, sizeof(event->total));
> +			memset(event->vcpu, 0,
> +			       event->max_vcpu * sizeof(*event->vcpu));
> +		}
> +	}
> +}
> +
>  static int kvm_events_hash_fn(u64 key)
>  {
>  	return key & (EVENTS_CACHE_SIZE - 1);
> @@ -471,7 +500,11 @@ static bool handle_end_event(struct perf_kvm *kvm,
>  	vcpu_record->last_event = NULL;
>  	vcpu_record->start_time = 0;
>  
> -	BUG_ON(timestamp < time_begin);
> +	/* seems to happen once in a while during live mode */
> +	if (timestamp < time_begin) {
> +		pr_debug("End time before begin time; skipping event.\n");
> +		return true;
> +	}
>  
>  	time_diff = timestamp - time_begin;
>  	return update_kvm_event(event, vcpu, time_diff);
> @@ -637,24 +670,60 @@ static struct kvm_event *pop_from_result(struct rb_root *result)
>  	return container_of(node, struct kvm_event, rb);
>  }
>  
> -static void print_vcpu_info(int vcpu)
> +static void print_vcpu_info(struct perf_kvm *kvm)
>  {
> +	int vcpu = kvm->trace_vcpu;
> +
>  	pr_info("Analyze events for ");
>  
> +	if (kvm->live) {
> +		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 if (kvm->opts.target.tid)
> +			pr_info("tid(s) %s, ", kvm->opts.target.tid);
> +		else if (kvm->opts.target.cpu_list)
> +			pr_info("host cpu(s) %s, ", kvm->opts.target.cpu_list);
> +		else
> +			pr_info("dazed and confused on what is monitored, ");
> +	}
> +
>  	if (vcpu == -1)
>  		pr_info("all VCPUs:\n\n");
>  	else
>  		pr_info("VCPU %d:\n\n", vcpu);
>  }
>  
> +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;
> +}
> +
>  static void print_result(struct perf_kvm *kvm)
>  {
>  	char decode[20];
>  	struct kvm_event *event;
>  	int vcpu = kvm->trace_vcpu;
>  
> +	if (kvm->live) {
> +		puts(CONSOLE_CLEAR);
> +		show_timeofday();
> +	}
> +
>  	pr_info("\n\n");
> -	print_vcpu_info(vcpu);
> +	print_vcpu_info(kvm);
>  	pr_info("%20s ", kvm->events_ops->name);
>  	pr_info("%10s ", "Samples");
>  	pr_info("%9s ", "Samples%");
> @@ -681,6 +750,20 @@ static void print_result(struct perf_kvm *kvm)
>  
>  	pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
>  		kvm->total_count, kvm->total_time / 1e3);
> +
> +	if (kvm->lost_events)
> +		pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events);
> +}
> +
> +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 *kvm = container_of(tool, struct perf_kvm, tool);
> +
> +	kvm->lost_events++;
> +	return 0;
>  }
>  
>  static int process_sample_event(struct perf_tool *tool,
> @@ -704,10 +787,20 @@ static int process_sample_event(struct perf_tool *tool,
>  	return 0;
>  }
>  
> -static int get_cpu_isa(struct perf_session *session)
> +static int cpu_isa_config(struct perf_kvm *kvm)
>  {
> -	char *cpuid = session->header.env.cpuid;
> -	int isa;
> +	char buf[64], *cpuid;
> +	int err, isa;
> +
> +	if (kvm->live) {
> +		err = get_cpuid(buf, sizeof(buf));
> +		if (err != 0) {
> +			pr_err("Failed to look up CPU type (Intel or AMD)\n");
> +			return err;
> +		}
> +		cpuid = buf;
> +	} else
> +		cpuid = kvm->session->header.env.cpuid;
>  
>  	if (strstr(cpuid, "Intel"))
>  		isa = 1;
> @@ -715,10 +808,374 @@ static int get_cpu_isa(struct perf_session *session)
>  		isa = 0;
>  	else {
>  		pr_err("CPU %s is not supported.\n", cpuid);
> -		isa = -ENOTSUP;
> +		return -ENOTSUP;
> +	}
> +
> +	if (isa == 1) {
> +		kvm->exit_reasons = vmx_exit_reasons;
> +		kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
> +		kvm->exit_reasons_isa = "VMX";
> +	}
> +
> +	return 0;
> +}
> +
> +static bool verify_vcpu(int vcpu)
> +{
> +	if (vcpu != -1 && vcpu < 0) {
> +		pr_err("Invalid vcpu:%d.\n", vcpu);
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +#define PERF_KVM__MAX_EVENTS_PER_MMAP  1000
> +
> +static s64 perf_kvm__mmap_read_idx(struct perf_kvm *kvm, int idx)
> +{
> +	union perf_event *event;
> +	s64 n = 0;
> +	int err;
> +
> +	while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) {
> +		err = perf_session__process_event(kvm->session, event,
> +						  &kvm->tool, 0);
> +		if (err) {
> +			pr_err("Failed to process event\n");
> +			return err;
> +		}
> +		n++;
> +
> +		/* limit events per mmap handled all at once */
> +		if (n == PERF_KVM__MAX_EVENTS_PER_MMAP)
> +			break;
> +	}
> +
> +	return n;
> +}
> +
> +static int perf_kvm__mmap_read(struct perf_kvm *kvm)
> +{
> +	int i, err, throttled = 0;
> +	s64 n, ntotal = 0;
> +
> +	for (i = 0; i < kvm->evlist->nr_mmaps; i++) {
> +		n = perf_kvm__mmap_read_idx(kvm, i);
> +		if (n < 0)
> +			return -1;
> +		ntotal += n;
> +		if (n == PERF_KVM__MAX_EVENTS_PER_MMAP)
> +			throttled = 1;
> +	}
> +
> +	/* flush queue after each round in which we processed events */
> +	if (ntotal) {
> +		err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session);
> +		if (err) {
> +			if (kvm->lost_events)
> +				pr_info("\nLost events: %" PRIu64 "\n\n",
> +					kvm->lost_events);
> +			return err;
> +		}
> +	}
> +
> +	return throttled;
> +}
> +
> +static volatile int done;
> +
> +static void sig_handler(int sig)
> +{
> +	if (sig == SIGINT)
> +		done = 1;
> +}
> +
> +static int perf_kvm__timerfd_create(struct perf_kvm *kvm)
> +{
> +	struct itimerspec new_value;
> +	struct timespec now;
> +	int rc = -1;
> +
> +	kvm->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
> +	if (kvm->timerfd < 0) {
> +		pr_err("timerfd_create failed\n");
> +		goto out;
> +	}
> +
> +	if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) {
> +		pr_err("clock_gettime failed: %d\n", errno);
> +		close(kvm->timerfd);
> +		goto out;
> +	}
> +
> +	new_value.it_value.tv_sec = now.tv_sec + kvm->display_time;
> +	new_value.it_value.tv_nsec = now.tv_nsec;
> +	new_value.it_interval.tv_sec = kvm->display_time;
> +	new_value.it_interval.tv_nsec = 0;
> +
> +	if (timerfd_settime(kvm->timerfd, TFD_TIMER_ABSTIME,
> +			    &new_value, NULL) != 0) {
> +		pr_err("timerfd_settime failed: %d\n", errno);
> +		close(kvm->timerfd);
> +		goto out;
> +	}
> +
> +	rc = 0;
> +out:
> +	return rc;
> +}
> +
> +static int perf_kvm__handle_timerfd(struct perf_kvm *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\n", errno);
> +		return -1;
> +	}
> +
> +	if (rc != sizeof(uint64_t)) {
> +		pr_err("Error reading timer fd - invalid size returned\n");
> +		return -1;
> +	}
> +
> +	if (c != 1)
> +		pr_debug("Missed timer beats: %" PRIu64 "\n", 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\n", fd);
> +		return -1;
> +	}
> +
> +	if (fcntl(fd, F_SETFL, arg | O_NONBLOCK) < 0) {
> +		pr_err("Failed to set non-block option on fd %d\n", fd);
> +		return -1;
>  	}
>  
> -	return isa;
> +	return 0;
> +}
> +
> +static
> +int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save)
> +{
> +	int c;
> +
> +	tcsetattr(0, TCSANOW, tc_now);
> +	c = getc(stdin);
> +	tcsetattr(0, TCSAFLUSH, tc_save);
> +
> +	if (c == 'q')
> +		return 1;
> +
> +	/* TO-DO: add hook for 'd' to change display rate
> +	 *        needs an update to timerfd too
> +	 */
> +
> +	return 0;
> +}
> +
> +static int kvm_events_live_report(struct perf_kvm *kvm)
> +{
> +	struct pollfd *pollfds = NULL;
> +	int nr_fds, ret, err = -EINVAL;
> +	struct termios tc, save;
> +
> +	/* 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;
> +	}
> +
> +	init_kvm_event_record(kvm);
> +
> +
> +	tcgetattr(0, &save);
> +	tc = save;
> +	tc.c_lflag &= ~(ICANON | ECHO);
> +	tc.c_cc[VMIN] = 0;
> +	tc.c_cc[VTIME] = 0;
> +
> +	signal(SIGINT, sig_handler);
> +
> +
> +	/* copy pollfds -- need to add timerfd and stdin */
> +	nr_fds = kvm->evlist->nr_fds;
> +	pollfds = zalloc(sizeof(struct pollfd) * (nr_fds + 2));
> +	if (!pollfds) {
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +	memcpy(pollfds, kvm->evlist->pollfd,
> +		sizeof(struct pollfd) * kvm->evlist->nr_fds);
> +
> +	/* add timer fd */
> +	if (perf_kvm__timerfd_create(kvm) < 0) {
> +		err = -1;
> +		goto out;
> +	}
> +
> +	pollfds[nr_fds].fd = kvm->timerfd;
> +	pollfds[nr_fds].events = POLLIN;
> +	nr_fds++;
> +
> +	pollfds[nr_fds].fd = fileno(stdin);
> +	pollfds[nr_fds].events = POLLIN;
> +	nr_fds++;
> +	if (fd_set_nonblock(fileno(stdin)) != 0)
> +		goto out;
> +
> +	/* everything is good - enable the events and process */
> +	perf_evlist__enable(kvm->evlist);
> +
> +	while (!done) {
> +		int rc;
> +
> +		rc = perf_kvm__mmap_read(kvm);
> +		if (rc < 0)
> +			break;
> +
> +		err = perf_kvm__handle_timerfd(kvm);
> +		if (err)
> +			goto out;
> +
> +		done = perf_kvm__handle_stdin(&tc, &save);
> +
> +		if (!rc && !done)
> +			err = poll(pollfds, nr_fds, 100);
> +	}
> +
> +	perf_evlist__disable(kvm->evlist);
> +
> +	if (err == 0) {
> +		sort_result(kvm);
> +		print_result(kvm);
> +	}
> +
> +out:
> +	if (kvm->timerfd >= 0)
> +		close(kvm->timerfd);
> +
> +	if (pollfds)
> +		free(pollfds);
> +
> +	return err;
> +}
> +
> +
> +/* TO-DO: how to merge this with perf-stat */
> +static int perf_kvm__open_counters(struct perf_kvm *kvm)
> +{
> +	struct perf_evsel *pos;
> +	struct perf_evlist *evlist = kvm->evlist;
> +	int err = 0;
> +
> +	/*
> +	 * Note: exclude_{guest,host} do not apply here.
> +	 *       This command processes KVM tracepoints form host only
> +	 */
> +	list_for_each_entry(pos, &evlist->entries, node) {
> +		struct perf_event_attr *attr = &pos->attr;
> +
> +		attr->sample_type = 0;
> +		attr->read_format = 0;
> +
> +		attr->sample_type |= PERF_SAMPLE_TID;
> +		attr->sample_type |= PERF_SAMPLE_TIME;
> +		attr->sample_type |= PERF_SAMPLE_CPU;
> +		attr->sample_type |= PERF_SAMPLE_RAW;
> +
> +		if (evlist->nr_entries > 1) {
> +			attr->sample_type |= PERF_SAMPLE_ID;
> +			attr->read_format |= PERF_FORMAT_ID;
> +		}
> +
> +		attr->sample_id_all = kvm->opts.sample_id_all_missing ? 0 : 1;
> +		attr->sample_period = 1;
> +		attr->comm = !pos->idx;
> +
> +		attr->watermark = 0;
> +		attr->wakeup_events = 100;
> +
> +		/* will enable all once we are ready */
> +		attr->disabled = 1;
> +
> +retry_sample_id:
> +		attr->sample_id_all = kvm->opts.sample_id_all_missing ? 0 : 1;
> +		if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
> +			err = errno;
> +
> +			if (err == EPERM || err == EACCES) {
> +				ui__error_paranoid();
> +				goto out_err;
> +			} else if ((err == EINVAL) &&
> +				   !kvm->opts.sample_id_all_missing) {
> +				/*
> +				 * Old kernel, no attr->sample_id_type_all field
> +				 */
> +				kvm->opts.sample_id_all_missing = true;
> +				goto retry_sample_id;
> +			}
> +
> +			/*
> +			 * should never happen since the event is validated
> +			 * before adding to evlist.
> +			 */
> +			if (err == ENOENT) {
> +				ui__error("The %s event is not supported.\n",
> +					  perf_evsel__name(pos));
> +				goto out_err;
> +			} else if (err == EMFILE) {
> +				ui__error("Too many events need to be opened.\n");
> +				goto out_err;
> +			}
> +
> +			ui__error("The sys_perf_event_open() syscall "
> +				  "returned with %d (%s).  /bin/dmesg "
> +				  "may provide additional information.\n",
> +				  err, strerror(err));
> +			goto out_err;
> +		}
> +	}
> +
> +	if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
> +		ui__error("Failed to mmap with %d (%s)\n",
> +			  errno, strerror(errno));
> +		goto out_err;
> +	}
> +
> +out_err:
> +	return err;
>  }
>  
>  static int read_events(struct perf_kvm *kvm)
> @@ -746,30 +1203,13 @@ static int read_events(struct perf_kvm *kvm)
>  	 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
>  	 * traced in the old kernel.
>  	 */
> -	ret = get_cpu_isa(kvm->session);
> -
> +	ret = cpu_isa_config(kvm);
>  	if (ret < 0)
>  		return ret;
>  
> -	if (ret == 1) {
> -		kvm->exit_reasons = vmx_exit_reasons;
> -		kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
> -		kvm->exit_reasons_isa = "VMX";
> -	}
> -
>  	return perf_session__process_events(kvm->session, &kvm->tool);
>  }
>  
> -static bool verify_vcpu(int vcpu)
> -{
> -	if (vcpu != -1 && vcpu < 0) {
> -		pr_err("Invalid vcpu:%d.\n", vcpu);
> -		return false;
> -	}
> -
> -	return true;
> -}
> -
>  static int kvm_events_report_vcpu(struct perf_kvm *kvm)
>  {
>  	int ret = -EINVAL;
> @@ -881,6 +1321,159 @@ static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv)
>  	return kvm_events_report_vcpu(kvm);
>  }
>  
> +static int kvm_events_live(struct perf_kvm *kvm, int argc, const char **argv)
> +{
> +	struct perf_session *session = NULL;
> +	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"),
> +		OPT_STRING('t', "tid", &kvm->opts.target.tid, "tid",
> +			"record events on existing thread id"),
> +		OPT_STRING('C', "cpu", &kvm->opts.target.cpu_list, "cpu",
> +			"list of host cpus to monitor"),
> +		OPT_UINTEGER('m', "mmap-pages", &kvm->opts.mmap_pages,
> +			"number of mmap data pages"),
> +		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",
> +			"event for reporting: vmexit, mmio, ioport"),
> +		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)"),
> +		OPT_END()
> +	};
> +	const char * const live_usage[] = {
> +		"perf kvm stat live [<options>]",
> +		NULL
> +	};
> +
> +
> +	/* 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;
> +	kvm->tool.ordered_samples = true;
> +	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 = true;
> +
> +	kvm->evlist = perf_evlist__new(NULL, NULL);
> +	if (kvm->evlist == NULL)
> +		return -ENOMEM;
> +
> +	symbol__init();
> +	disable_buildid_cache();
> +
> +	if (argc) {
> +		argc = parse_options(argc, argv, live_options,
> +				     live_usage, 0);
> +		if (argc)
> +			usage_with_options(live_usage, live_options);
> +	}
> +
> +	use_browser = 0;
> +	setup_browser(false);
> +
> +	/*
> +	 * target related setups
> +	 */
> +	if (perf_target__none(&kvm->opts.target))
> +		kvm->opts.target.system_wide = true;
> +
> +	err = perf_target__validate(&kvm->opts.target);
> +	if (err) {
> +		perf_target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ);
> +		ui__warning("%s", errbuf);
> +	}
> +
> +	err = perf_target__parse_uid(&kvm->opts.target);
> +	if (err) {
> +		int saved_errno = errno;
> +
> +		perf_target__strerror(&kvm->opts.target, err,
> +				      errbuf, BUFSIZ);
> +		ui__error("%s", errbuf);
> +
> +		err = -saved_errno;
> +		goto out;
> +	}
> +
> +	/*
> +	 * generate the event list
> +	 */
> +	err = perf_evlist__add_tracepoints(kvm->evlist,
> +					   kvm_events_tp,
> +					   ARRAY_SIZE(kvm_events_tp));
> +	if (err != 0)
> +		goto out;
> +
> +	symbol_conf.nr_events = kvm->evlist->nr_entries;
> +
> +	if (perf_evlist__create_maps(kvm->evlist, &kvm->opts.target) < 0)
> +		usage_with_options(live_usage, live_options);
> +
> +	/*
> +	 * perf session
> +	 */
> +	session = perf_session__new(NULL, O_WRONLY, false, false, &kvm->tool);
> +	if (session == NULL) {
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +	session->evlist = kvm->evlist;
> +	kvm->session = session;
> +	perf_session__set_id_hdr_size(session);
> +
> +
> +	/*
> +	 * need to get pevent initialized
> +	 */
> +	err = perf_evlist__trace_init(kvm->evlist, session);
> +	if (err != 0)
> +		goto out;
> +
> +	if (perf_target__has_task(&kvm->opts.target))
> +		perf_event__synthesize_thread_map(&kvm->tool,
> +						  kvm->evlist->threads,
> +						  perf_event__process,
> +						  &session->host_machine);
> +	else
> +		perf_event__synthesize_threads(&kvm->tool, perf_event__process,
> +					       &session->host_machine);
> +
> +
> +	err = perf_kvm__open_counters(kvm);
> +	if (err != 0)
> +		goto out;
> +
> +	err = kvm_events_live_report(kvm);
> +
> +out:
> +	exit_browser(0);
> +
> +	if (session)
> +		perf_session__delete(session);
> +	kvm->session = NULL;
> +	perf_evlist__delete_maps(kvm->evlist);
> +	perf_evlist__delete(kvm->evlist);
> +
> +	return err;
> +}
> +
>  static void print_kvm_stat_usage(void)
>  {
>  	printf("Usage: perf kvm stat <command>\n\n");
> @@ -888,6 +1481,7 @@ static void print_kvm_stat_usage(void)
>  	printf("# Available commands:\n");
>  	printf("\trecord: record kvm events\n");
>  	printf("\treport: report statistical data of kvm events\n");
> +	printf("\tlive:   live reporting of statistical data of kvm events\n");
>  
>  	printf("\nOtherwise, it is the alias of 'perf stat':\n");
>  }
> @@ -905,6 +1499,9 @@ static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv)
>  	if (!strncmp(argv[1], "rep", 3))
>  		return kvm_events_report(kvm, argc - 1 , argv + 1);
>  
> +	if (!strncmp(argv[1], "live", 4))
> +		return kvm_events_live(kvm, argc - 1 , argv + 1);
> +
>  perf_stat:
>  	return cmd_stat(argc, argv, NULL);
>  }
> -- 
> 1.7.10.1

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 12/12] perf kvm: add live mode
  2012-10-08 20:35   ` Arnaldo Carvalho de Melo
@ 2012-10-08 20:54     ` David Ahern
  2012-10-08 21:44       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 26+ messages in thread
From: David Ahern @ 2012-10-08 20:54 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, mingo, peterz, fweisbec, Xiao Guangrong, Dong Hao

On 10/8/12 2:35 PM, Arnaldo Carvalho de Melo wrote:
> Em Mon, Oct 08, 2012 at 11:17:36AM -0600, David Ahern escreveu:
> Overall it looks good, I like the fact you're not doing it the way perf
> script does, i.e. that "pipe mode" thing, more or less like I'm doing on
> 'perf trace', but I think this is the time to get rid of 'perf_session'
> too for this specific "live mode" tools.

pipe mode would never work for this case. I'm looking at nested virt 
case now and it shows 360,000 events per second.

> I'm almost getting there for 'trace' and 'top', just need to move the
> ordered_samples code to evlist, then session, top, trace, kvm live and
> script will not need to use 'perf_session' at all.

ok. you going to have that soon?

> Also that 'perf_kvm__open_counters' really is just a third copy of code
> in 'record' and 'top', right? You could move it to
> 'perf_ev{list,open}__open' and solve this dup :-)

there's a TO-DO at the top of that function for that reason ;-) I copied 
a fair bit from perf-stat. Now that it's working I can look at code 
consolidation.

> I applied the cleanups/simple stuff, will try to do some of the prep
> work on ordered_samples to use on top and trace and then I think you
> could look there so that we get to something that is useful for all
> these !perf.data tools.

On my Westmere based server I am not seeing problems with timestamps and 
ordering (prior testing was on a Nehalem based server). It just 
weathered a 5 minute or so barrage of > 100,000 events per second 
(peaking at around 360k events/sec) with no problem.

David

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 07/12] perf kvm: handle realloc failures
  2012-10-08 20:34     ` David Ahern
@ 2012-10-08 21:38       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 26+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-10-08 21:38 UTC (permalink / raw)
  To: David Ahern
  Cc: linux-kernel, mingo, peterz, fweisbec, Xiao Guangrong, Dong Hao

Em Mon, Oct 08, 2012 at 02:34:55PM -0600, David Ahern escreveu:
> On 10/8/12 2:19 PM, Arnaldo Carvalho de Melo wrote:
> >>+	prev = event->vcpu;
> >>  	event->vcpu = realloc(event->vcpu,
> >>  			      event->max_vcpu * sizeof(*event->vcpu));
> >>  	if (!event->vcpu) {
> >>+		free(prev);
> >>  		pr_err("Not enough memory\n");

> >Unfamiliar way of doing it, usually we do it like:

> >   	vcpu = realloc(event->vcpu, event->max_vcpu * sizeof(*event->vcpu));

> >	if (!vcpu) {
> >   		pr_err("Not enough memory\n");
> >		return -1;
> >	}

> >	event->vcpu = vcpu;

> >I.e. we don't trow away the old value of event->vcpu.
> 
> right. Command is going to exit on a failure, so leaving the old
> value does not have any impact. I can leave the old if you want it
> for consistency.

I think do it in the familiar way for consistency.

- Arnaldo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 12/12] perf kvm: add live mode
  2012-10-08 20:54     ` David Ahern
@ 2012-10-08 21:44       ` Arnaldo Carvalho de Melo
  2012-10-08 21:57         ` David Ahern
  0 siblings, 1 reply; 26+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-10-08 21:44 UTC (permalink / raw)
  To: David Ahern
  Cc: linux-kernel, mingo, peterz, fweisbec, Xiao Guangrong, Dong Hao

Em Mon, Oct 08, 2012 at 02:54:10PM -0600, David Ahern escreveu:
> On 10/8/12 2:35 PM, Arnaldo Carvalho de Melo wrote:
> >Em Mon, Oct 08, 2012 at 11:17:36AM -0600, David Ahern escreveu:
> >Overall it looks good, I like the fact you're not doing it the way perf
> >script does, i.e. that "pipe mode" thing, more or less like I'm doing on
> >'perf trace', but I think this is the time to get rid of 'perf_session'
> >too for this specific "live mode" tools.
 
> pipe mode would never work for this case. I'm looking at nested virt
> case now and it shows 360,000 events per second.

Right, 'pipe mode' is an interesting construct, but its too inneficient
for same machine record/report, and for networking one we need to have
splice/sendfile, i.e. feed a socket directly in the kernel with what we
stash in mmap.
 
> >I'm almost getting there for 'trace' and 'top', just need to move the
> >ordered_samples code to evlist, then session, top, trace, kvm live and
> >script will not need to use 'perf_session' at all.
> 
> ok. you going to have that soon?

I hope to have it by the end of this week, perhaps earlier.
 
> >Also that 'perf_kvm__open_counters' really is just a third copy of code
> >in 'record' and 'top', right? You could move it to
> >'perf_ev{list,open}__open' and solve this dup :-)
> 
> there's a TO-DO at the top of that function for that reason ;-) I
> copied a fair bit from perf-stat. Now that it's working I can look
> at code consolidation.

Ok, just scratching again an old itch :-)
 
> >I applied the cleanups/simple stuff, will try to do some of the prep
> >work on ordered_samples to use on top and trace and then I think you
> >could look there so that we get to something that is useful for all
> >these !perf.data tools.
> 
> On my Westmere based server I am not seeing problems with timestamps
> and ordering (prior testing was on a Nehalem based server). It just
> weathered a 5 minute or so barrage of > 100,000 events per second
> (peaking at around 360k events/sec) with no problem.

Interesting, but does this involves consuming samples from multiple
CPUs?

- Arnaldo

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 12/12] perf kvm: add live mode
  2012-10-08 21:44       ` Arnaldo Carvalho de Melo
@ 2012-10-08 21:57         ` David Ahern
  0 siblings, 0 replies; 26+ messages in thread
From: David Ahern @ 2012-10-08 21:57 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, mingo, peterz, fweisbec, Xiao Guangrong, Dong Hao

On 10/8/12 3:44 PM, Arnaldo Carvalho de Melo wrote:

>> On my Westmere based server I am not seeing problems with timestamps
>> and ordering (prior testing was on a Nehalem based server). It just
>> weathered a 5 minute or so barrage of > 100,000 events per second
>> (peaking at around 360k events/sec) with no problem.
>
> Interesting, but does this involves consuming samples from multiple
> CPUs?

yes. 4 vcpus that can and do roam the pcpus.

David


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [tip:perf/core] perf kvm: Only process events for vcpus of interest
  2012-10-08 17:17 ` [PATCH 11/12] perf kvm: only process events for vcpus of interest David Ahern
@ 2012-10-09 17:37   ` tip-bot for David Ahern
  0 siblings, 0 replies; 26+ messages in thread
From: tip-bot for David Ahern @ 2012-10-09 17:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, fweisbec, haodong,
	xiaoguangrong, dsahern, tglx

Commit-ID:  2aa8eab029b319b2b458b3ba393bbba31961ea96
Gitweb:     http://git.kernel.org/tip/2aa8eab029b319b2b458b3ba393bbba31961ea96
Author:     David Ahern <dsahern@gmail.com>
AuthorDate: Mon, 8 Oct 2012 11:17:35 -0600
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 8 Oct 2012 17:14:13 -0300

perf kvm: Only process events for vcpus of interest

Minimizing processing overhead for each sample - which becomes important
for the upcoming live mode when it has to deal with 100+k events per
second.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1349716656-48165-12-git-send-email-dsahern@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-kvm.c |   18 ++++++++++++++++--
 1 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 260abc5..b98095e 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -416,7 +416,10 @@ static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event)
 static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
 			     u64 time_diff)
 {
-	kvm_update_event_stats(&event->total, time_diff);
+	if (vcpu_id == -1) {
+		kvm_update_event_stats(&event->total, time_diff);
+		return true;
+	}
 
 	if (!kvm_event_expand(event, vcpu_id))
 		return false;
@@ -432,6 +435,12 @@ static bool handle_end_event(struct perf_kvm *kvm,
 {
 	struct kvm_event *event;
 	u64 time_begin, time_diff;
+	int vcpu;
+
+	if (kvm->trace_vcpu == -1)
+		vcpu = -1;
+	else
+		vcpu = vcpu_record->vcpu_id;
 
 	event = vcpu_record->last_event;
 	time_begin = vcpu_record->start_time;
@@ -461,7 +470,7 @@ static bool handle_end_event(struct perf_kvm *kvm,
 	BUG_ON(timestamp < time_begin);
 
 	time_diff = timestamp - time_begin;
-	return update_kvm_event(event, vcpu_record->vcpu_id, time_diff);
+	return update_kvm_event(event, vcpu, time_diff);
 }
 
 static
@@ -498,6 +507,11 @@ static bool handle_kvm_event(struct perf_kvm *kvm,
 	if (!vcpu_record)
 		return true;
 
+	/* only process events for vcpus user cares about */
+	if ((kvm->trace_vcpu != -1) &&
+	    (kvm->trace_vcpu != vcpu_record->vcpu_id))
+		return true;
+
 	if (kvm->events_ops->is_begin_event(evsel, sample, &key))
 		return handle_begin_event(kvm, vcpu_record, &key, sample->time);
 

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [tip:perf/core] perf kvm: Remove typecast in init_kvm_event_record
  2012-10-08 17:17 ` [PATCH 06/12] perf kvm: remove typecast in init_kvm_event_record David Ahern
@ 2012-10-09 17:38   ` tip-bot for David Ahern
  0 siblings, 0 replies; 26+ messages in thread
From: tip-bot for David Ahern @ 2012-10-09 17:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, fweisbec, haodong,
	xiaoguangrong, dsahern, tglx

Commit-ID:  b880deeaffd9df0cec9a4496447d0d7fd78086f2
Gitweb:     http://git.kernel.org/tip/b880deeaffd9df0cec9a4496447d0d7fd78086f2
Author:     David Ahern <dsahern@gmail.com>
AuthorDate: Mon, 8 Oct 2012 11:17:30 -0600
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 8 Oct 2012 17:14:57 -0300

perf kvm: Remove typecast in init_kvm_event_record

Not needed after changing i to unsigned int.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1349716656-48165-7-git-send-email-dsahern@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-kvm.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index b98095e..8416754 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -313,9 +313,9 @@ struct vcpu_event_record {
 
 static void init_kvm_event_record(struct perf_kvm *kvm)
 {
-	int i;
+	unsigned int i;
 
-	for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
+	for (i = 0; i < EVENTS_CACHE_SIZE; i++)
 		INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
 }
 

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [tip:perf/core] perf kvm: Total count is a u64, print as so
  2012-10-08 17:17 ` [PATCH 10/12] perf kvm: total count is a u64, print as so David Ahern
@ 2012-10-09 17:39   ` tip-bot for David Ahern
  0 siblings, 0 replies; 26+ messages in thread
From: tip-bot for David Ahern @ 2012-10-09 17:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, fweisbec, haodong,
	xiaoguangrong, dsahern, tglx

Commit-ID:  e4f7637f8aefa2ad5159a1cda46fedea6eaf64fc
Gitweb:     http://git.kernel.org/tip/e4f7637f8aefa2ad5159a1cda46fedea6eaf64fc
Author:     David Ahern <dsahern@gmail.com>
AuthorDate: Mon, 8 Oct 2012 11:17:34 -0600
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 8 Oct 2012 17:15:25 -0300

perf kvm: Total count is a u64, print as so

remove cast and use proper type in format.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1349716656-48165-11-git-send-email-dsahern@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-kvm.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 8416754..72a302e 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -673,8 +673,8 @@ static void print_result(struct perf_kvm *kvm)
 		pr_info("\n");
 	}
 
-	pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
-		(unsigned long long)kvm->total_count, kvm->total_time / 1e3);
+	pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
+		kvm->total_count, kvm->total_time / 1e3);
 }
 
 static int process_sample_event(struct perf_tool *tool,

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [tip:perf/core] perf kvm: Add braces around multi-line statements
  2012-10-08 17:17 ` [PATCH 08/12] perf kvm: add braces around multi-line statements David Ahern
@ 2012-10-09 17:40   ` tip-bot for David Ahern
  0 siblings, 0 replies; 26+ messages in thread
From: tip-bot for David Ahern @ 2012-10-09 17:40 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, fweisbec, haodong,
	xiaoguangrong, dsahern, tglx

Commit-ID:  355afe816312faf20d81fdcade29e0361d72a7b4
Gitweb:     http://git.kernel.org/tip/355afe816312faf20d81fdcade29e0361d72a7b4
Author:     David Ahern <dsahern@gmail.com>
AuthorDate: Mon, 8 Oct 2012 11:17:32 -0600
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 8 Oct 2012 17:15:54 -0300

perf kvm: Add braces around multi-line statements

Multi-line statements should have braces. Improves readability.

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Dong Hao <haodong@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1349716656-48165-9-git-send-email-dsahern@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-kvm.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 72a302e..836c82f 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -369,9 +369,10 @@ static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
 	BUG_ON(key->key == INVALID_KEY);
 
 	head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
-	list_for_each_entry(event, head, hash_entry)
+	list_for_each_entry(event, head, hash_entry) {
 		if (event->key.key == key->key && event->key.info == key->info)
 			return event;
+	}
 
 	event = kvm_alloc_init_event(key);
 	if (!event)
@@ -610,13 +611,15 @@ static void sort_result(struct perf_kvm *kvm)
 	int vcpu = kvm->trace_vcpu;
 	struct kvm_event *event;
 
-	for (i = 0; i < EVENTS_CACHE_SIZE; i++)
-		list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry)
+	for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
+		list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry) {
 			if (event_is_valid(event, vcpu)) {
 				update_total_count(kvm, event);
 				insert_to_result(&kvm->result, event,
 						 kvm->compare, vcpu);
 			}
+		}
+	}
 }
 
 /* returns left most element of result, and erase it */

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 09/12] perf kvm: split out tracepoints from record args
  2012-10-08 17:17 ` [PATCH 09/12] perf kvm: split out tracepoints from record args David Ahern
@ 2012-10-17  8:19   ` Xiao Guangrong
  2012-10-17 13:38     ` David Ahern
  0 siblings, 1 reply; 26+ messages in thread
From: Xiao Guangrong @ 2012-10-17  8:19 UTC (permalink / raw)
  To: David Ahern; +Cc: acme, linux-kernel, mingo, peterz, fweisbec, Dong Hao

On 10/09/2012 01:17 AM, David Ahern wrote:

>  	unsigned int rec_argc, i, j;
>  	const char **rec_argv;
> +	const char * const record_args[] = {
> +		"record",
> +		"-R",
> +		"-f",
> +		"-m", "1024",
> +		"-c", "1",
> +	};
> 
> -	rec_argc = ARRAY_SIZE(record_args) + argc + 2;
> +	rec_argc = ARRAY_SIZE(record_args) + argc + 2 +
> +		   ARRAY_SIZE(kvm_events_tp);

Only calculate the size of tracepoints...

>  	rec_argv = calloc(rec_argc + 1, sizeof(char *));
> 
>  	if (rec_argv == NULL)
> @@ -818,6 +821,11 @@ static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
>  	for (i = 0; i < ARRAY_SIZE(record_args); i++)
>  		rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
> 
> +	for (j = 0; j < ARRAY_SIZE(kvm_events_tp); j++) {
> +		rec_argv[i++] = "-e";

Then you add "-e" into the array, however, it is calculated into rec_argc?
Or I missed something.

Other patches look good to me, thanks for your work and look forward to
the new version. :)


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 09/12] perf kvm: split out tracepoints from record args
  2012-10-17  8:19   ` Xiao Guangrong
@ 2012-10-17 13:38     ` David Ahern
  0 siblings, 0 replies; 26+ messages in thread
From: David Ahern @ 2012-10-17 13:38 UTC (permalink / raw)
  To: Xiao Guangrong; +Cc: acme, linux-kernel, mingo, peterz, fweisbec, Dong Hao

On 10/17/12 2:19 AM, Xiao Guangrong wrote:
>> -	rec_argc = ARRAY_SIZE(record_args) + argc + 2;
>> +	rec_argc = ARRAY_SIZE(record_args) + argc + 2 +
>> +		   ARRAY_SIZE(kvm_events_tp);

Lost the 2 in re-doing the set formally for distribution. I'll send a 
patch. Thanks for reviewing it.

David



^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2012-10-17 13:38 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-08 17:17 [PATCH 00/12] perf kvm: Add live mode for analyzing events David Ahern
2012-10-08 17:17 ` [PATCH 01/12] perf evlist: restore some methods removed in an earlier cleanup David Ahern
2012-10-08 17:17 ` [PATCH 02/12] perf evlist: move tracepoint processing code to evlist.c David Ahern
2012-10-08 17:17 ` [PATCH 03/12] perf evlist: add initialzation function for tracepoints David Ahern
2012-10-08 17:17 ` [PATCH 04/12] perf session: export a few functions for event processing David Ahern
2012-10-08 17:17 ` [PATCH 05/12] perf top: move CONSOLE_CLEAR to header file David Ahern
2012-10-08 17:17 ` [PATCH 06/12] perf kvm: remove typecast in init_kvm_event_record David Ahern
2012-10-09 17:38   ` [tip:perf/core] perf kvm: Remove " tip-bot for David Ahern
2012-10-08 17:17 ` [PATCH 07/12] perf kvm: handle realloc failures David Ahern
2012-10-08 20:19   ` Arnaldo Carvalho de Melo
2012-10-08 20:34     ` David Ahern
2012-10-08 21:38       ` Arnaldo Carvalho de Melo
2012-10-08 17:17 ` [PATCH 08/12] perf kvm: add braces around multi-line statements David Ahern
2012-10-09 17:40   ` [tip:perf/core] perf kvm: Add " tip-bot for David Ahern
2012-10-08 17:17 ` [PATCH 09/12] perf kvm: split out tracepoints from record args David Ahern
2012-10-17  8:19   ` Xiao Guangrong
2012-10-17 13:38     ` David Ahern
2012-10-08 17:17 ` [PATCH 10/12] perf kvm: total count is a u64, print as so David Ahern
2012-10-09 17:39   ` [tip:perf/core] perf kvm: Total " tip-bot for David Ahern
2012-10-08 17:17 ` [PATCH 11/12] perf kvm: only process events for vcpus of interest David Ahern
2012-10-09 17:37   ` [tip:perf/core] perf kvm: Only " tip-bot for David Ahern
2012-10-08 17:17 ` [PATCH 12/12] perf kvm: add live mode David Ahern
2012-10-08 20:35   ` Arnaldo Carvalho de Melo
2012-10-08 20:54     ` David Ahern
2012-10-08 21:44       ` Arnaldo Carvalho de Melo
2012-10-08 21:57         ` David Ahern

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.