mbox series

[v2,bpf-next,0/3] bpf: support module BTF in BTF display helpers

Message ID 1607107716-14135-1-git-send-email-alan.maguire@oracle.com (mailing list archive)
Headers show
Series bpf: support module BTF in BTF display helpers | expand

Message

Alan Maguire Dec. 4, 2020, 6:48 p.m. UTC
This series aims to add support to bpf_snprintf_btf() and
bpf_seq_printf_btf() allowing them to store string representations
of module-specific types, as well as the kernel-specific ones
they currently support.

Patch 1 removes the btf_module_mutex, as since we will need to
look up module BTF during BPF program execution, we don't want
to risk sleeping in the various contexts in which BPF can run.
The access patterns to the btf module list seem to conform to
classic list RCU usage so with a few minor tweaks this seems
workable.

Patch 2 replaces the unused flags field in struct btf_ptr with
an obj_id field,  allowing the specification of the id of a
BTF module.  If the value is 0, the core kernel vmlinux is
assumed to contain the type's BTF information.  Otherwise the
module with that id is used to identify the type.  If the
object-id based lookup fails, we again fall back to vmlinux
BTF.

Patch 3 is a selftest that uses veth (when built as a
module) and a kprobe to display both a module-specific
and kernel-specific type; both are arguments to veth_stats_rx().
Currently it looks up the module-specific type and object ids
using libbpf; in future, these lookups will likely be supported
directly in the BPF program via __builtin_btf_type_id(); but
I need to determine a good test to determine if that builtin
supports object ids.

Changes since RFC

- add patch to remove module mutex
- modify to use obj_id instead of module name as identifier
  in "struct btf_ptr" (Andrii)

Alan Maguire (3):
  bpf: eliminate btf_module_mutex as RCU synchronization can be used
  bpf: add module support to btf display helpers
  selftests/bpf: verify module-specific types can be shown via
    bpf_snprintf_btf

 include/linux/btf.h                                |  12 ++
 include/uapi/linux/bpf.h                           |  13 ++-
 kernel/bpf/btf.c                                   |  49 +++++---
 kernel/trace/bpf_trace.c                           |  44 ++++++--
 tools/include/uapi/linux/bpf.h                     |  13 ++-
 .../selftests/bpf/prog_tests/snprintf_btf_mod.c    | 124 +++++++++++++++++++++
 tools/testing/selftests/bpf/progs/bpf_iter.h       |   2 +-
 tools/testing/selftests/bpf/progs/btf_ptr.h        |   2 +-
 tools/testing/selftests/bpf/progs/veth_stats_rx.c  |  72 ++++++++++++
 9 files changed, 292 insertions(+), 39 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/snprintf_btf_mod.c
 create mode 100644 tools/testing/selftests/bpf/progs/veth_stats_rx.c

Comments

Yonghong Song Dec. 5, 2020, 8:35 p.m. UTC | #1
On 12/4/20 10:48 AM, Alan Maguire wrote:
> This series aims to add support to bpf_snprintf_btf() and
> bpf_seq_printf_btf() allowing them to store string representations
> of module-specific types, as well as the kernel-specific ones
> they currently support.
> 
> Patch 1 removes the btf_module_mutex, as since we will need to
> look up module BTF during BPF program execution, we don't want
> to risk sleeping in the various contexts in which BPF can run.
> The access patterns to the btf module list seem to conform to
> classic list RCU usage so with a few minor tweaks this seems
> workable.
> 
> Patch 2 replaces the unused flags field in struct btf_ptr with
> an obj_id field,  allowing the specification of the id of a
> BTF module.  If the value is 0, the core kernel vmlinux is
> assumed to contain the type's BTF information.  Otherwise the
> module with that id is used to identify the type.  If the
> object-id based lookup fails, we again fall back to vmlinux
> BTF.
> 
> Patch 3 is a selftest that uses veth (when built as a
> module) and a kprobe to display both a module-specific
> and kernel-specific type; both are arguments to veth_stats_rx().
> Currently it looks up the module-specific type and object ids
> using libbpf; in future, these lookups will likely be supported
> directly in the BPF program via __builtin_btf_type_id(); but
> I need to determine a good test to determine if that builtin
> supports object ids.

__builtin_btf_type_id() is really only supported in llvm12
and 64bit return value support is pushed to llvm12 trunk
a while back. The builtin is introduced in llvm11 but has a
corner bug, so llvm12 is recommended. So if people use the builtin,
you can assume 64bit return value. libbpf support is required
here. So in my opinion, there is no need to do feature detection.

Andrii has a patch to support 64bit return value for
__builtin_btf_type_id() and I assume that one should
be landed before or together with your patch.

