bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alan Maguire <alan.maguire@oracle.com>
To: andrii@kernel.org, jolsa@kernel.org, acme@redhat.com,
	quentin@isovalent.com
Cc: eddyz87@gmail.com, mykolal@fb.com, ast@kernel.org,
	daniel@iogearbox.net, martin.lau@linux.dev, song@kernel.org,
	yonghong.song@linux.dev, john.fastabend@gmail.com,
	kpsingh@kernel.org, sdf@google.com, haoluo@google.com,
	houtao1@huawei.com, bpf@vger.kernel.org, masahiroy@kernel.org,
	mcgrof@kernel.org, nathan@kernel.org,
	Alan Maguire <alan.maguire@oracle.com>
Subject: [RFC bpf-next 00/13] bpf: support resilient split BTF
Date: Fri, 22 Mar 2024 10:24:41 +0000	[thread overview]
Message-ID: <20240322102455.98558-1-alan.maguire@oracle.com> (raw)

Split BPF Type Format (BTF) provides huge advantages in that kernel
modules only have to provide type information for types that they do not
share with the core kernel; for core kernel types, split BTF refers to
core kernel BTF type ids.  So for a STRUCT sk_buff, a module that
uses that structure (or a pointer to it) simply needs to refer to the
core kernel type id, saving the need to define the structure and its many
dependents.  This cuts down on duplication and makes BTF as compact
as possible.

However, there is a downside.  This scheme requires the references from
split BTF to base BTF to be valid not just at encoding time, but at use
time (when the module is loaded).  Even a small change in kernel types
can perturb the type ids in core kernel BTF, and due to pahole's
parallel processing of compilation units, even an unchanged kernel can
have different type ids if BTF is re-generated.  So we have a robustness
problem for split BTF for cases where a module is not always compiled at
the same time as the kernel.  This problem is particularly acute for
distros which generally want module builders to be able to compile a
module for the lifetime of a Linux stable-based release, and have it
continue to be valid over the lifetime of that release, even as changes
in data structures (and hence BTF types) accrue.  Today it's not
possible to generate BTF for modules that works beyond the initial
kernel it is compiled against - kernel bugfixes etc invalidate the split
BTF references to vmlinux BTF, and BTF is no longer usable for the
module.

The goal of this series is to provide options to provide additional
context for cases like this.  That context comes in the form of "base
reference" BTF; it stands in for the base BTF, and contains
information about the types referenced from split BTF, but not their
full descriptions.  The modified split BTF will refer to type ids in
this .BTF.base_ref section, and when the kernel loads such modules it
will use the base reference BTF to map references from split BTF to the
current vmlinux BTF - a process of reconciling split BTF with the
currently-running kernel's vmlinux base BTF.

A module builder - using this series along with the pahole changes -
can then build a module with base reference BTF via

BTF_BASE_REF=1 make -C . M=path/2/module

For this to work, pahole will have to be built with libbpf based on
this series and with the patch titled

[RFC dwarves] btf_encoder: add base_ref BTF feature to generate split
BTF with base refs

The module will have a .BTF section (the split BTF) and a
.BTF.base_ref section.  The latter is small in size - base reference
BTF does not need full struct/union/enum information for named
types for example.  For 2667 modules built with base reference BTF,
the average size observed was 1556 bytes (stddev 1563).

Note that for the in-tree modules, this approach is not needed as
split and base BTF in the case of in-tree modules are always built
and re-built together.

The series first focuses on generating split BTF with base reference
BTF, and provides btf__parse_opts() which allows specification
of the section name from which to read BTF data, since we now have
both .BTF and .BTF.base_ref sections that can contain such data.

Then we add support to resolve_btfids for generating the .BTF.ids
section with reference to the .BTF.base_ref section - this ensures the
.BTF.ids match those used in the split/base reference BTF.

Finally the series provides the mechanism for reconciling split BTF with
a new base; the base reference BTF is used to map the references to base
BTF in the split BTF to the new base.  For the kernel, this
reconciliation process happens at module load time, and we reconcile
split BTF references to base BTF with the current vmlinux BTF.  .BTF.ids
need to be reconciled also.

So concretely, what happens is

- we generate split BTF in the .BTF section of a module that refers to
  types in the .BTF.base_ref section as base types; these are not full
  type descriptions but provide information about the base type.  So
  a STRUCT sk_buff would be represented as a FWD struct sk_buff in
  base reference BTF for example.
- when the module is loaded, the split BTF is reconciled with vmlinux
  BTF; in the case of the FWD struct sk_buff, we find the STRUCT sk_buff
  in vmlinux BTF and map all split BTF references to the base reference
  FWD sk_buff to the vmlinux BTF STRUCT sk_buff.

Support is also added to bpftool to be able to display split BTF
relative to its .BTF.base_ref section and display the reconciled form.

A previous approach to this problem [1] utilized standalone BTF for such
cases - where the BTF is not defined relative to base BTF so there is no
reconciliation required.  The problem with that approach is that from
the verifier perspective, some types are special, and having a custom
representation of a core kernel type that did not necessarily match the
current representation is not tenable.  So the approach taken here was
to preserve the split BTF model while minimizing the representation of
the context needed to reconcile split and current vmlinux BTF.

