diff mbox series

[bpf-next,1/3] perf/core: Prepare sample data before calling BPF

Message ID 20221101052340.1210239-2-namhyung@kernel.org (mailing list archive)
State Changes Requested
Delegated to: BPF
Headers show
Series bpf: Add bpf_perf_event_read_sample() helper (v1) | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-VM_Test-24 success Logs for test_verifier on x86_64 with llvm-16
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 42 this patch: 42
netdev/cc_maintainers warning 4 maintainers not CCed: alexander.shishkin@linux.intel.com mark.rutland@arm.com linux-perf-users@vger.kernel.org mingo@redhat.com
netdev/build_clang success Errors and warnings before: 5 this patch: 5
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 42 this patch: 42
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 58 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-1 pending Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-5 success Logs for llvm-toolchain
bpf/vmtest-bpf-next-VM_Test-6 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-3 success Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-4 success Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-2 success Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-8 success Logs for test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for test_maps on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-11 success Logs for test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-15 success Logs for test_progs_no_alu32 on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-16 success Logs for test_progs_no_alu32_parallel on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 success Logs for test_progs_no_alu32_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-20 success Logs for test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-12 success Logs for test_progs on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-13 success Logs for test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for test_progs_parallel on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for test_progs_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-22 success Logs for test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-7 success Logs for test_maps on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for test_progs on s390x with gcc

Commit Message

Namhyung Kim Nov. 1, 2022, 5:23 a.m. UTC
To allow bpf overflow handler to access the perf sample data, it needs to
prepare missing but requested data before calling the handler.

I'm taking a conservative approach to allow a list of sample formats only
instead of allowing them all.  For now, IP and ADDR data are allowed and
I think it's good enough to build and verify general BPF-based sample
filters for perf events.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 kernel/events/core.c | 40 +++++++++++++++++++++++++++++++---------
 1 file changed, 31 insertions(+), 9 deletions(-)

Comments

Jiri Olsa Nov. 1, 2022, 10:03 a.m. UTC | #1
On Mon, Oct 31, 2022 at 10:23:38PM -0700, Namhyung Kim wrote:
> To allow bpf overflow handler to access the perf sample data, it needs to
> prepare missing but requested data before calling the handler.
> 
> I'm taking a conservative approach to allow a list of sample formats only
> instead of allowing them all.  For now, IP and ADDR data are allowed and
> I think it's good enough to build and verify general BPF-based sample
> filters for perf events.
> 
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
>  kernel/events/core.c | 40 +++++++++++++++++++++++++++++++---------
>  1 file changed, 31 insertions(+), 9 deletions(-)
> 
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index aefc1e08e015..519f30c33a24 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -7329,8 +7329,10 @@ void perf_prepare_sample(struct perf_event_header *header,
>  	filtered_sample_type = sample_type & ~data->sample_flags;
>  	__perf_event_header__init_id(header, data, event, filtered_sample_type);
>  
> -	if (sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_CODE_PAGE_SIZE))
> -		data->ip = perf_instruction_pointer(regs);
> +	if (sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_CODE_PAGE_SIZE)) {
> +		if (filtered_sample_type & PERF_SAMPLE_IP)
> +			data->ip = perf_instruction_pointer(regs);
> +	}
>  
>  	if (sample_type & PERF_SAMPLE_CALLCHAIN) {
>  		int size = 1;
> @@ -10006,6 +10008,32 @@ static void perf_event_free_filter(struct perf_event *event)
>  }
>  
>  #ifdef CONFIG_BPF_SYSCALL
> +static void bpf_prepare_sample(struct bpf_prog *prog,
> +			       struct perf_event *event,
> +			       struct perf_sample_data *data,
> +			       struct pt_regs *regs)
> +{
> +	u64 filtered_sample_type;
> +
> +	filtered_sample_type = event->attr.sample_type & ~data->sample_flags;

could we add the same comment in here as is in perf_prepare_sample

        /*
         * Clear the sample flags that have already been done by the
         * PMU driver.
         */

it took me while to recall while we set addr to 0 in here ;-)

thanks,
jirka

