linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Adrian Hunter <adrian.hunter@intel.com>
To: Ian Rogers <irogers@google.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>,
	Jiri Olsa <jolsa@redhat.com>, Namhyung Kim <namhyung@kernel.org>,
	Andi Kleen <ak@linux.intel.com>,
	linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Subject: Re: [PATCH 10/35] perf tools: Add machine_pid and vcpu to id_index
Date: Tue, 9 Aug 2022 15:19:27 +0300	[thread overview]
Message-ID: <87ba10ef-8d8e-4104-91c2-c8d8defafba3@intel.com> (raw)
In-Reply-To: <CAP-5=fUOHiOyKi0_Mp9EMD5Jz-K0+6R8Vz6=+rpAbhL1neqxEQ@mail.gmail.com>

On 19/07/22 20:48, Ian Rogers wrote:
> On Mon, Jul 11, 2022 at 2:33 AM Adrian Hunter <adrian.hunter@intel.com> wrote:
>>
>> When injecting events from a guest perf.data file, the events will have
>> separate sample ID numbers. These ID numbers can then be used to determine
>> which machine an event belongs to. To facilitate that, add machine_pid and
>> vcpu to id_index records. For backward compatibility, these are added at
>> the end of the record, and the length of the record is used to determine
>> if they are present or not.
>>
>> Note, this is needed because the events from a guest perf.data file contain
>> the pid/tid of the process running at that time inside the VM not the
>> pid/tid of the (QEMU) hypervisor thread. So a way is needed to relate
>> guest events back to the guest machine and VCPU, and using sample ID
>> numbers for that is relatively simple and convenient.
>>
>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
>> ---
>>  tools/lib/perf/include/internal/evsel.h |  4 ++
>>  tools/lib/perf/include/perf/event.h     |  5 +++
>>  tools/perf/util/session.c               | 40 ++++++++++++++++---
>>  tools/perf/util/synthetic-events.c      | 51 +++++++++++++++++++------
>>  tools/perf/util/synthetic-events.h      |  1 +
>>  5 files changed, 84 insertions(+), 17 deletions(-)
>>
>> diff --git a/tools/lib/perf/include/internal/evsel.h b/tools/lib/perf/include/internal/evsel.h
>> index 2a912a1f1989..a99a75d9e78f 100644
>> --- a/tools/lib/perf/include/internal/evsel.h
>> +++ b/tools/lib/perf/include/internal/evsel.h
>> @@ -30,6 +30,10 @@ struct perf_sample_id {
>>         struct perf_cpu          cpu;
>>         pid_t                    tid;
>>
>> +       /* Guest machine pid and VCPU, valid only if machine_pid is non-zero */
>> +       pid_t                    machine_pid;
>> +       struct perf_cpu          vcpu;
>> +
>>         /* Holds total ID period value for PERF_SAMPLE_READ processing. */
>>         u64                      period;
>>  };
>> diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h
>> index 9f7ca070da87..c2dbd3e88885 100644
>> --- a/tools/lib/perf/include/perf/event.h
>> +++ b/tools/lib/perf/include/perf/event.h
>> @@ -237,6 +237,11 @@ struct id_index_entry {
>>         __u64                    tid;
>>  };
>>
>> +struct id_index_entry_2 {
>> +       __u64                    machine_pid;
>> +       __u64                    vcpu;
>> +};
>> +
>>  struct perf_record_id_index {
>>         struct perf_event_header header;
>>         __u64                    nr;
>> diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
>> index 4c9513bc6d89..5141fe164e97 100644
>> --- a/tools/perf/util/session.c
>> +++ b/tools/perf/util/session.c
>> @@ -2756,18 +2756,35 @@ int perf_event__process_id_index(struct perf_session *session,
>>  {
>>         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;
>>
>> -       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;
>>
>> @@ -2775,15 +2792,28 @@ int perf_event__process_id_index(struct perf_session *session,
>>                         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;
>>         }
>>         return 0;
>>  }
>> diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c
>> index ed9623702f34..2ae59c03ae77 100644
>> --- a/tools/perf/util/synthetic-events.c
>> +++ b/tools/perf/util/synthetic-events.c
>> @@ -1759,19 +1759,26 @@ int perf_event__synthesize_id_sample(__u64 *array, u64 type, const struct perf_s
>>         return (void *)array - (void *)start;
>>  }
>>
>> -int perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_t process,
>> -                                   struct evlist *evlist, struct machine *machine)
>> +int __perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_t process,
>> +                                     struct evlist *evlist, struct machine *machine, size_t from)
>>  {
>>         union perf_event *ev;
>>         struct evsel *evsel;
>> -       size_t nr = 0, i = 0, sz, max_nr, n;
>> +       size_t nr = 0, i = 0, sz, max_nr, n, pos;
>> +       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;
>> +       bool e2_needed = false;
>>         int err;
>>
>> -       max_nr = (UINT16_MAX - sizeof(struct perf_record_id_index)) /
>> -                sizeof(struct id_index_entry);
>> +       max_nr = (UINT16_MAX - sizeof(struct perf_record_id_index)) / etot_sz;
>>
>> -       evlist__for_each_entry(evlist, evsel)
>> +       pos = 0;
>> +       evlist__for_each_entry(evlist, evsel) {
>> +               if (pos++ < from)
>> +                       continue;
>>                 nr += evsel->core.ids;
>> +       }
>>
>>         if (!nr)
>>                 return 0;
>> @@ -1779,31 +1786,38 @@ int perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_
>>         pr_debug2("Synthesizing id index\n");
>>
>>         n = nr > max_nr ? max_nr : nr;
>> -       sz = sizeof(struct perf_record_id_index) + n * sizeof(struct id_index_entry);
>> +       sz = sizeof(struct perf_record_id_index) + n * etot_sz;
>>         ev = zalloc(sz);
>>         if (!ev)
>>                 return -ENOMEM;
>>
>> +       sz = sizeof(struct perf_record_id_index) + n * e1_sz;
>> +
>>         ev->id_index.header.type = PERF_RECORD_ID_INDEX;
>> -       ev->id_index.header.size = sz;
>>         ev->id_index.nr = n;
>>
>> +       pos = 0;
>>         evlist__for_each_entry(evlist, evsel) {
>>                 u32 j;
>>
>> -               for (j = 0; j < evsel->core.ids; j++) {
>> +               if (pos++ < from)
>> +                       continue;
>> +               for (j = 0; j < evsel->core.ids; j++, i++) {
>>                         struct id_index_entry *e;
>> +                       struct id_index_entry_2 *e2;
>>                         struct perf_sample_id *sid;
>>
>>                         if (i >= n) {
>> +                               ev->id_index.header.size = sz + (e2_needed ? n * e2_sz : 0);
>>                                 err = process(tool, ev, NULL, machine);
>>                                 if (err)
>>                                         goto out_err;
>>                                 nr -= n;
>>                                 i = 0;
>> +                               e2_needed = false;
>>                         }
>>
>> -                       e = &ev->id_index.entries[i++];
>> +                       e = &ev->id_index.entries[i];
>>
>>                         e->id = evsel->core.id[j];
>>
>> @@ -1816,11 +1830,18 @@ int perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_
>>                         e->idx = sid->idx;
>>                         e->cpu = sid->cpu.cpu;
>>                         e->tid = sid->tid;
>> +
>> +                       if (sid->machine_pid)
>> +                               e2_needed = true;
>> +
>> +                       e2 = (void *)ev + sz;
>> +                       e2[i].machine_pid = sid->machine_pid;
>> +                       e2[i].vcpu        = sid->vcpu.cpu;
>>                 }
>>         }
>>
>> -       sz = sizeof(struct perf_record_id_index) + nr * sizeof(struct id_index_entry);
>> -       ev->id_index.header.size = sz;
>> +       sz = sizeof(struct perf_record_id_index) + nr * e1_sz;
>> +       ev->id_index.header.size = sz + (e2_needed ? nr * e2_sz : 0);
>>         ev->id_index.nr = nr;
>>
>>         err = process(tool, ev, NULL, machine);
>> @@ -1830,6 +1851,12 @@ int perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_
>>         return err;
>>  }
>>
>> +int perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_t process,
>> +                                   struct evlist *evlist, struct machine *machine)
>> +{
>> +       return __perf_event__synthesize_id_index(tool, process, evlist, machine, 0);
>> +}
>> +
>>  int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
>>                                   struct target *target, struct perf_thread_map *threads,
>>                                   perf_event__handler_t process, bool needs_mmap,
>> diff --git a/tools/perf/util/synthetic-events.h b/tools/perf/util/synthetic-events.h
>> index b136ec3ec95d..81cb3d6af0b9 100644
>> --- a/tools/perf/util/synthetic-events.h
>> +++ b/tools/perf/util/synthetic-events.h
>> @@ -55,6 +55,7 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool, struct evlist *evs
>>  int perf_event__synthesize_extra_kmaps(struct perf_tool *tool, perf_event__handler_t process, struct machine *machine);
>>  int perf_event__synthesize_features(struct perf_tool *tool, struct perf_session *session, struct evlist *evlist, perf_event__handler_t process);
>>  int perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_t process, struct evlist *evlist, struct machine *machine);
>> +int __perf_event__synthesize_id_index(struct perf_tool *tool, perf_event__handler_t process, struct evlist *evlist, struct machine *machine, size_t from);
> 
> Given there is only 1 use in the file defining the function, should
> this just be static with no header file declaration?