[1] https://lore.kernel.org/bpf/20231112124834.388735-14-alan.maguire@oracle.com/

Alan Maguire (13):
  libbpf: add support to btf__add_fwd() for ENUM64
  libbpf: add btf__new_split_base_ref() creating split BTF with
    reference base BTF
  selftests/bpf: test split base reference BTF generation
  libbpf: add btf__parse_opts() API for flexible BTF parsing
  bpftool: support displaying raw split BTF using base reference BTF as
    base
  kbuild,bpf: switch to using --btf_features for pahole v1.26 and later
  resolve_btfids: use .BTF.base_ref BTF as base BTF if -r option is used
  kbuild, bpf: add module-specific pahole/resolve_btfids flags for base
    reference BTF
  libbpf: split BTF reconciliation
  module, bpf: store BTF base reference pointer in struct module
  libbpf,bpf: share BTF reconcile-related code with kernel
  selftests/bpf: extend base reference tests cover BTF reconciliation
  bpftool: support displaying reconciled-with-base split BTF

 include/linux/btf.h                           |  29 +
 include/linux/module.h                        |   2 +
 kernel/bpf/Makefile                           |   8 +
 kernel/bpf/btf.c                              | 197 +++++-
 kernel/module/main.c                          |   2 +
 scripts/Makefile.btf                          |  12 +-
 scripts/Makefile.modfinal                     |   4 +-
 .../bpf/bpftool/Documentation/bpftool-btf.rst |  17 +
 tools/bpf/bpftool/btf.c                       |  33 +-
 tools/bpf/bpftool/main.c                      |  14 +-
 tools/bpf/bpftool/main.h                      |   2 +
 tools/bpf/resolve_btfids/main.c               |  17 +-
 tools/lib/bpf/Build                           |   2 +-
 tools/lib/bpf/btf.c                           | 434 +++++++++----
 tools/lib/bpf/btf.h                           |  56 ++
 tools/lib/bpf/btf_common.c                    | 146 +++++
 tools/lib/bpf/btf_reconcile.c                 | 614 ++++++++++++++++++
 tools/lib/bpf/libbpf.map                      |   3 +
 tools/lib/bpf/libbpf_internal.h               |   2 +
 .../bpf/prog_tests/btf_split_base_ref.c       | 254 ++++++++
 20 files changed, 1668 insertions(+), 180 deletions(-)
 create mode 100644 tools/lib/bpf/btf_common.c
 create mode 100644 tools/lib/bpf/btf_reconcile.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_split_base_ref.c

-- 
2.39.3


             reply	other threads:[~2024-03-22 10:25 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-22 10:24 Alan Maguire [this message]
2024-03-22 10:24 ` [RFC dwarves] btf_encoder: add base_ref BTF feature to generate split BTF with base refs Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 01/13] libbpf: add support to btf__add_fwd() for ENUM64 Alan Maguire
2024-03-29 21:59   ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 02/13] libbpf: add btf__new_split_base_ref() creating split BTF with reference base BTF Alan Maguire
2024-03-29 22:00   ` Andrii Nakryiko
2024-04-04 15:21     ` Alan Maguire
2024-04-04 22:49       ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 03/13] selftests/bpf: test split base reference BTF generation Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 04/13] libbpf: add btf__parse_opts() API for flexible BTF parsing Alan Maguire
2024-03-29 22:00   ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 05/13] bpftool: support displaying raw split BTF using base reference BTF as base Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 06/13] kbuild,bpf: switch to using --btf_features for pahole v1.26 and later Alan Maguire
2024-03-29 22:01   ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 07/13] resolve_btfids: use .BTF.base_ref BTF as base BTF if -r option is used Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 08/13] kbuild, bpf: add module-specific pahole/resolve_btfids flags for base reference BTF Alan Maguire
2024-03-23  2:50   ` Alexei Starovoitov
2024-03-25  9:51     ` Alan Maguire
2024-03-25 16:41       ` Alexei Starovoitov
2024-03-22 10:24 ` [RFC bpf-next 09/13] libbpf: split BTF reconciliation Alan Maguire
2024-03-29 22:01   ` Andrii Nakryiko
2024-04-05 10:06     ` Alan Maguire
2024-04-05 19:58       ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 10/13] module, bpf: store BTF base reference pointer in struct module Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 11/13] libbpf,bpf: share BTF reconcile-related code with kernel Alan Maguire
2024-03-29 22:04   ` Andrii Nakryiko
2024-04-01 15:58     ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 12/13] selftests/bpf: extend base reference tests cover BTF reconciliation Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 13/13] bpftool: support displaying reconciled-with-base split BTF Alan Maguire

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=20240322102455.98558-1-alan.maguire@oracle.com \
    --to=alan.maguire@oracle.com \
    --cc=acme@redhat.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=haoluo@google.com \
    --cc=houtao1@huawei.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=masahiroy@kernel.org \
    --cc=mcgrof@kernel.org \
    --cc=mykolal@fb.com \
    --cc=nathan@kernel.org \
    --cc=quentin@isovalent.com \
    --cc=sdf@google.com \
    --cc=song@kernel.org \
    --cc=yonghong.song@linux.dev \
    /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).