> +
> +	if (prog->call_get_stack &&
> +	    (filtered_sample_type & PERF_SAMPLE_CALLCHAIN)) {
> +		data->callchain = perf_callchain(event, regs);
> +		data->sample_flags |= PERF_SAMPLE_CALLCHAIN;
> +	}
> +
> +	if (filtered_sample_type & PERF_SAMPLE_IP) {
> +		data->ip = perf_instruction_pointer(regs);
> +		data->sample_flags |= PERF_SAMPLE_IP;
> +	}
> +
> +	if (filtered_sample_type & PERF_SAMPLE_ADDR) {
> +		data->addr = 0;
> +		data->sample_flags |= PERF_SAMPLE_ADDR;
> +	}
> +}
> +
>  static void bpf_overflow_handler(struct perf_event *event,
>  				 struct perf_sample_data *data,
>  				 struct pt_regs *regs)
> @@ -10023,13 +10051,7 @@ static void bpf_overflow_handler(struct perf_event *event,
>  	rcu_read_lock();
>  	prog = READ_ONCE(event->prog);
>  	if (prog) {
> -		if (prog->call_get_stack &&
> -		    (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) &&
> -		    !(data->sample_flags & PERF_SAMPLE_CALLCHAIN)) {
> -			data->callchain = perf_callchain(event, regs);
> -			data->sample_flags |= PERF_SAMPLE_CALLCHAIN;
> -		}
> -
> +		bpf_prepare_sample(prog, event, data, regs);
>  		ret = bpf_prog_run(prog, &ctx);
>  	}
>  	rcu_read_unlock();
> -- 
> 2.38.1.273.g43a17bfeac-goog
>
Namhyung Kim Nov. 4, 2022, 6:03 a.m. UTC | #2
Hi Jiri,

On Tue, Nov 1, 2022 at 3:03 AM Jiri Olsa <olsajiri@gmail.com> wrote:
>
> On Mon, Oct 31, 2022 at 10:23:38PM -0700, Namhyung Kim wrote:
> > To allow bpf overflow handler to access the perf sample data, it needs to
> > prepare missing but requested data before calling the handler.
> >
> > I'm taking a conservative approach to allow a list of sample formats only
> > instead of allowing them all.  For now, IP and ADDR data are allowed and
> > I think it's good enough to build and verify general BPF-based sample
> > filters for perf events.
> >
> > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> > ---
> >  kernel/events/core.c | 40 +++++++++++++++++++++++++++++++---------
> >  1 file changed, 31 insertions(+), 9 deletions(-)
> >
> > diff --git a/kernel/events/core.c b/kernel/events/core.c
> > index aefc1e08e015..519f30c33a24 100644
> > --- a/kernel/events/core.c
> > +++ b/kernel/events/core.c
> > @@ -7329,8 +7329,10 @@ void perf_prepare_sample(struct perf_event_header *header,
> >       filtered_sample_type = sample_type & ~data->sample_flags;
> >       __perf_event_header__init_id(header, data, event, filtered_sample_type);
> >
> > -     if (sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_CODE_PAGE_SIZE))
> > -             data->ip = perf_instruction_pointer(regs);
> > +     if (sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_CODE_PAGE_SIZE)) {
> > +             if (filtered_sample_type & PERF_SAMPLE_IP)
> > +                     data->ip = perf_instruction_pointer(regs);
> > +     }
> >
> >       if (sample_type & PERF_SAMPLE_CALLCHAIN) {
> >               int size = 1;
> > @@ -10006,6 +10008,32 @@ static void perf_event_free_filter(struct perf_event *event)
> >  }
> >
> >  #ifdef CONFIG_BPF_SYSCALL
> > +static void bpf_prepare_sample(struct bpf_prog *prog,
> > +                            struct perf_event *event,
> > +                            struct perf_sample_data *data,
> > +                            struct pt_regs *regs)
> > +{
> > +     u64 filtered_sample_type;
> > +
> > +     filtered_sample_type = event->attr.sample_type & ~data->sample_flags;
>
> could we add the same comment in here as is in perf_prepare_sample
>
>         /*
>          * Clear the sample flags that have already been done by the
>          * PMU driver.
>          */
>
> it took me while to recall while we set addr to 0 in here ;-)

Sorry about that! :)  I'll add the comment.

Thanks,
Namhyung