Just for your info. The following is an example you could
use to determine whether __builtin_btf_type_id()
supports btf object id at llvm level.

-bash-4.4$ cat t.c
int test(int arg) {
   return __builtin_btf_type_id(arg, 1);
}

Compile to generate assembly code with latest llvm12 trunk:
   clang -target bpf -O2 -S -g -mcpu=v3 t.c
In the asm code, you should see one line with
   r0 = 1 ll

Or you can generate obj code:
   clang -target bpf -O2 -c -g -mcpu=v3 t.c
and then you disassemble the obj file
   llvm-objdump -d --no-show-raw-insn --no-leading-addr t.o
You should see below in the output
   r0 = 1 ll

Use earlier version of llvm12 trunk, the builtin has
32bit return value, you will see
   r0 = 1
which is a 32bit imm to r0, while "r0 = 1 ll" is
64bit imm to r0.

> 
> Changes since RFC
> 
> - add patch to remove module mutex
> - modify to use obj_id instead of module name as identifier
>    in "struct btf_ptr" (Andrii)
> 
> Alan Maguire (3):
>    bpf: eliminate btf_module_mutex as RCU synchronization can be used
>    bpf: add module support to btf display helpers
>    selftests/bpf: verify module-specific types can be shown via
>      bpf_snprintf_btf
> 
>   include/linux/btf.h                                |  12 ++
>   include/uapi/linux/bpf.h                           |  13 ++-
>   kernel/bpf/btf.c                                   |  49 +++++---
>   kernel/trace/bpf_trace.c                           |  44 ++++++--
>   tools/include/uapi/linux/bpf.h                     |  13 ++-
>   .../selftests/bpf/prog_tests/snprintf_btf_mod.c    | 124 +++++++++++++++++++++
>   tools/testing/selftests/bpf/progs/bpf_iter.h       |   2 +-
>   tools/testing/selftests/bpf/progs/btf_ptr.h        |   2 +-
>   tools/testing/selftests/bpf/progs/veth_stats_rx.c  |  72 ++++++++++++
>   9 files changed, 292 insertions(+), 39 deletions(-)
>   create mode 100644 tools/testing/selftests/bpf/prog_tests/snprintf_btf_mod.c
>   create mode 100644 tools/testing/selftests/bpf/progs/veth_stats_rx.c
>
Yonghong Song Dec. 5, 2020, 8:39 p.m. UTC | #2
On 12/5/20 12:35 PM, Yonghong Song wrote:
> 
> 
> On 12/4/20 10:48 AM, Alan Maguire wrote:
>> This series aims to add support to bpf_snprintf_btf() and
>> bpf_seq_printf_btf() allowing them to store string representations
>> of module-specific types, as well as the kernel-specific ones
>> they currently support.
>>
>> Patch 1 removes the btf_module_mutex, as since we will need to
>> look up module BTF during BPF program execution, we don't want
>> to risk sleeping in the various contexts in which BPF can run.
>> The access patterns to the btf module list seem to conform to
>> classic list RCU usage so with a few minor tweaks this seems
>> workable.
>>
>> Patch 2 replaces the unused flags field in struct btf_ptr with
>> an obj_id field,  allowing the specification of the id of a
>> BTF module.  If the value is 0, the core kernel vmlinux is
>> assumed to contain the type's BTF information.  Otherwise the
>> module with that id is used to identify the type.  If the
>> object-id based lookup fails, we again fall back to vmlinux
>> BTF.
>>
>> Patch 3 is a selftest that uses veth (when built as a
>> module) and a kprobe to display both a module-specific
>> and kernel-specific type; both are arguments to veth_stats_rx().
>> Currently it looks up the module-specific type and object ids
>> using libbpf; in future, these lookups will likely be supported
>> directly in the BPF program via __builtin_btf_type_id(); but
>> I need to determine a good test to determine if that builtin
>> supports object ids.
> 
> __builtin_btf_type_id() is really only supported in llvm12
> and 64bit return value support is pushed to llvm12 trunk
> a while back. The builtin is introduced in llvm11 but has a
> corner bug, so llvm12 is recommended. So if people use the builtin,
> you can assume 64bit return value. libbpf support is required
> here. So in my opinion, there is no need to do feature detection.

if people use llvm11 which may cause test to fail, we can add
an entry in selftest README file to warn people this specific
test needs llvm12.