It is used perf inject also.

> 
> Thanks,
> Ian
> 
>>  int perf_event__synthesize_id_sample(__u64 *array, u64 type, const struct perf_sample *sample);
>>  int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, perf_event__handler_t process, struct machine *machine);
>>  int perf_event__synthesize_mmap_events(struct perf_tool *tool, union perf_event *event, pid_t pid, pid_t tgid, perf_event__handler_t process, struct machine *machine, bool mmap_data);
>> --
>> 2.25.1
>>


  reply	other threads:[~2022-08-09 12:19 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-11  9:31 [PATCH 00/35] perf intel-pt: Add support for tracing virtual machine user space on the host Adrian Hunter
2022-07-11  9:31 ` [PATCH 01/35] perf tools: Fix dso_id inode generation comparison Adrian Hunter
2022-07-18 14:57   ` Arnaldo Carvalho de Melo
2022-07-19 10:18     ` Adrian Hunter
2022-07-19 15:13       ` Ian Rogers
2022-07-19 19:16         ` Arnaldo Carvalho de Melo
2022-07-11  9:31 ` [PATCH 02/35] perf tools: Export dsos__for_each_with_build_id() Adrian Hunter
2022-07-19 16:55   ` Ian Rogers
2022-07-11  9:31 ` [PATCH 03/35] perf ordered_events: Add ordered_events__last_flush_time() Adrian Hunter
2022-07-19 16:56   ` Ian Rogers
2022-07-11  9:31 ` [PATCH 04/35] perf tools: Export perf_event__process_finished_round() Adrian Hunter
2022-07-19 17:04   ` Ian Rogers
2022-08-09 11:37     ` Adrian Hunter
2022-07-11  9:31 ` [PATCH 05/35] perf tools: Factor out evsel__id_hdr_size() Adrian Hunter
2022-07-19 17:09   ` Ian Rogers
2022-08-09 11:49     ` Adrian Hunter
2022-08-09 17:07       ` Ian Rogers
2022-07-11  9:31 ` [PATCH 06/35] perf tools: Add perf_event__synthesize_id_sample() Adrian Hunter
2022-07-19 17:10   ` Ian Rogers
2022-07-11  9:31 ` [PATCH 07/35] perf script: Add --dump-unsorted-raw-trace option Adrian Hunter
2022-07-19 17:11   ` Ian Rogers
2022-07-11  9:31 ` [PATCH 08/35] perf buildid-cache: Add guestmount'd files to the build ID cache Adrian Hunter
2022-07-19 17:41   ` Ian Rogers
2022-08-09 12:21     ` Adrian Hunter
2022-07-11  9:31 ` [PATCH 09/35] perf buildid-cache: Do not require purge files to also be in the file system Adrian Hunter
2022-07-19 17:44   ` Ian Rogers
2022-07-11  9:31 ` [PATCH 10/35] perf tools: Add machine_pid and vcpu to id_index Adrian Hunter
2022-07-19 17:48   ` Ian Rogers
2022-08-09 12:19     ` Adrian Hunter [this message]
2022-07-11  9:31 ` [PATCH 11/35] perf session: Create guest machines from id_index Adrian Hunter
2022-07-19 17:51   ` Ian Rogers
2022-07-11  9:31 ` [PATCH 12/35] perf tools: Add guest_cpu to hypervisor threads Adrian Hunter
2022-07-20  0:23   ` Ian Rogers
2022-07-11  9:31 ` [PATCH 13/35] perf tools: Add machine_pid and vcpu to perf_sample Adrian Hunter
2022-07-20  0:36   ` Ian Rogers
2022-07-11  9:31 ` [PATCH 14/35] perf tools: Use sample->machine_pid to find guest machine Adrian Hunter
2022-07-20  0:37   ` Ian Rogers
2022-07-11  9:31 ` [PATCH 15/35] perf script: Add machine_pid and vcpu Adrian Hunter
2022-07-20  0:39   ` Ian Rogers
2022-07-11  9:31 ` [PATCH 16/35] perf dlfilter: " Adrian Hunter
2022-07-20  0:42   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 17/35] perf auxtrace: Add machine_pid and vcpu to auxtrace_error Adrian Hunter
2022-07-20  0:43   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 18/35] perf script python: Add machine_pid and vcpu Adrian Hunter
2022-07-20  0:43   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 19/35] perf script python: intel-pt-events: " Adrian Hunter
2022-07-20  0:44   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 20/35] perf tools: Remove also guest kcore_dir with host kcore_dir Adrian Hunter
2022-07-20  0:45   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 21/35] perf tools: Make has_kcore_dir() work also for guest kcore_dir Adrian Hunter
2022-07-20  0:49   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 22/35] perf tools: Automatically use guest kcore_dir if present Adrian Hunter
2022-07-20  0:51   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 23/35] perf tools: Add reallocarray_as_needed() Adrian Hunter
2022-07-20  0:55   ` Ian Rogers
2022-08-09 16:48     ` Adrian Hunter
2022-07-11  9:32 ` [PATCH 24/35] perf inject: Add support for injecting guest sideband events Adrian Hunter
2022-07-20  1:06   ` Ian Rogers
2022-08-11 17:19     ` Adrian Hunter
2022-07-11  9:32 ` [PATCH 25/35] perf machine: Use realloc_array_as_needed() in machine__set_current_tid() Adrian Hunter
2022-07-11  9:32 ` [PATCH 26/35] perf tools: Handle injected guest kernel mmap event Adrian Hunter
2022-07-20  1:09   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 27/35] perf tools: Add perf_event__is_guest() Adrian Hunter
2022-07-20  1:11   ` Ian Rogers
2022-07-20 14:06     ` Arnaldo Carvalho de Melo
2022-07-20 14:56       ` Ian Rogers
2022-07-11  9:32 ` [PATCH 28/35] perf intel-pt: Remove guest_machine_pid Adrian Hunter
2022-07-20  1:12   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 29/35] perf intel-pt: Add some more logging to intel_pt_walk_next_insn() Adrian Hunter
2022-07-20  1:13   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 30/35] perf intel-pt: Track guest context switches Adrian Hunter
2022-07-20  1:13   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 31/35] perf intel-pt: Disable sync switch with guest sideband Adrian Hunter
2022-07-20  1:14   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 32/35] perf intel-pt: Determine guest thread from " Adrian Hunter
2022-07-20  1:15   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 33/35] perf intel-pt: Add machine_pid and vcpu to auxtrace_error Adrian Hunter
2022-07-20  5:27   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 34/35] perf intel-pt: Use guest pid/tid etc in guest samples Adrian Hunter
2022-07-20  5:28   ` Ian Rogers
2022-07-11  9:32 ` [PATCH 35/35] perf intel-pt: Add documentation for tracing guest machine user space Adrian Hunter
2022-07-20  5:29   ` Ian Rogers
2022-07-18 15:28 ` [PATCH 00/35] perf intel-pt: Add support for tracing virtual machine user space on the host Arnaldo Carvalho de Melo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ba10ef-8d8e-4104-91c2-c8d8defafba3@intel.com \
    --to=adrian.hunter@intel.com \
    --cc=acme@kernel.org \
    --cc=ak@linux.intel.com \
    --cc=irogers@google.com \
    --cc=jolsa@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=namhyung@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).