>
> > +
> > +     if (prog->call_get_stack &&
> > +         (filtered_sample_type & PERF_SAMPLE_CALLCHAIN)) {
> > +             data->callchain = perf_callchain(event, regs);
> > +             data->sample_flags |= PERF_SAMPLE_CALLCHAIN;
> > +     }
> > +
> > +     if (filtered_sample_type & PERF_SAMPLE_IP) {
> > +             data->ip = perf_instruction_pointer(regs);
> > +             data->sample_flags |= PERF_SAMPLE_IP;
> > +     }
> > +
> > +     if (filtered_sample_type & PERF_SAMPLE_ADDR) {
> > +             data->addr = 0;
> > +             data->sample_flags |= PERF_SAMPLE_ADDR;
> > +     }
> > +}
> > +
> >  static void bpf_overflow_handler(struct perf_event *event,
> >                                struct perf_sample_data *data,
> >                                struct pt_regs *regs)
> > @@ -10023,13 +10051,7 @@ static void bpf_overflow_handler(struct perf_event *event,
> >       rcu_read_lock();
> >       prog = READ_ONCE(event->prog);
> >       if (prog) {
> > -             if (prog->call_get_stack &&
> > -                 (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) &&
> > -                 !(data->sample_flags & PERF_SAMPLE_CALLCHAIN)) {
> > -                     data->callchain = perf_callchain(event, regs);
> > -                     data->sample_flags |= PERF_SAMPLE_CALLCHAIN;
> > -             }
> > -
> > +             bpf_prepare_sample(prog, event, data, regs);
> >               ret = bpf_prog_run(prog, &ctx);
> >       }
> >       rcu_read_unlock();
> > --
> > 2.38.1.273.g43a17bfeac-goog
> >
diff mbox series

Patch

diff --git a/kernel/events/core.c b/kernel/events/core.c
index aefc1e08e015..519f30c33a24 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7329,8 +7329,10 @@  void perf_prepare_sample(struct perf_event_header *header,
 	filtered_sample_type = sample_type & ~data->sample_flags;
 	__perf_event_header__init_id(header, data, event, filtered_sample_type);
 
-	if (sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_CODE_PAGE_SIZE))
-		data->ip = perf_instruction_pointer(regs);
+	if (sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_CODE_PAGE_SIZE)) {
+		if (filtered_sample_type & PERF_SAMPLE_IP)
+			data->ip = perf_instruction_pointer(regs);
+	}
 
 	if (sample_type & PERF_SAMPLE_CALLCHAIN) {
 		int size = 1;
@@ -10006,6 +10008,32 @@  static void perf_event_free_filter(struct perf_event *event)
 }
 
 #ifdef CONFIG_BPF_SYSCALL
+static void bpf_prepare_sample(struct bpf_prog *prog,
+			       struct perf_event *event,
+			       struct perf_sample_data *data,
+			       struct pt_regs *regs)
+{
+	u64 filtered_sample_type;
+
+	filtered_sample_type = event->attr.sample_type & ~data->sample_flags;
+
+	if (prog->call_get_stack &&
+	    (filtered_sample_type & PERF_SAMPLE_CALLCHAIN)) {
+		data->callchain = perf_callchain(event, regs);
+		data->sample_flags |= PERF_SAMPLE_CALLCHAIN;
+	}
+
+	if (filtered_sample_type & PERF_SAMPLE_IP) {
+		data->ip = perf_instruction_pointer(regs);
+		data->sample_flags |= PERF_SAMPLE_IP;
+	}
+
+	if (filtered_sample_type & PERF_SAMPLE_ADDR) {
+		data->addr = 0;
+		data->sample_flags |= PERF_SAMPLE_ADDR;
+	}
+}
+
 static void bpf_overflow_handler(struct perf_event *event,
 				 struct perf_sample_data *data,
 				 struct pt_regs *regs)
@@ -10023,13 +10051,7 @@  static void bpf_overflow_handler(struct perf_event *event,
 	rcu_read_lock();
 	prog = READ_ONCE(event->prog);
 	if (prog) {
-		if (prog->call_get_stack &&
-		    (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) &&
-		    !(data->sample_flags & PERF_SAMPLE_CALLCHAIN)) {
-			data->callchain = perf_callchain(event, regs);
-			data->sample_flags |= PERF_SAMPLE_CALLCHAIN;
-		}
-
+		bpf_prepare_sample(prog, event, data, regs);
 		ret = bpf_prog_run(prog, &ctx);
 	}
 	rcu_read_unlock();