perf tools: Resolve machine earlier and pass it to perf_event_ops

Reducing the exposure of perf_session further, so that we can use the
classes in cases where no perf.data file is created.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-stua66dcscsezzrcdugvbmvd@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index a36023a..be33606 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -84,6 +84,7 @@
 	self->sample_size = __perf_evsel__sample_size(self->sample_type);
 	self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
 	self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
+	self->host_machine.id_hdr_size = self->id_hdr_size;
 }
 
 int perf_session__create_kernel_maps(struct perf_session *self)
@@ -216,10 +217,10 @@
 	return 0;
 }
 
-int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
-				    struct thread *thread,
-				    struct ip_callchain *chain,
-				    struct symbol **parent)
+int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
+			       struct thread *thread,
+			       struct ip_callchain *chain,
+			       struct symbol **parent)
 {
 	u8 cpumode = PERF_RECORD_MISC_USER;
 	unsigned int i;
@@ -252,7 +253,7 @@
 
 		al.filtered = false;
 		thread__find_addr_location(thread, self, cpumode,
-				MAP__FUNCTION, thread->pid, ip, &al, NULL);
+					   MAP__FUNCTION, ip, &al, NULL);
 		if (al.sym != NULL) {
 			if (sort__has_parent && !*parent &&
 			    symbol__match_parent_regex(al.sym))
@@ -270,14 +271,6 @@
 	return 0;
 }
 
-static int process_event_synth_stub(struct perf_event_ops *ops __used,
-				    union perf_event *event __used,
-				    struct perf_session *session __used)
-{
-	dump_printf(": unhandled!\n");
-	return 0;
-}
-
 static int process_event_synth_tracing_data_stub(union perf_event *event __used,
 						 struct perf_session *session __used)
 {
@@ -296,7 +289,7 @@
 				     union perf_event *event __used,
 				     struct perf_sample *sample __used,
 				     struct perf_evsel *evsel __used,
-				     struct perf_session *session __used)
+				     struct machine *machine __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
@@ -305,7 +298,7 @@
 static int process_event_stub(struct perf_event_ops *ops __used,
 			      union perf_event *event __used,
 			      struct perf_sample *sample __used,
-			      struct perf_session *session __used)
+			      struct machine *machine __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
@@ -313,7 +306,14 @@
 
 static int process_finished_round_stub(struct perf_event_ops *ops __used,
 				       union perf_event *event __used,
-				       struct perf_session *session __used)
+				       struct perf_session *perf_session __used)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
+static int process_event_type_stub(struct perf_event_ops *ops __used,
+				   union perf_event *event __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
@@ -338,7 +338,7 @@
 	if (handler->lost == NULL)
 		handler->lost = perf_event__process_lost;
 	if (handler->read == NULL)
-		handler->read = process_event_stub;
+		handler->read = process_event_sample_stub;
 	if (handler->throttle == NULL)
 		handler->throttle = process_event_stub;
 	if (handler->unthrottle == NULL)
@@ -346,11 +346,11 @@
 	if (handler->attr == NULL)
 		handler->attr = process_event_synth_attr_stub;
 	if (handler->event_type == NULL)
-		handler->event_type = process_event_synth_stub;
+		handler->event_type = process_event_type_stub;
 	if (handler->tracing_data == NULL)
 		handler->tracing_data = process_event_synth_tracing_data_stub;
 	if (handler->build_id == NULL)
-		handler->build_id = process_event_synth_stub;
+		handler->build_id = process_finished_round_stub;
 	if (handler->finished_round == NULL) {
 		if (handler->ordered_samples)
 			handler->finished_round = process_finished_round;
@@ -734,6 +734,18 @@
 		callchain__printf(sample);
 }
 
+static struct machine *
+	perf_session__find_machine_for_cpumode(struct perf_session *session,
+					       union perf_event *event)
+{
+	const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+
+	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)
+		return perf_session__find_machine(session, event->ip.pid);
+
+	return perf_session__find_host_machine(session);
+}
+
 static int perf_session_deliver_event(struct perf_session *session,
 				      union perf_event *event,
 				      struct perf_sample *sample,
@@ -741,6 +753,7 @@
 				      u64 file_offset)
 {
 	struct perf_evsel *evsel;
+	struct machine *machine;
 
 	dump_event(session, event, file_offset, sample);
 
@@ -762,6 +775,8 @@
 		hists__inc_nr_events(&evsel->hists, event->header.type);
 	}
 
+	machine = perf_session__find_machine_for_cpumode(session, event);
+
 	switch (event->header.type) {
 	case PERF_RECORD_SAMPLE:
 		dump_sample(session, event, sample);
@@ -769,23 +784,25 @@
 			++session->hists.stats.nr_unknown_id;
 			return -1;
 		}
-		return ops->sample(ops, event, sample, evsel, session);
+		return ops->sample(ops, event, sample, evsel, machine);
 	case PERF_RECORD_MMAP:
-		return ops->mmap(ops, event, sample, session);
+		return ops->mmap(ops, event, sample, machine);
 	case PERF_RECORD_COMM:
-		return ops->comm(ops, event, sample, session);
+		return ops->comm(ops, event, sample, machine);
 	case PERF_RECORD_FORK:
-		return ops->fork(ops, event, sample, session);
+		return ops->fork(ops, event, sample, machine);
 	case PERF_RECORD_EXIT:
-		return ops->exit(ops, event, sample, session);
+		return ops->exit(ops, event, sample, machine);
 	case PERF_RECORD_LOST:
-		return ops->lost(ops, event, sample, session);
+		if (ops->lost == perf_event__process_lost)
+			session->hists.stats.total_lost += event->lost.lost;
+		return ops->lost(ops, event, sample, machine);
 	case PERF_RECORD_READ:
-		return ops->read(ops, event, sample, session);
+		return ops->read(ops, event, sample, evsel, machine);
 	case PERF_RECORD_THROTTLE:
-		return ops->throttle(ops, event, sample, session);
+		return ops->throttle(ops, event, sample, machine);
 	case PERF_RECORD_UNTHROTTLE:
-		return ops->unthrottle(ops, event, sample, session);
+		return ops->unthrottle(ops, event, sample, machine);
 	default:
 		++session->hists.stats.nr_unknown_events;
 		return -1;
@@ -823,7 +840,7 @@
 			perf_session__update_sample_type(session);
 		return err;
 	case PERF_RECORD_HEADER_EVENT_TYPE:
-		return ops->event_type(ops, event, session);
+		return ops->event_type(ops, event);
 	case PERF_RECORD_HEADER_TRACING_DATA:
 		/* setup for reading amidst mmap */
 		lseek(session->fd, file_offset, SEEK_SET);
@@ -1170,9 +1187,8 @@
 	return true;
 }
 
-int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
-					     const char *symbol_name,
-					     u64 addr)
+int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
+				     const char *symbol_name, u64 addr)
 {
 	char *bracket;
 	enum map_type i;
@@ -1264,17 +1280,16 @@
 	return NULL;
 }
 
-void perf_session__print_ip(union perf_event *event, struct perf_evsel *evsel,
-			    struct perf_sample *sample,
-			    struct perf_session *session,
-			    int print_sym, int print_dso)
+void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
+			  struct machine *machine, struct perf_evsel *evsel,
+			  int print_sym, int print_dso)
 {
 	struct addr_location al;
 	const char *symname, *dsoname;
 	struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
 	struct callchain_cursor_node *node;
 
-	if (perf_event__preprocess_sample(event, session, &al, sample,
+	if (perf_event__preprocess_sample(event, machine, &al, sample,
 					  NULL) < 0) {
 		error("problem processing %d event, skipping it.\n",
 			event->header.type);
@@ -1283,7 +1298,7 @@
 
 	if (symbol_conf.use_callchain && sample->callchain) {
 
-		if (perf_session__resolve_callchain(session, evsel, al.thread,
+		if (machine__resolve_callchain(machine, evsel, al.thread,
 						sample->callchain, NULL) != 0) {
 			if (verbose)
 				error("Failed to resolve callchain. Skipping\n");