summaryrefslogtreecommitdiff
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r--tools/perf/util/session.c180
1 files changed, 137 insertions, 43 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0aa818977d2b..192c9274f7ad 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -374,10 +374,6 @@ static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
return 0;
}
-static int process_finished_round(struct perf_tool *tool,
- union perf_event *event,
- struct ordered_events *oe);
-
static int skipn(int fd, off_t n)
{
char buf[4096];
@@ -534,7 +530,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
tool->build_id = process_event_op2_stub;
if (tool->finished_round == NULL) {
if (tool->ordered_events)
- tool->finished_round = process_finished_round;
+ tool->finished_round = perf_event__process_finished_round;
else
tool->finished_round = process_finished_round_stub;
}
@@ -562,6 +558,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
tool->feature = process_event_op2_stub;
if (tool->compressed == NULL)
tool->compressed = perf_session__process_compressed_event;
+ if (tool->finished_init == NULL)
+ tool->finished_init = process_event_op2_stub;
}
static void swap_sample_id_all(union perf_event *event, void *data)
@@ -897,6 +895,10 @@ static void perf_event__auxtrace_error_swap(union perf_event *event,
event->auxtrace_error.ip = bswap_64(event->auxtrace_error.ip);
if (event->auxtrace_error.fmt)
event->auxtrace_error.time = bswap_64(event->auxtrace_error.time);
+ if (event->auxtrace_error.fmt >= 2) {
+ event->auxtrace_error.machine_pid = bswap_32(event->auxtrace_error.machine_pid);
+ event->auxtrace_error.vcpu = bswap_32(event->auxtrace_error.vcpu);
+ }
}
static void perf_event__thread_map_swap(union perf_event *event,
@@ -914,30 +916,30 @@ static void perf_event__cpu_map_swap(union perf_event *event,
bool sample_id_all __maybe_unused)
{
struct perf_record_cpu_map_data *data = &event->cpu_map.data;
- struct cpu_map_entries *cpus;
- struct perf_record_record_cpu_map *mask;
- unsigned i;
data->type = bswap_16(data->type);
switch (data->type) {
case PERF_CPU_MAP__CPUS:
- cpus = (struct cpu_map_entries *)data->data;
-
- cpus->nr = bswap_16(cpus->nr);
+ data->cpus_data.nr = bswap_16(data->cpus_data.nr);
- for (i = 0; i < cpus->nr; i++)
- cpus->cpu[i] = bswap_16(cpus->cpu[i]);
+ for (unsigned i = 0; i < data->cpus_data.nr; i++)
+ data->cpus_data.cpu[i] = bswap_16(data->cpus_data.cpu[i]);
break;
case PERF_CPU_MAP__MASK:
- mask = (struct perf_record_record_cpu_map *)data->data;
+ data->mask32_data.long_size = bswap_16(data->mask32_data.long_size);
- mask->nr = bswap_16(mask->nr);
- mask->long_size = bswap_16(mask->long_size);
-
- switch (mask->long_size) {
- case 4: mem_bswap_32(&mask->mask, mask->nr); break;
- case 8: mem_bswap_64(&mask->mask, mask->nr); break;
+ switch (data->mask32_data.long_size) {
+ case 4:
+ data->mask32_data.nr = bswap_16(data->mask32_data.nr);
+ for (unsigned i = 0; i < data->mask32_data.nr; i++)
+ data->mask32_data.mask[i] = bswap_32(data->mask32_data.mask[i]);
+ break;
+ case 8:
+ data->mask64_data.nr = bswap_16(data->mask64_data.nr);
+ for (unsigned i = 0; i < data->mask64_data.nr; i++)
+ data->mask64_data.mask[i] = bswap_64(data->mask64_data.mask[i]);
+ break;
default:
pr_err("cpu_map swap: unsupported long size\n");
}
@@ -1067,9 +1069,9 @@ static perf_event__swap_op perf_event__swap_ops[] = {
* Flush every events below timestamp 7
* etc...
*/
-static int process_finished_round(struct perf_tool *tool __maybe_unused,
- union perf_event *event __maybe_unused,
- struct ordered_events *oe)
+int perf_event__process_finished_round(struct perf_tool *tool __maybe_unused,
+ union perf_event *event __maybe_unused,
+ struct ordered_events *oe)
{
if (dump_trace)
fprintf(stdout, "\n");
@@ -1281,21 +1283,25 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
sample->read.time_running);
if (read_format & PERF_FORMAT_GROUP) {
- u64 i;
+ struct sample_read_value *value = sample->read.group.values;
printf(".... group nr %" PRIu64 "\n", sample->read.group.nr);
- for (i = 0; i < sample->read.group.nr; i++) {
- struct sample_read_value *value;
-
- value = &sample->read.group.values[i];
+ sample_read_group__for_each(value, sample->read.group.nr, read_format) {
printf("..... id %016" PRIx64
- ", value %016" PRIx64 "\n",
+ ", value %016" PRIx64,
value->id, value->value);
+ if (read_format & PERF_FORMAT_LOST)
+ printf(", lost %" PRIu64, value->lost);
+ printf("\n");
}
- } else
- printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
+ } else {
+ printf("..... id %016" PRIx64 ", value %016" PRIx64,
sample->read.one.id, sample->read.one.value);
+ if (read_format & PERF_FORMAT_LOST)
+ printf(", lost %" PRIu64, sample->read.one.lost);
+ printf("\n");
+ }
}
static void dump_event(struct evlist *evlist, union perf_event *event,
@@ -1409,6 +1415,9 @@ static void dump_read(struct evsel *evsel, union perf_event *event)
if (read_format & PERF_FORMAT_ID)
printf("... id : %" PRI_lu64 "\n", read_event->id);
+
+ if (read_format & PERF_FORMAT_LOST)
+ printf("... lost : %" PRI_lu64 "\n", read_event->lost);
}
static struct machine *machines__find_for_cpumode(struct machines *machines,
@@ -1420,7 +1429,9 @@ static struct machine *machines__find_for_cpumode(struct machines *machines,
(sample->cpumode == PERF_RECORD_MISC_GUEST_USER))) {
u32 pid;
- if (event->header.type == PERF_RECORD_MMAP
+ if (sample->machine_pid)
+ pid = sample->machine_pid;
+ else if (event->header.type == PERF_RECORD_MMAP
|| event->header.type == PERF_RECORD_MMAP2)
pid = event->mmap.pid;
else
@@ -1475,14 +1486,14 @@ static int deliver_sample_group(struct evlist *evlist,
struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
- struct machine *machine)
+ struct machine *machine,
+ u64 read_format)
{
int ret = -EINVAL;
- u64 i;
+ struct sample_read_value *v = sample->read.group.values;
- for (i = 0; i < sample->read.group.nr; i++) {
- ret = deliver_sample_value(evlist, tool, event, sample,
- &sample->read.group.values[i],
+ sample_read_group__for_each(v, sample->read.group.nr, read_format) {
+ ret = deliver_sample_value(evlist, tool, event, sample, v,
machine);
if (ret)
break;
@@ -1506,7 +1517,7 @@ static int evlist__deliver_sample(struct evlist *evlist, struct perf_tool *tool,
/* For PERF_SAMPLE_READ we have either single or group mode. */
if (read_format & PERF_FORMAT_GROUP)
return deliver_sample_group(evlist, tool, event, sample,
- machine);
+ machine, read_format);
else
return deliver_sample_value(evlist, tool, event, sample,
&sample->read.one, machine);
@@ -1706,6 +1717,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
if (err)
dump_event(session->evlist, event, file_offset, &sample, file_path);
return err;
+ case PERF_RECORD_FINISHED_INIT:
+ return tool->finished_init(session, event);
default:
return -EINVAL;
}
@@ -2751,39 +2764,120 @@ void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
fprintf(fp, "# ========\n#\n");
}
+static int perf_session__register_guest(struct perf_session *session, pid_t machine_pid)
+{
+ struct machine *machine = machines__findnew(&session->machines, machine_pid);
+ struct thread *thread;
+
+ if (!machine)
+ return -ENOMEM;
+
+ machine->single_address_space = session->machines.host.single_address_space;
+
+ thread = machine__idle_thread(machine);
+ if (!thread)
+ return -ENOMEM;
+ thread__put(thread);
+
+ machine->kallsyms_filename = perf_data__guest_kallsyms_name(session->data, machine_pid);
+
+ return 0;
+}
+
+static int perf_session__set_guest_cpu(struct perf_session *session, pid_t pid,
+ pid_t tid, int guest_cpu)
+{
+ struct machine *machine = &session->machines.host;
+ struct thread *thread = machine__findnew_thread(machine, pid, tid);
+
+ if (!thread)
+ return -ENOMEM;
+ thread->guest_cpu = guest_cpu;
+ thread__put(thread);
+
+ return 0;
+}
+
int perf_event__process_id_index(struct perf_session *session,
union perf_event *event)
{
struct evlist *evlist = session->evlist;
struct perf_record_id_index *ie = &event->id_index;
+ size_t sz = ie->header.size - sizeof(*ie);
size_t i, nr, max_nr;
+ size_t e1_sz = sizeof(struct id_index_entry);
+ size_t e2_sz = sizeof(struct id_index_entry_2);
+ size_t etot_sz = e1_sz + e2_sz;
+ struct id_index_entry_2 *e2;
+ pid_t last_pid = 0;
- max_nr = (ie->header.size - sizeof(struct perf_record_id_index)) /
- sizeof(struct id_index_entry);
+ max_nr = sz / e1_sz;
nr = ie->nr;
- if (nr > max_nr)
+ if (nr > max_nr) {
+ printf("Too big: nr %zu max_nr %zu\n", nr, max_nr);
return -EINVAL;
+ }
+
+ if (sz >= nr * etot_sz) {
+ max_nr = sz / etot_sz;
+ if (nr > max_nr) {
+ printf("Too big2: nr %zu max_nr %zu\n", nr, max_nr);
+ return -EINVAL;
+ }
+ e2 = (void *)ie + sizeof(*ie) + nr * e1_sz;
+ } else {
+ e2 = NULL;
+ }
if (dump_trace)
fprintf(stdout, " nr: %zu\n", nr);
- for (i = 0; i < nr; i++) {
+ for (i = 0; i < nr; i++, (e2 ? e2++ : 0)) {
struct id_index_entry *e = &ie->entries[i];
struct perf_sample_id *sid;
+ int ret;
if (dump_trace) {
fprintf(stdout, " ... id: %"PRI_lu64, e->id);
fprintf(stdout, " idx: %"PRI_lu64, e->idx);
fprintf(stdout, " cpu: %"PRI_ld64, e->cpu);
- fprintf(stdout, " tid: %"PRI_ld64"\n", e->tid);
+ fprintf(stdout, " tid: %"PRI_ld64, e->tid);
+ if (e2) {
+ fprintf(stdout, " machine_pid: %"PRI_ld64, e2->machine_pid);
+ fprintf(stdout, " vcpu: %"PRI_lu64"\n", e2->vcpu);
+ } else {
+ fprintf(stdout, "\n");
+ }
}
sid = evlist__id2sid(evlist, e->id);
if (!sid)
return -ENOENT;
+
sid->idx = e->idx;
sid->cpu.cpu = e->cpu;
sid->tid = e->tid;
+
+ if (!e2)
+ continue;
+
+ sid->machine_pid = e2->machine_pid;
+ sid->vcpu.cpu = e2->vcpu;
+
+ if (!sid->machine_pid)
+ continue;
+
+ if (sid->machine_pid != last_pid) {
+ ret = perf_session__register_guest(session, sid->machine_pid);
+ if (ret)
+ return ret;
+ last_pid = sid->machine_pid;
+ perf_guest = true;
+ }
+
+ ret = perf_session__set_guest_cpu(session, sid->machine_pid, e->tid, e2->vcpu);
+ if (ret)
+ return ret;
}
return 0;
}