Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpf: Add 64bit enum value support #2953

Closed
wants to merge 13 commits into from

Conversation

kernel-patches-bot
Copy link

Pull request for series with
subject: bpf: Add 64bit enum value support
version: 1
url: https://patchwork.kernel.org/project/netdevbpf/list/?series=637423

@kernel-patches-bot
Copy link
Author

Master branch: 20b87e7
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=637423
version: 1

Kernel Patches Daemon and others added 11 commits May 9, 2022 08:24
Currently, BTF only supports upto 32bit enum value with BTF_KIND_ENUM.
But in kernel, some enum indeed has 64bit values, e.g.,
in uapi bpf.h, we have
  enum {
        BPF_F_INDEX_MASK                = 0xffffffffULL,
        BPF_F_CURRENT_CPU               = BPF_F_INDEX_MASK,
        BPF_F_CTXLEN_MASK               = (0xfffffULL << 32),
  };
In this case, BTF_KIND_ENUM will encode the value of BPF_F_CTXLEN_MASK
as 0, which certainly is incorrect.

This patch added a new btf kind, BTF_KIND_ENUM64, which permits
64bit value to cover the above use case. The BTF_KIND_ENUM64 has
the following three bytes followed by the common type:
  struct bpf_enum64 {
    __u32 nume_off;
    __u32 hi32;
    __u32 lo32;
  };
Currently, btf type section has an alignment of 4 as all element types
are u32. Representing the value with __u64 will introduce a pad
for bpf_enum64 and may also introduce misalignment for the 64bit value.
Hence, two members of hi32 and lo32 are chosen to avoid these issues.

The kflag is also introduced for BTF_KIND_ENUM and BTF_KIND_ENUM64
to indicate whether the value is signed or unsigned. The kflag intends
to provide consistent output of BTF C fortmat with the original
source code. For example, the original BTF_KIND_ENUM bit value is 0xffffffff.
The format C has two choices, print out 0xffffffff or -1 and current libbpf
prints out as unsigned value. But if the signedness is preserved in btf,
the value can be printed the same as the original source code.

The new BTF_KIND_ENUM64 is intended to support the enum value represented as
64bit value. But it can represent all BTF_KIND_ENUM values as well.
The value size of BTF_KIND_ENUM64 is encoded to 8 to represent its intent.
The compiler ([1]) and pahole will generate BTF_KIND_ENUM64 only if the value has
to be represented with 64 bits.

  [1] https://reviews.llvm.org/D124641

Signed-off-by: Yonghong Song <yhs@fb.com>
Currently, the libbpf limits the relocation value to be 32bit
since all current relocations have such a limit. But with
BTF_KIND_ENUM64 support, the enum value could be 64bit.
So let us permit 64bit relocation value in libbpf.

Signed-off-by: Yonghong Song <yhs@fb.com>
Currently, the 64bit relocation value in the instruction
is computed as follows:
  __u64 imm = insn[0].imm + ((__u64)insn[1].imm << 32)

Suppose insn[0].imm = -1 (0xffffffff) and insn[1].imm = 1.
With the above computation, insn[0].imm will first sign-extend
to 64bit -1 (0xffffffffFFFFFFFF) and then add 0x1FFFFFFFF,
producing incorrect value 0xFFFFFFFF. The correct value
should be 0x1FFFFFFFF.

Changing insn[0].imm to __u32 first will prevent 64bit sign
extension and fix the issue.

Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
Acked-by: Dave Marchevsky <davemarchevsky@fb.com>
Add BTF_KIND_ENUM64 support. Deprecated btf__add_enum() and
btf__add_enum_value() and introduced the following new APIs
  btf__add_enum32()
  btf__add_enum32_value()
  btf__add_enum64()
  btf__add_enum64_value()
due to new kind and introduction of kflag.

To support old kernel with enum64, the sanitization is
added to replace BTF_KIND_ENUM64 with a bunch of
pointer-to-void types.

The enum64 value relocation is also supported. The enum64
forward resolution, with enum type as forward declaration
and enum64 as the actual definition, is also supported.

Signed-off-by: Yonghong Song <yhs@fb.com>
Reported-by: kernel test robot <lkp@intel.com>
Add BTF_KIND_ENUM64 support.
For example, the following enum is defined in uapi bpf.h.
  $ cat core.c
  enum A {
        BPF_F_INDEX_MASK                = 0xffffffffULL,
        BPF_F_CURRENT_CPU               = BPF_F_INDEX_MASK,
        BPF_F_CTXLEN_MASK               = (0xfffffULL << 32),
  } g;
Compiled with
  clang -target bpf -O2 -g -c core.c
Using bpftool to dump types and generate format C file:
  $ bpftool btf dump file core.o
  ...
  [1] ENUM64 'A' size=8 vlen=3
        'BPF_F_INDEX_MASK' val=4294967295ULL
        'BPF_F_CURRENT_CPU' val=4294967295ULL
        'BPF_F_CTXLEN_MASK' val=4503595332403200ULL
  $ bpftool btf dump file core.o format c
  ...
  enum A {
        BPF_F_INDEX_MASK = 4294967295ULL,
        BPF_F_CURRENT_CPU = 4294967295ULL,
        BPF_F_CTXLEN_MASK = 4503595332403200ULL,
  };
  ...

The 64bit value is represented properly in BTF and C dump.

Signed-off-by: Yonghong Song <yhs@fb.com>
The kflag is supported now for BTF_KIND_ENUM.
So remove the test which tests verifier failure
due to existence of kflag.

With enum64 support in kernel and libbpf,
selftest btf_dump/btf_dump failed with
no-enum64 support llvm for the following
enum definition:
 enum e2 {
        C = 100,
        D = 4294967295,
        E = 0,
 };

With the no-enum64 support llvm, the signedness is
'signed' by default, and D (4294967295 = 0xffffffff)
will print as -1. With enum64 support llvm, the signedness
is 'unsigned' and the value of D will print as 4294967295.
To support both old and new compilers, this patch
changed the value to 268435455 = 0xfffffff which works
with both enum64 or non-enum64 support llvm.

Signed-off-by: Yonghong Song <yhs@fb.com>
Acked-by: Dave Marchevsky <davemarchevsky@fb.com>
Add tests to use the newer libbpf enum32/enum64 API functions
in selftest btf_write.

Signed-off-by: Yonghong Song <yhs@fb.com>
Add unit tests for basic BTF_KIND_ENUM64 encoding.

Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Add a test for enum64 value relocations.

Signed-off-by: Yonghong Song <yhs@fb.com>
@kernel-patches-bot
Copy link
Author

Master branch: 7b3a063
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=637423
version: 1

Certain subtests in selftests core_reloc and core_reloc_btfgen
requires llvm ENUM64 support in llvm15. If an older compiler
is used, these subtests will fail. Make this requirement clear
in selftests README.rst file.

Signed-off-by: Yonghong Song <yhs@fb.com>
Add BTF_KIND_ENUM64 documentation in btf.rst.
Also fixed a typo for section number for BTF_KIND_TYPE_TAG
from 2.2.17 to 2.2.18.

Signed-off-by: Yonghong Song <yhs@fb.com>
@kernel-patches-bot
Copy link
Author

At least one diff in series https://patchwork.kernel.org/project/netdevbpf/list/?series=637423 expired. Closing PR.

@kernel-patches-bot kernel-patches-bot deleted the series/637423=>bpf-next branch May 12, 2022 06:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants