bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eduard Zingerman <eddyz87@gmail.com>
To: Edward Cree <ecree.xilinx@gmail.com>,
	bpf@vger.kernel.org, ast@kernel.org
Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev,
	kernel-team@fb.com, yhs@fb.com
Subject: Re: [PATCH bpf-next v3 1/1] docs/bpf: Add description of register liveness tracking algorithm
Date: Wed, 01 Feb 2023 17:14:33 +0200	[thread overview]
Message-ID: <48f840c1b879728bda69e059f19c2cea642c1e97.camel@gmail.com> (raw)
In-Reply-To: <99a2eaa9-aebb-f0c8-1d13-62e1533631e7@gmail.com>

On Wed, 2023-02-01 at 11:00 +0000, Edward Cree wrote:
> On 31/01/2023 18:11, Eduard Zingerman wrote:
> > This is a followup for [1], adds an overview for the register liveness
> > tracking, covers the following points:
> > - why register liveness tracking is useful;
> > - how register parentage chains are constructed;
> > - how liveness marks are applied using the parentage chains.
> > 
> > [1] https://lore.kernel.org/bpf/CAADnVQKs2i1iuZ5SUGuJtxWVfGYR9kDgYKhq3rNV+kBLQCu7rA@mail.gmail.com/
> > 
> > Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
> > ---
> >  Documentation/bpf/verifier.rst | 280 +++++++++++++++++++++++++++++++++
> >  1 file changed, 280 insertions(+)
> ...
> > +  Current    +-------------------------------+
> > +  state      | r0 | r1-r5 | r6-r9 | fp-8 ... |
> > +             +-------------------------------+
> > +                             \
> > +                               r6 read mark is propagated via
> > +                               these links all the way up to
> > +                               checkpoint #1.

Hi Edward, could you please review the updates below?

> Perhaps explicitly mention here that the reason it doesn't
>  propagate to checkpoint #0 (despite the arrow) is that there's
>  a write mark on c1[r6].

I can update this remark as follows:

---- 8< ---------------------------

  Current    +-------------------------------+
  state      | r0 | r1-r5 | r6-r9 | fp-8 ... |
             +-------------------------------+
                             \
                               r6 read mark is propagated via these links
                               all the way up to checkpoint #1.
                               The checkpoint #1 contains a write mark for r6
                               because of instruction (1), thus read propagation
                               does not reach checkpoint #0 (see section below).

--------------------------- >8 ----

> 
> Also worth mentioning somewhere that write marks are really a
>  property of the arrow, not the state — a write mark in c#1 tells
>  us that the straight-line code from c#0 to c#1 contains a write
>  (thus 'breaking' that arrow for read mark propagation); it lives
>  in c#1's data structures because it's c#1 that needs to 'know'
>  about it, whereas c#0 (and its parents) need to 'know' about any
>  *reads* in the straight-line code from c#0 to c#1 (but these are
>  of no interest to c#1).
> I sometimes summarise this with the phrase "read up, write down",
>  though idk how useful that is to anyone outside of my head ;)

TBH, I'm a bit hesitant to put such note on the diagram because
liveness tracking algorithm is not yet discussed. I've updated the
next section a bit to reflect this, please see below.

> 
> > +Liveness marks tracking
> > +=======================
> > +
> > +For each processed instruction, the verifier propagates information about reads
> > +up the parentage chain and saves information about writes in the current state.
> > +The information about reads is propagated by function ``mark_reg_read()`` which
> > +could be summarized as follows::
> > +
> > +  mark_reg_read(struct bpf_reg_state *state):
> > +      parent = state->parent
> > +      while parent:
> > +          if parent->live & REG_LIVE_WRITTEN:
> > +              break
> This isn't correct; we look at `state->live` here, because if in
>  the straight-line code since the last checkpoint (parent)
>  there's a write to this register, then reads should not
>  propagate to `parent`.

You are correct, thank you for catching it (:big facepalm image:).

> Then there's the complication of the `writes` variable in
>  mark_reg_read(); that's explained by the comment on
>  propagate_liveness(), which AFAICT you don't cover in your
>  doc section about that.  (And note that `writes` is only ever
>  false for the first iteration through the mark_reg_read() loop).

I intentionally avoided description of this mechanics to keep some
balance between clarity and level of details. Added a note that there
is some additional logic.

> 
> > +          if parent->live & REG_LIVE_READ64:
> > +              break
> > +          parent->live |= REG_LIVE_READ64
> > +          state = parent
> > +          parent = state->parent
> > +
> > +Note: details about REG_LIVE_READ32 are omitted.
> > +
> > +Also note: the read marks are applied to the **parent** state while write marks
> > +are applied to the **current** state.
> May be worth stating that the principle of the algorithm is that
>  read marks propagate back along the chain until they hit a write
>  mark, which 'screens off' earlier states from the read.
> Your doc implies this but afaict never states it explicitly, and
>  I think it makes the algo easier to understand for someone who
>  doesn't already know what it's all about.

All in all here is updated start of the section:

---- 8< ---------------------------

The principle of the algorithm is that read marks propagate back along the state
parentage chain until they hit a write mark, which 'screens off' earlier states
from the read. The information about reads is propagated by function
``mark_reg_read()`` which could be summarized as follows::

  mark_reg_read(struct bpf_reg_state *state, ...):
      parent = state->parent
      while parent:
          if state->live & REG_LIVE_WRITTEN:
              break
          if parent->live & REG_LIVE_READ64:
              break
          parent->live |= REG_LIVE_READ64
          state = parent
          parent = state->parent

Notes:
* The read marks are applied to the **parent** state while write marks are
  applied to the **current** state. The write mark on a register or stack slot
  means that it is updated by some instruction verified within current state.
* Details about REG_LIVE_READ32 are omitted.
* Function ``propagate_liveness()`` (see section :ref:`Read marks propagation
  for cache hits`) might override the first parent link, please refer to the
  comments in the source code for further details.

--------------------------- >8 ----

> 
> Apart from that, this is great.  I particularly like your diagram
>  of the parentage chains.

Thanks a lot for commenting!
wdyt about my updates?


  reply	other threads:[~2023-02-01 15:15 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-31 18:11 [PATCH bpf-next v3 0/1] docs/bpf: Add description of register liveness tracking algorithm Eduard Zingerman
2023-01-31 18:11 ` [PATCH bpf-next v3 1/1] " Eduard Zingerman
2023-02-01 11:00   ` Edward Cree
2023-02-01 15:14     ` Eduard Zingerman [this message]
2023-02-01 16:13       ` Edward Cree
2023-02-01 18:28         ` Eduard Zingerman
2023-02-02  9:25           ` Edward Cree

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=48f840c1b879728bda69e059f19c2cea642c1e97.camel@gmail.com \
    --to=eddyz87@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=ecree.xilinx@gmail.com \
    --cc=kernel-team@fb.com \
    --cc=martin.lau@linux.dev \
    --cc=yhs@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).