> 
> Andrii has a patch to support 64bit return value for
> __builtin_btf_type_id() and I assume that one should
> be landed before or together with your patch.
> 
> Just for your info. The following is an example you could
> use to determine whether __builtin_btf_type_id()
> supports btf object id at llvm level.
> 
> -bash-4.4$ cat t.c
> int test(int arg) {
>    return __builtin_btf_type_id(arg, 1);
> }
> 
> Compile to generate assembly code with latest llvm12 trunk:
>    clang -target bpf -O2 -S -g -mcpu=v3 t.c
> In the asm code, you should see one line with
>    r0 = 1 ll
> 
> Or you can generate obj code:
>    clang -target bpf -O2 -c -g -mcpu=v3 t.c
> and then you disassemble the obj file
>    llvm-objdump -d --no-show-raw-insn --no-leading-addr t.o
> You should see below in the output
>    r0 = 1 ll
> 
> Use earlier version of llvm12 trunk, the builtin has
> 32bit return value, you will see
>    r0 = 1
> which is a 32bit imm to r0, while "r0 = 1 ll" is
> 64bit imm to r0.
> 
>>
>> Changes since RFC
>>
>> - add patch to remove module mutex
>> - modify to use obj_id instead of module name as identifier
>>    in "struct btf_ptr" (Andrii)
>>
>> Alan Maguire (3):
>>    bpf: eliminate btf_module_mutex as RCU synchronization can be used
>>    bpf: add module support to btf display helpers
>>    selftests/bpf: verify module-specific types can be shown via
>>      bpf_snprintf_btf
>>
>>   include/linux/btf.h                                |  12 ++
>>   include/uapi/linux/bpf.h                           |  13 ++-
>>   kernel/bpf/btf.c                                   |  49 +++++---
>>   kernel/trace/bpf_trace.c                           |  44 ++++++--
>>   tools/include/uapi/linux/bpf.h                     |  13 ++-
>>   .../selftests/bpf/prog_tests/snprintf_btf_mod.c    | 124 
>> +++++++++++++++++++++
>>   tools/testing/selftests/bpf/progs/bpf_iter.h       |   2 +-
>>   tools/testing/selftests/bpf/progs/btf_ptr.h        |   2 +-
>>   tools/testing/selftests/bpf/progs/veth_stats_rx.c  |  72 ++++++++++++
>>   9 files changed, 292 insertions(+), 39 deletions(-)
>>   create mode 100644 
>> tools/testing/selftests/bpf/prog_tests/snprintf_btf_mod.c
>>   create mode 100644 tools/testing/selftests/bpf/progs/veth_stats_rx.c
>>
Alan Maguire Dec. 6, 2020, 12:43 a.m. UTC | #3
On Sat, 5 Dec 2020, Yonghong Song wrote:

> 
> 
> __builtin_btf_type_id() is really only supported in llvm12
> and 64bit return value support is pushed to llvm12 trunk
> a while back. The builtin is introduced in llvm11 but has a
> corner bug, so llvm12 is recommended. So if people use the builtin,
> you can assume 64bit return value. libbpf support is required
> here. So in my opinion, there is no need to do feature detection.
> 
> Andrii has a patch to support 64bit return value for
> __builtin_btf_type_id() and I assume that one should
> be landed before or together with your patch.
> 
> Just for your info. The following is an example you could
> use to determine whether __builtin_btf_type_id()
> supports btf object id at llvm level.
> 
> -bash-4.4$ cat t.c
> int test(int arg) {
>   return __builtin_btf_type_id(arg, 1);
> }
> 
> Compile to generate assembly code with latest llvm12 trunk:
>   clang -target bpf -O2 -S -g -mcpu=v3 t.c
> In the asm code, you should see one line with
>   r0 = 1 ll
> 
> Or you can generate obj code:
>   clang -target bpf -O2 -c -g -mcpu=v3 t.c
> and then you disassemble the obj file
>   llvm-objdump -d --no-show-raw-insn --no-leading-addr t.o
> You should see below in the output
>   r0 = 1 ll
> 
> Use earlier version of llvm12 trunk, the builtin has
> 32bit return value, you will see
>   r0 = 1
> which is a 32bit imm to r0, while "r0 = 1 ll" is
> 64bit imm to r0.
>

Thanks for this Yonghong!  I'm thinking the way I'll tackle it
is to simply verify that the upper 32 bits specifying the
veth module object id are non-zero; if they are zero, we'll skip
the test (I think a skip probably makes sense as not everyone will
have llvm12). Does that seem reasonable?

With the additional few minor changes on top of Andrii's patch,
the use of __builtin_btf_type_id() worked perfectly. Thanks!

