From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Song Liu <songliubraving@fb.com>
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
peterz@infradead.org, ast@kernel.org, daniel@iogearbox.net,
kernel-team@fb.com
Subject: Re: [PATCH v6 perf, bpf-next 1/7] perf, bpf: Introduce PERF_RECORD_KSYMBOL
Date: Thu, 10 Jan 2019 15:24:03 -0300 [thread overview]
Message-ID: <20190110182403.GN22483@kernel.org> (raw)
In-Reply-To: <20190109192111.130995-2-songliubraving@fb.com>
Em Wed, Jan 09, 2019 at 11:21:05AM -0800, Song Liu escreveu:
> For better performance analysis of dynamically JITed and loaded kernel
> functions, such as BPF programs, this patch introduces
> PERF_RECORD_KSYMBOL, a new perf_event_type that exposes kernel symbol
> register/unregister information to user space.
>
> The following data structure is used for PERF_RECORD_KSYMBOL.
>
> /*
> * struct {
> * struct perf_event_header header;
> * u64 addr;
> * u32 len;
> * u16 ksym_type;
> * u16 flags;
> * char name[];
> * struct sample_id sample_id;
> * };
> */
So, I couldn't find where this gets used, the intention here is just to
add the interfaces and afterwards is that you will wire this up? I would
like to test the whole shebang to see it working.
- Arnaldo
> Signed-off-by: Song Liu <songliubraving@fb.com>
> ---
> include/linux/perf_event.h | 13 +++++
> include/uapi/linux/perf_event.h | 26 ++++++++-
> kernel/events/core.c | 98 ++++++++++++++++++++++++++++++++-
> 3 files changed, 135 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> index 1d5c551a5add..6b5f08db5ef3 100644
> --- a/include/linux/perf_event.h
> +++ b/include/linux/perf_event.h
> @@ -1113,6 +1113,13 @@ static inline void perf_event_task_sched_out(struct task_struct *prev,
> }
>
> extern void perf_event_mmap(struct vm_area_struct *vma);
> +
> +/* callback function to generate ksymbol name */
> +typedef int (perf_ksymbol_get_name_f)(char *name, int name_len, void *data);
> +extern void perf_event_ksymbol(u16 ksym_type, u64 addr, u32 len,
> + bool unregister,
> + perf_ksymbol_get_name_f get_name, void *data);
> +
> extern struct perf_guest_info_callbacks *perf_guest_cbs;
> extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks);
> extern int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks);
> @@ -1333,6 +1340,12 @@ static inline int perf_unregister_guest_info_callbacks
> (struct perf_guest_info_callbacks *callbacks) { return 0; }
>
> static inline void perf_event_mmap(struct vm_area_struct *vma) { }
> +
> +typedef int (perf_ksymbol_get_name_f)(char *name, int name_len, void *data);
> +static inline void perf_event_ksymbol(u16 ksym_type, u64 addr, u32 len,
> + bool unregister,
> + perf_ksymbol_get_name_f get_name,
> + void *data) { }
> static inline void perf_event_exec(void) { }
> static inline void perf_event_comm(struct task_struct *tsk, bool exec) { }
> static inline void perf_event_namespaces(struct task_struct *tsk) { }
> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
> index 9de8780ac8d9..68c4da0227c5 100644
> --- a/include/uapi/linux/perf_event.h
> +++ b/include/uapi/linux/perf_event.h
> @@ -372,7 +372,8 @@ struct perf_event_attr {
> context_switch : 1, /* context switch data */
> write_backward : 1, /* Write ring buffer from end to beginning */
> namespaces : 1, /* include namespaces data */
> - __reserved_1 : 35;
> + ksymbol : 1, /* include ksymbol events */
> + __reserved_1 : 34;
>
> union {
> __u32 wakeup_events; /* wakeup every n events */
> @@ -965,9 +966,32 @@ enum perf_event_type {
> */
> PERF_RECORD_NAMESPACES = 16,
>
> + /*
> + * Record ksymbol register/unregister events:
> + *
> + * struct {
> + * struct perf_event_header header;
> + * u64 addr;
> + * u32 len;
> + * u16 ksym_type;
> + * u16 flags;
> + * char name[];
> + * struct sample_id sample_id;
> + * };
> + */
> + PERF_RECORD_KSYMBOL = 17,
> +
> PERF_RECORD_MAX, /* non-ABI */
> };
>
> +enum perf_record_ksymbol_type {
> + PERF_RECORD_KSYMBOL_TYPE_UNKNOWN = 0,
> + PERF_RECORD_KSYMBOL_TYPE_BPF = 1,
> + PERF_RECORD_KSYMBOL_TYPE_MAX /* non-ABI */
> +};
> +
> +#define PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER (1 << 0)
> +
> #define PERF_MAX_STACK_DEPTH 127
> #define PERF_MAX_CONTEXTS_PER_STACK 8
>
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 3cd13a30f732..ef27f2776999 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -385,6 +385,7 @@ static atomic_t nr_namespaces_events __read_mostly;
> static atomic_t nr_task_events __read_mostly;
> static atomic_t nr_freq_events __read_mostly;
> static atomic_t nr_switch_events __read_mostly;
> +static atomic_t nr_ksymbol_events __read_mostly;
>
> static LIST_HEAD(pmus);
> static DEFINE_MUTEX(pmus_lock);
> @@ -4235,7 +4236,7 @@ static bool is_sb_event(struct perf_event *event)
>
> if (attr->mmap || attr->mmap_data || attr->mmap2 ||
> attr->comm || attr->comm_exec ||
> - attr->task ||
> + attr->task || attr->ksymbol ||
> attr->context_switch)
> return true;
> return false;
> @@ -4305,6 +4306,8 @@ static void unaccount_event(struct perf_event *event)
> dec = true;
> if (has_branch_stack(event))
> dec = true;
> + if (event->attr.ksymbol)
> + atomic_dec(&nr_ksymbol_events);
>
> if (dec) {
> if (!atomic_add_unless(&perf_sched_count, -1, 1))
> @@ -7650,6 +7653,97 @@ static void perf_log_throttle(struct perf_event *event, int enable)
> perf_output_end(&handle);
> }
>
> +/*
> + * ksymbol register/unregister tracking
> + */
> +
> +struct perf_ksymbol_event {
> + const char *name;
> + int name_len;
> + struct {
> + struct perf_event_header header;
> + u64 addr;
> + u32 len;
> + u16 ksym_type;
> + u16 flags;
> + } event_id;
> +};
> +
> +static int perf_event_ksymbol_match(struct perf_event *event)
> +{
> + return event->attr.ksymbol;
> +}
> +
> +static void perf_event_ksymbol_output(struct perf_event *event, void *data)
> +{
> + struct perf_ksymbol_event *ksymbol_event = data;
> + struct perf_output_handle handle;
> + struct perf_sample_data sample;
> + int ret;
> +
> + if (!perf_event_ksymbol_match(event))
> + return;
> +
> + perf_event_header__init_id(&ksymbol_event->event_id.header,
> + &sample, event);
> + ret = perf_output_begin(&handle, event,
> + ksymbol_event->event_id.header.size);
> + if (ret)
> + return;
> +
> + perf_output_put(&handle, ksymbol_event->event_id);
> + __output_copy(&handle, ksymbol_event->name, ksymbol_event->name_len);
> + perf_event__output_id_sample(event, &handle, &sample);
> +
> + perf_output_end(&handle);
> +}
> +
> +void perf_event_ksymbol(u16 ksym_type, u64 addr, u32 len, bool unregister,
> + perf_ksymbol_get_name_f get_name, void *data)
> +{
> + struct perf_ksymbol_event ksymbol_event;
> + char name[KSYM_NAME_LEN];
> + u16 flags = 0;
> + int name_len;
> +
> + if (!atomic_read(&nr_ksymbol_events))
> + return;
> +
> + if (ksym_type >= PERF_RECORD_KSYMBOL_TYPE_MAX ||
> + ksym_type == PERF_RECORD_KSYMBOL_TYPE_UNKNOWN)
> + goto err;
> +
> + get_name(name, KSYM_NAME_LEN, data);
> + name_len = strlen(name) + 1;
> + while (!IS_ALIGNED(name_len, sizeof(u64)))
> + name[name_len++] = '\0';
> + BUILD_BUG_ON(KSYM_NAME_LEN % sizeof(u64));
> +
> + if (unregister)
> + flags |= PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER;
> +
> + ksymbol_event = (struct perf_ksymbol_event){
> + .name = name,
> + .name_len = name_len,
> + .event_id = {
> + .header = {
> + .type = PERF_RECORD_KSYMBOL,
> + .size = sizeof(ksymbol_event.event_id) +
> + name_len,
> + },
> + .addr = addr,
> + .len = len,
> + .ksym_type = ksym_type,
> + .flags = flags,
> + },
> + };
> +
> + perf_iterate_sb(perf_event_ksymbol_output, &ksymbol_event, NULL);
> + return;
> +err:
> + WARN_ONCE(1, "%s: Invalid KSYMBOL type 0x%x\n", __func__, ksym_type);
> +}
> +
> void perf_event_itrace_started(struct perf_event *event)
> {
> event->attach_state |= PERF_ATTACH_ITRACE;
> @@ -9900,6 +9994,8 @@ static void account_event(struct perf_event *event)
> inc = true;
> if (is_cgroup_event(event))
> inc = true;
> + if (event->attr.ksymbol)
> + atomic_inc(&nr_ksymbol_events);
>
> if (inc) {
> /*
> --
> 2.17.1
--
- Arnaldo
next prev parent reply other threads:[~2019-01-10 18:24 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-09 19:21 [PATCH v6 perf, bpf-next 0/7] reveal invisible bpf programs Song Liu
2019-01-09 19:21 ` Song Liu
2019-01-09 19:21 ` [PATCH v6 perf, bpf-next 1/7] perf, bpf: Introduce PERF_RECORD_KSYMBOL Song Liu
2019-01-09 19:21 ` Song Liu
2019-01-10 18:24 ` Arnaldo Carvalho de Melo [this message]
2019-01-10 18:24 ` Arnaldo Carvalho de Melo
2019-01-10 18:40 ` Song Liu
2019-01-10 18:40 ` Song Liu
2019-01-10 18:55 ` Arnaldo Carvalho de Melo
2019-01-10 18:55 ` Arnaldo Carvalho de Melo
2019-01-10 19:30 ` Song Liu
2019-01-10 19:30 ` Song Liu
2019-01-10 19:45 ` Song Liu
2019-01-10 19:45 ` Song Liu
2019-01-11 1:05 ` David Ahern
2019-01-11 1:05 ` David Ahern
2019-01-10 19:52 ` Arnaldo Carvalho de Melo
2019-01-10 19:52 ` Arnaldo Carvalho de Melo
2019-01-09 19:21 ` [PATCH v6 perf, bpf-next 2/7] sync tools/include/uapi/linux/perf_event.h Song Liu
2019-01-09 19:21 ` Song Liu
2019-01-09 19:21 ` [PATCH v6 perf, bpf-next 3/7] perf, bpf: introduce PERF_RECORD_BPF_EVENT Song Liu
2019-01-10 3:06 ` Alexei Starovoitov
2019-01-10 3:06 ` Alexei Starovoitov
2019-01-09 19:21 ` [PATCH v6 perf, bpf-next 4/7] sync tools/include/uapi/linux/perf_event.h Song Liu
2019-01-09 19:21 ` Song Liu
2019-01-09 19:21 ` [PATCH v6 perf, bpf-next 5/7] perf util: handle PERF_RECORD_KSYMBOL Song Liu
2019-01-09 19:21 ` Song Liu
2019-01-09 19:21 ` [PATCH v6 perf, bpf-next 6/7] perf util: handle PERF_RECORD_BPF_EVENT Song Liu
2019-01-09 19:21 ` Song Liu
2019-01-09 19:21 ` [PATCH v6 perf, bpf-next 7/7] perf tools: synthesize PERF_RECORD_* for loaded BPF programs Song Liu
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=20190110182403.GN22483@kernel.org \
--to=acme@kernel.org \
--cc=ast@kernel.org \
--cc=daniel@iogearbox.net \
--cc=kernel-team@fb.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=songliubraving@fb.com \
/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).