linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiri Olsa <olsajiri@gmail.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Andrii Nakryiko <andrii@kernel.org>,
	lkml <linux-kernel@vger.kernel.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Ingo Molnar <mingo@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Namhyung Kim <namhyung@kernel.org>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Ian Rogers <irogers@google.com>,
	"linux-perf-use." <linux-perf-users@vger.kernel.org>,
	bpf <bpf@vger.kernel.org>
Subject: Re: [PATCH 3/3] perf tools: Rework prologue generation code
Date: Sun, 20 Feb 2022 14:44:51 +0100	[thread overview]
Message-ID: <YhJF00d9baPtXjzH@krava> (raw)
In-Reply-To: <CAEf4BzZaFWhWf73JbfO7gLi82Nn4ma-qmaZBPij=giNzzoSCTQ@mail.gmail.com>

On Fri, Feb 18, 2022 at 11:55:16AM -0800, Andrii Nakryiko wrote:
> On Fri, Feb 18, 2022 at 1:01 AM Jiri Olsa <olsajiri@gmail.com> wrote:
> >
> > On Thu, Feb 17, 2022 at 01:53:16PM -0800, Andrii Nakryiko wrote:
> > > On Thu, Feb 17, 2022 at 5:19 AM Jiri Olsa <jolsa@kernel.org> wrote:
> > > >
> > > > Some functions we use now for bpf prologue generation are
> > > > going to be deprecated, so reworking the current code not
> > > > to use them.
> > > >
> > > > We need to replace following functions/struct:
> > > >    bpf_program__set_prep
> > > >    bpf_program__nth_fd
> > > >    struct bpf_prog_prep_result
> > > >
> > > > Current code uses bpf_program__set_prep to hook perf callback
> > > > before the program is loaded and provide new instructions with
> > > > the prologue.
> > > >
> > > > We workaround this by using objects's 'unloaded' programs instructions
> > > > for that specific program and load new ebpf programs with prologue
> > > > using separate bpf_prog_load calls.
> > > >
> > > > We keep new ebpf program instances descriptors in bpf programs
> > > > private struct.
> > > >
> > > > Suggested-by: Andrii Nakryiko <andrii@kernel.org>
> > > > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > > > ---
> > > >  tools/perf/util/bpf-loader.c | 122 +++++++++++++++++++++++++++++------
> > > >  1 file changed, 104 insertions(+), 18 deletions(-)
> > > >
> > >
> > > [...]
> > >
> > > >  errout:
> > > > @@ -696,7 +718,7 @@ static int hook_load_preprocessor(struct bpf_program *prog)
> > > >         struct bpf_prog_priv *priv = program_priv(prog);
> > > >         struct perf_probe_event *pev;
> > > >         bool need_prologue = false;
> > > > -       int err, i;
> > > > +       int i;
> > > >
> > > >         if (IS_ERR_OR_NULL(priv)) {
> > > >                 pr_debug("Internal error when hook preprocessor\n");
> > > > @@ -727,6 +749,12 @@ static int hook_load_preprocessor(struct bpf_program *prog)
> > > >                 return 0;
> > > >         }
> > > >
> > > > +       /*
> > > > +        * Do not load programs that need prologue, because we need
> > > > +        * to add prologue first, check bpf_object__load_prologue.
> > > > +        */
> > > > +       bpf_program__set_autoload(prog, false);
> > >
> > > if you set autoload to false, program instructions might be invalid in
> > > the end. Libbpf doesn't apply some (all?) relocations to such
> > > programs, doesn't resolve CO-RE, etc, etc. You have to let
> > > "prototypal" BPF program to be loaded before you can grab final
> > > instructions. It's not great, but in your case it should work, right?
> >
> > hum, do we care? it should all be done when the 'new' program with
> > the prologue is loaded, right?
> 
> yeah, you should care. If there is any BPF map involved, it is
> properly resolved to correct FD (which is put into ldimm64 instruction
> in BPF program code) during the load. If program is not autoloaded,
> this is skipped. Same for any global variable or subprog call (if it's
> not always inlined). So you very much should care for any non-trivial
> program.

ah too bad.. all that is in the load path, ok

> 
> >
> > I switched it off because the verifier failed to load the program
> > without the prologue.. because in the original program there's no
> > code to grab the arguments that the rest of the code depends on,
> > so the verifier sees invalid access
> 
> Do you have an example of C code and corresponding BPF instructions
> before/after prologue generation? Just curious to see in details how
> this is done.

so with following example:

	SEC("func=do_sched_setscheduler param->sched_priority@user")
	int bpf_func__setscheduler(void *ctx, int err, int param)
	{
		char fmt[] = "prio: %ld";
		bpf_trace_printk(fmt, sizeof(fmt), param);
		return 1;
	}

perf will attach the code to do_sched_setscheduler function,
and read 'param->sched_priority' into 'param' argument

so the resulting clang object expects 'param' to be in R3

	0000000000000000 <bpf_func__setscheduler>:
	       0:       b7 01 00 00 64 00 00 00 r1 = 100
	       1:       6b 1a f8 ff 00 00 00 00 *(u16 *)(r10 - 8) = r1
	       2:       18 01 00 00 70 72 69 6f 00 00 00 00 3a 20 25 6c r1 = 77926701655
	       4:       7b 1a f0 ff 00 00 00 00 *(u64 *)(r10 - 16) = r1
	       5:       bf a1 00 00 00 00 00 00 r1 = r10
	       6:       07 01 00 00 f0 ff ff ff r1 += -16
	       7:       b7 02 00 00 0a 00 00 00 r2 = 10
	       8:       85 00 00 00 06 00 00 00 call 6
	       9:       b7 00 00 00 01 00 00 00 r0 = 1
	      10:       95 00 00 00 00 00 00 00 exit

and R3 is loaded in the prologue code (first 15 instructions)
and it also sets 'err' (R2) with the result of the reading:

	   0: (bf) r6 = r1
	   1: (79) r3 = *(u64 *)(r6 +96)
	   2: (bf) r7 = r10
	   3: (07) r7 += -8
	   4: (7b) *(u64 *)(r10 -8) = r3
	   5: (b7) r2 = 8
	   6: (bf) r1 = r7
	   7: (85) call bpf_probe_read_user#-60848
	   8: (55) if r0 != 0x0 goto pc+2
	   9: (61) r3 = *(u32 *)(r10 -8)
	  10: (05) goto pc+3
	  11: (b7) r2 = 1
	  12: (b7) r3 = 0
	  13: (05) goto pc+1
	  14: (b7) r2 = 0
	  15: (bf) r1 = r6

	  16: (b7) r1 = 100
	  17: (6b) *(u16 *)(r10 -8) = r1
	  18: (18) r1 = 0x6c25203a6f697270
	  20: (7b) *(u64 *)(r10 -16) = r1
	  21: (bf) r1 = r10
	  22: (07) r1 += -16
	  23: (b7) r2 = 10
	  24: (85) call bpf_trace_printk#-54848
	  25: (b7) r0 = 1
	  26: (95) exit


I'm still scratching my head how to workaround this.. we do want maps
and all the other updates to the code, but verifier won't let it pass
without the prologue code

jirka

  reply	other threads:[~2022-02-20 13:44 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-17 13:19 [PATCHv2 0/3] perf/bpf: Replace deprecated code Jiri Olsa
2022-02-17 13:19 ` [PATCH 1/3] perf tools: Remove bpf_program__set_priv/bpf_program__priv usage Jiri Olsa
2022-02-17 21:47   ` Andrii Nakryiko
2022-02-18  9:01     ` Jiri Olsa
2022-02-17 13:19 ` [PATCH 2/3] perf tools: Remove bpf_map__set_priv/bpf_map__priv usage Jiri Olsa
2022-02-17 21:49   ` Andrii Nakryiko
2022-02-18  9:01     ` Jiri Olsa
2022-02-17 13:19 ` [PATCH 3/3] perf tools: Rework prologue generation code Jiri Olsa
2022-02-17 21:53   ` Andrii Nakryiko
2022-02-18  9:01     ` Jiri Olsa
2022-02-18 13:03       ` Jiri Olsa
2022-02-18 14:22         ` Jiri Olsa
2022-02-18 19:55       ` Andrii Nakryiko
2022-02-20 13:44         ` Jiri Olsa [this message]
     [not found]           ` <aa29a73b-b40d-6adf-2252-308917603f05@fb.com>
2022-02-20 23:10             ` Jiri Olsa
2022-02-23 22:29           ` Andrii Nakryiko
2022-02-25 12:14             ` Jiri Olsa
2022-02-25 14:32               ` Arnaldo Carvalho de Melo
2022-02-17 21:55 ` [PATCHv2 0/3] perf/bpf: Replace deprecated code Andrii Nakryiko
2022-02-18  9:01   ` Jiri Olsa

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=YhJF00d9baPtXjzH@krava \
    --to=olsajiri@gmail.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@kernel.org \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=andrii.nakryiko@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=irogers@google.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@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).