Alan
Yonghong Song Dec. 7, 2020, 3:38 a.m. UTC | #4
On 12/5/20 4:43 PM, Alan Maguire wrote:
> 
> On Sat, 5 Dec 2020, Yonghong Song wrote:
> 
>>
>>
>> __builtin_btf_type_id() is really only supported in llvm12
>> and 64bit return value support is pushed to llvm12 trunk
>> a while back. The builtin is introduced in llvm11 but has a
>> corner bug, so llvm12 is recommended. So if people use the builtin,
>> you can assume 64bit return value. libbpf support is required
>> here. So in my opinion, there is no need to do feature detection.
>>
>> Andrii has a patch to support 64bit return value for
>> __builtin_btf_type_id() and I assume that one should
>> be landed before or together with your patch.
>>
>> Just for your info. The following is an example you could
>> use to determine whether __builtin_btf_type_id()
>> supports btf object id at llvm level.
>>
>> -bash-4.4$ cat t.c
>> int test(int arg) {
>>    return __builtin_btf_type_id(arg, 1);
>> }
>>
>> Compile to generate assembly code with latest llvm12 trunk:
>>    clang -target bpf -O2 -S -g -mcpu=v3 t.c
>> In the asm code, you should see one line with
>>    r0 = 1 ll
>>
>> Or you can generate obj code:
>>    clang -target bpf -O2 -c -g -mcpu=v3 t.c
>> and then you disassemble the obj file
>>    llvm-objdump -d --no-show-raw-insn --no-leading-addr t.o
>> You should see below in the output
>>    r0 = 1 ll
>>
>> Use earlier version of llvm12 trunk, the builtin has
>> 32bit return value, you will see
>>    r0 = 1
>> which is a 32bit imm to r0, while "r0 = 1 ll" is
>> 64bit imm to r0.
>>
> 
> Thanks for this Yonghong!  I'm thinking the way I'll tackle it
> is to simply verify that the upper 32 bits specifying the
> veth module object id are non-zero; if they are zero, we'll skip
> the test (I think a skip probably makes sense as not everyone will
> have llvm12). Does that seem reasonable?

This should work too and we do not need to add a note in
README.rst for this test then.

> 
> With the additional few minor changes on top of Andrii's patch,
> the use of __builtin_btf_type_id() worked perfectly. Thanks!
> 
> Alan
>
Andrii Nakryiko Dec. 8, 2020, 3:42 a.m. UTC | #5
On Sat, Dec 5, 2020 at 4:44 PM Alan Maguire <alan.maguire@oracle.com> wrote:
>
>
> On Sat, 5 Dec 2020, Yonghong Song wrote:
>
> >
> >
> > __builtin_btf_type_id() is really only supported in llvm12
> > and 64bit return value support is pushed to llvm12 trunk
> > a while back. The builtin is introduced in llvm11 but has a
> > corner bug, so llvm12 is recommended. So if people use the builtin,
> > you can assume 64bit return value. libbpf support is required
> > here. So in my opinion, there is no need to do feature detection.
> >
> > Andrii has a patch to support 64bit return value for
> > __builtin_btf_type_id() and I assume that one should
> > be landed before or together with your patch.
> >
> > Just for your info. The following is an example you could
> > use to determine whether __builtin_btf_type_id()
> > supports btf object id at llvm level.
> >
> > -bash-4.4$ cat t.c
> > int test(int arg) {
> >   return __builtin_btf_type_id(arg, 1);
> > }
> >
> > Compile to generate assembly code with latest llvm12 trunk:
> >   clang -target bpf -O2 -S -g -mcpu=v3 t.c
> > In the asm code, you should see one line with
> >   r0 = 1 ll
> >
> > Or you can generate obj code:
> >   clang -target bpf -O2 -c -g -mcpu=v3 t.c
> > and then you disassemble the obj file
> >   llvm-objdump -d --no-show-raw-insn --no-leading-addr t.o
> > You should see below in the output
> >   r0 = 1 ll
> >
> > Use earlier version of llvm12 trunk, the builtin has
> > 32bit return value, you will see
> >   r0 = 1
> > which is a 32bit imm to r0, while "r0 = 1 ll" is
> > 64bit imm to r0.
> >
>
> Thanks for this Yonghong!  I'm thinking the way I'll tackle it
> is to simply verify that the upper 32 bits specifying the
> veth module object id are non-zero; if they are zero, we'll skip

Let's instead of the real veth module use selftests's bpf_testmod,
which I added specifically to use for tests like these. We can define
whatever types we need in there.

> the test (I think a skip probably makes sense as not everyone will
> have llvm12). Does that seem reasonable?
>
> With the additional few minor changes on top of Andrii's patch,
> the use of __builtin_btf_type_id() worked perfectly. Thanks!
>
> Alan