diff mbox series

[v2,bpf-next,16/20] bpf: Add helper macro bpf_arena_cast()

Message ID 20240209040608.98927-17-alexei.starovoitov@gmail.com (mailing list archive)
State Changes Requested
Delegated to: BPF
Headers show
Series bpf: Introduce BPF arena. | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR fail PR summary
bpf/vmtest-bpf-next-VM_Test-25 fail Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-llvm-18 / test
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-4 fail Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test
bpf/vmtest-bpf-next-VM_Test-7 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-9 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-8 fail Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for s390x-gcc / test
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-12 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-13 fail Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-15 success Logs for x86_64-gcc / test
bpf/vmtest-bpf-next-VM_Test-16 success Logs for x86_64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-17 fail Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-llvm-17 / test
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-21 fail Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-llvm-18 / test
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-22 fail Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-18 fail Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17 and -O2 optimization
netdev/series_format fail Series longer than 15 patches (and no cover letter)
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 8 this patch: 8
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 16 maintainers not CCed: john.fastabend@gmail.com mykolal@fb.com nathan@kernel.org shuah@kernel.org morbo@google.com kpsingh@kernel.org llvm@lists.linux.dev jolsa@kernel.org yonghong.song@linux.dev martin.lau@linux.dev song@kernel.org sdf@google.com linux-kselftest@vger.kernel.org justinstitt@google.com ndesaulniers@google.com haoluo@google.com
netdev/build_clang success Errors and warnings before: 8 this patch: 8
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 8 this patch: 8
netdev/checkpatch warning WARNING: Avoid line continuations in quoted strings WARNING: Avoid unnecessary line continuations WARNING: line length of 87 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Alexei Starovoitov Feb. 9, 2024, 4:06 a.m. UTC
From: Alexei Starovoitov <ast@kernel.org>

Introduce helper macro bpf_arena_cast() that emits:
rX = rX
instruction with off = BPF_ARENA_CAST_KERN or off = BPF_ARENA_CAST_USER
and encodes address_space into imm32.

It's useful with older LLVM that doesn't emit this insn automatically.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
 .../testing/selftests/bpf/bpf_experimental.h  | 41 +++++++++++++++++++
 1 file changed, 41 insertions(+)

Comments

Kumar Kartikeya Dwivedi Feb. 10, 2024, 8:54 a.m. UTC | #1
On Fri, 9 Feb 2024 at 05:07, Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> From: Alexei Starovoitov <ast@kernel.org>
>
> Introduce helper macro bpf_arena_cast() that emits:
> rX = rX
> instruction with off = BPF_ARENA_CAST_KERN or off = BPF_ARENA_CAST_USER
> and encodes address_space into imm32.
>
> It's useful with older LLVM that doesn't emit this insn automatically.
>
> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
> ---

Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>

But could this simply be added to libbpf along with bpf_cast_user and
bpf_cast_kern? I believe since LLVM and the verifier support the new
cast instructions, they are unlikely to disappear any time soon. It
would probably also make it easier to use elsewhere (e.g. sched-ext)
without having to copy them.

I plan on doing the same eventually with assert macros too.
Alexei Starovoitov Feb. 13, 2024, 10:35 p.m. UTC | #2
On Sat, Feb 10, 2024 at 12:54 AM Kumar Kartikeya Dwivedi
<memxor@gmail.com> wrote:
>
> On Fri, 9 Feb 2024 at 05:07, Alexei Starovoitov
> <alexei.starovoitov@gmail.com> wrote:
> >
> > From: Alexei Starovoitov <ast@kernel.org>
> >
> > Introduce helper macro bpf_arena_cast() that emits:
> > rX = rX
> > instruction with off = BPF_ARENA_CAST_KERN or off = BPF_ARENA_CAST_USER
> > and encodes address_space into imm32.
> >
> > It's useful with older LLVM that doesn't emit this insn automatically.
> >
> > Signed-off-by: Alexei Starovoitov <ast@kernel.org>
> > ---
>
> Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>
> But could this simply be added to libbpf along with bpf_cast_user and
> bpf_cast_kern? I believe since LLVM and the verifier support the new
> cast instructions, they are unlikely to disappear any time soon. It
> would probably also make it easier to use elsewhere (e.g. sched-ext)
> without having to copy them.

This arena bpf_arena_cast() macro probably will be removed
once llvm 19 is released and we upgrade bpf CI to it.
It's here for selftests only.
It's quite tricky and fragile to use in practice.
Notice it does:
"r"(__var)
which is not quite correct,
since llvm won't recognize it as output that changes __var and
will use a copy of __var in a different register later.
But if the macro changes to "=r" or "+r" then llvm allocates
a register and that screws up codegen even more.

The __var;}) also doesn't always work.
So this macro is not suited for all to use.

> I plan on doing the same eventually with assert macros too.

I think it's too early to move them.
Eduard Zingerman Feb. 14, 2024, 4:47 p.m. UTC | #3
On Tue, 2024-02-13 at 14:35 -0800, Alexei Starovoitov wrote:
[...]

> This arena bpf_arena_cast() macro probably will be removed
> once llvm 19 is released and we upgrade bpf CI to it.
> It's here for selftests only.
> It's quite tricky and fragile to use in practice.
> Notice it does:
> "r"(__var)
> which is not quite correct,
> since llvm won't recognize it as output that changes __var and
> will use a copy of __var in a different register later.
> But if the macro changes to "=r" or "+r" then llvm allocates
> a register and that screws up codegen even more.
> 
> The __var;}) also doesn't always work.
> So this macro is not suited for all to use.

Could you please elaborate a bit on why is this macro fragile?
I toyed a bit with a version patched as below and it seems to work fine.
Don't see how  ": [reg]"+r"(var) : ..." could be broken by the compiler
(when "+r" is in the "output constraint" position):
from clang pov the variable 'var' would be in register and updated
after the asm volatile part.

---

diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index e73b7d48439f..488001236506 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -334,8 +334,6 @@ l_true:                                                                                             \
 /* emit instruction: rX=rX .off = mode .imm32 = address_space */
 #ifndef bpf_arena_cast
 #define bpf_arena_cast(var, mode, addr_space)  \
-       ({                                      \
-       typeof(var) __var = var;                \
        asm volatile(".byte 0xBF;               \
                     .ifc %[reg], r0;           \
                     .byte 0x00;                \
@@ -368,8 +366,7 @@ l_true:                                                                                             \
                     .byte 0x99;                \
                     .endif;                    \
                     .short %[off]; .long %[as]"        \
-                    :: [reg]"r"(__var), [off]"i"(mode), [as]"i"(addr_space)); __var; \
-       })
+                    : [reg]"+r"(var) : [off]"i"(mode), [as]"i"(addr_space))
 #endif
Alexei Starovoitov Feb. 14, 2024, 5:45 p.m. UTC | #4
On Wed, Feb 14, 2024 at 8:47 AM Eduard Zingerman <eddyz87@gmail.com> wrote:
>
> On Tue, 2024-02-13 at 14:35 -0800, Alexei Starovoitov wrote:
> [...]
>
> > This arena bpf_arena_cast() macro probably will be removed
> > once llvm 19 is released and we upgrade bpf CI to it.
> > It's here for selftests only.
> > It's quite tricky and fragile to use in practice.
> > Notice it does:
> > "r"(__var)
> > which is not quite correct,
> > since llvm won't recognize it as output that changes __var and
> > will use a copy of __var in a different register later.
> > But if the macro changes to "=r" or "+r" then llvm allocates
> > a register and that screws up codegen even more.
> >
> > The __var;}) also doesn't always work.
> > So this macro is not suited for all to use.
>
> Could you please elaborate a bit on why is this macro fragile?
> I toyed a bit with a version patched as below and it seems to work fine.
> Don't see how  ": [reg]"+r"(var) : ..." could be broken by the compiler
> (when "+r" is in the "output constraint" position):
> from clang pov the variable 'var' would be in register and updated
> after the asm volatile part.
>
> ---
>
> diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
> index e73b7d48439f..488001236506 100644
> --- a/tools/testing/selftests/bpf/bpf_experimental.h
> +++ b/tools/testing/selftests/bpf/bpf_experimental.h
> @@ -334,8 +334,6 @@ l_true:                                                                                             \
>  /* emit instruction: rX=rX .off = mode .imm32 = address_space */
>  #ifndef bpf_arena_cast
>  #define bpf_arena_cast(var, mode, addr_space)  \
> -       ({                                      \
> -       typeof(var) __var = var;                \
>         asm volatile(".byte 0xBF;               \
>                      .ifc %[reg], r0;           \
>                      .byte 0x00;                \
> @@ -368,8 +366,7 @@ l_true:                                                                                             \
>                      .byte 0x99;                \
>                      .endif;                    \
>                      .short %[off]; .long %[as]"        \
> -                    :: [reg]"r"(__var), [off]"i"(mode), [as]"i"(addr_space)); __var; \
> -       })
> +                    : [reg]"+r"(var) : [off]"i"(mode), [as]"i"(addr_space))

Earlier I tried "+r" while keeping __var.
Directly using var seems to work indeed.
I'll apply this change.
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index 0d749006d107..e73b7d48439f 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -331,6 +331,47 @@  l_true:												\
 	asm volatile("%[reg]=%[reg]"::[reg]"r"((short)var))
 #endif
 
+/* emit instruction: rX=rX .off = mode .imm32 = address_space */
+#ifndef bpf_arena_cast
+#define bpf_arena_cast(var, mode, addr_space)	\
+	({					\
+	typeof(var) __var = var;		\
+	asm volatile(".byte 0xBF;		\
+		     .ifc %[reg], r0;		\
+		     .byte 0x00;		\
+		     .endif;			\
+		     .ifc %[reg], r1;		\
+		     .byte 0x11;		\
+		     .endif;			\
+		     .ifc %[reg], r2;		\
+		     .byte 0x22;		\
+		     .endif;			\
+		     .ifc %[reg], r3;		\
+		     .byte 0x33;		\
+		     .endif;			\
+		     .ifc %[reg], r4;		\
+		     .byte 0x44;		\
+		     .endif;			\
+		     .ifc %[reg], r5;		\
+		     .byte 0x55;		\
+		     .endif;			\
+		     .ifc %[reg], r6;		\
+		     .byte 0x66;		\
+		     .endif;			\
+		     .ifc %[reg], r7;		\
+		     .byte 0x77;		\
+		     .endif;			\
+		     .ifc %[reg], r8;		\
+		     .byte 0x88;		\
+		     .endif;			\
+		     .ifc %[reg], r9;		\
+		     .byte 0x99;		\
+		     .endif;			\
+		     .short %[off]; .long %[as]"	\
+		     :: [reg]"r"(__var), [off]"i"(mode), [as]"i"(addr_space)); __var; \
+	})
+#endif
+
 /* Description
  *	Assert that a conditional expression is true.
  * Returns