diff mbox series

[RFC,bpf-next] bpf, tnums: add bitwise-not helper

Message ID 20231106021119.10455-1-shung-hsi.yu@suse.com (mailing list archive)
State RFC
Delegated to: BPF
Headers show
Series [RFC,bpf-next] bpf, tnums: add bitwise-not helper | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for bpf-next
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: 1413 this patch: 1413
netdev/cc_maintainers success CCed 12 of 12 maintainers
netdev/build_clang success Errors and warnings before: 1379 this patch: 1379
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: 1441 this patch: 1441
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 19 lines checked
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
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-7 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-12 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-10 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-8 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-3 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-11 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-llvm-16 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-16 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-llvm-16 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 fail Logs for x86_64-llvm-16 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-llvm-16 / build / build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-16 / veristat
bpf/vmtest-bpf-next-VM_Test-15 success Logs for set-matrix

Commit Message

Shung-Hsi Yu Nov. 6, 2023, 2:11 a.m. UTC
Note: Andrii' patch mentioned in the Link tag isn't merge yet, I'll
      resend this along with the proposed refactoring once it is merged.
      For now, sending the patch as RFC for feedback and review.

While the BPF instruction set does not contain a bitwise-NOT
instruction, the verifier may still need to compute the bitwise-NOT
result for the value tracked in the register. One such case reference in
the link below is

	u64 val;
	val = reg_const_value(reg2, is_jmp32);
	tnum_ops(..., tnum_const(~val);

Where the value is extract of out tnum, operated with bitwise-NOT, then
simply turned back into tnum again; plus it has the limitation of only
working on constant. This commit adds the tnum_not() helper that compute
the bitwise-NOT result for all the values tracked within the tnum, that
allow us to simplify the above code to

	tnum_ops(..., tnum_not(reg2->var_off));

without being limited to constant, and is general enough to be reused
and composed with other tnum operations.

Link: https://lore.kernel.org/bpf/ZUSwQtfjCsKpbWcL@u94a/
Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
---

 include/linux/tnum.h | 2 ++
 kernel/bpf/tnum.c    | 5 +++++
 2 files changed, 7 insertions(+)


base-commit: 1a119e269dc69e82217525d92a93e082c4424fc8

Comments

Andrii Nakryiko Nov. 6, 2023, 7:56 p.m. UTC | #1
On Sun, Nov 5, 2023 at 6:11 PM Shung-Hsi Yu <shung-hsi.yu@suse.com> wrote:
>
> Note: Andrii' patch mentioned in the Link tag isn't merge yet, I'll
>       resend this along with the proposed refactoring once it is merged.
>       For now, sending the patch as RFC for feedback and review.
>
> While the BPF instruction set does not contain a bitwise-NOT
> instruction, the verifier may still need to compute the bitwise-NOT
> result for the value tracked in the register. One such case reference in
> the link below is
>
>         u64 val;
>         val = reg_const_value(reg2, is_jmp32);
>         tnum_ops(..., tnum_const(~val);
>
> Where the value is extract of out tnum, operated with bitwise-NOT, then
> simply turned back into tnum again; plus it has the limitation of only
> working on constant. This commit adds the tnum_not() helper that compute
> the bitwise-NOT result for all the values tracked within the tnum, that
> allow us to simplify the above code to
>
>         tnum_ops(..., tnum_not(reg2->var_off));
>
> without being limited to constant, and is general enough to be reused
> and composed with other tnum operations.
>
> Link: https://lore.kernel.org/bpf/ZUSwQtfjCsKpbWcL@u94a/
> Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
> ---
>
>  include/linux/tnum.h | 2 ++
>  kernel/bpf/tnum.c    | 5 +++++
>  2 files changed, 7 insertions(+)
>
> diff --git a/include/linux/tnum.h b/include/linux/tnum.h
> index 1c3948a1d6ad..817065df1297 100644
> --- a/include/linux/tnum.h
> +++ b/include/linux/tnum.h
> @@ -46,6 +46,8 @@ struct tnum tnum_and(struct tnum a, struct tnum b);
>  struct tnum tnum_or(struct tnum a, struct tnum b);
>  /* Bitwise-XOR, return @a ^ @b */
>  struct tnum tnum_xor(struct tnum a, struct tnum b);
> +/* Bitwise-NOT, return ~@a */
> +struct tnum tnum_not(struct tnum a);
>  /* Multiply two tnums, return @a * @b */
>  struct tnum tnum_mul(struct tnum a, struct tnum b);
>
> diff --git a/kernel/bpf/tnum.c b/kernel/bpf/tnum.c
> index 3d7127f439a1..b4f4a4beb0c9 100644
> --- a/kernel/bpf/tnum.c
> +++ b/kernel/bpf/tnum.c
> @@ -111,6 +111,11 @@ struct tnum tnum_xor(struct tnum a, struct tnum b)
>         return TNUM(v & ~mu, mu);
>  }
>
> +struct tnum tnum_not(struct tnum a)
> +{
> +       return TNUM(~a.value & ~a.mask, a.mask);
> +}
> +

In isolation this does look like it's implementing the tnum version of
~x, so I have no objections to this. But I'm not sure it actually
simplifies anything in my patches. But let's see, once it lands,
please send a follow up applying this tnum_not().


>  /* Generate partial products by multiplying each bit in the multiplier (tnum a)
>   * with the multiplicand (tnum b), and add the partial products after
>   * appropriately bit-shifting them. Instead of directly performing tnum addition
>
> base-commit: 1a119e269dc69e82217525d92a93e082c4424fc8
> --
> 2.42.0
>
Shung-Hsi Yu Nov. 7, 2023, 4:43 a.m. UTC | #2
On Mon, Nov 06, 2023 at 11:56:22AM -0800, Andrii Nakryiko wrote:
> On Sun, Nov 5, 2023 at 6:11 PM Shung-Hsi Yu <shung-hsi.yu@suse.com> wrote:
> > Note: Andrii' patch mentioned in the Link tag isn't merge yet, I'll
> >       resend this along with the proposed refactoring once it is merged.
> >       For now, sending the patch as RFC for feedback and review.
> >
> > While the BPF instruction set does not contain a bitwise-NOT
> > instruction, the verifier may still need to compute the bitwise-NOT
> > result for the value tracked in the register. One such case reference in
> > the link below is
> >
> >         u64 val;
> >         val = reg_const_value(reg2, is_jmp32);
> >         tnum_ops(..., tnum_const(~val);
> >
> > Where the value is extract of out tnum, operated with bitwise-NOT, then
> > simply turned back into tnum again; plus it has the limitation of only
> > working on constant. This commit adds the tnum_not() helper that compute
> > the bitwise-NOT result for all the values tracked within the tnum, that
> > allow us to simplify the above code to
> >
> >         tnum_ops(..., tnum_not(reg2->var_off));
> >
> > without being limited to constant, and is general enough to be reused
> > and composed with other tnum operations.
> >
> > Link: https://lore.kernel.org/bpf/ZUSwQtfjCsKpbWcL@u94a/
> > Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
> > ---

[...]

> > diff --git a/kernel/bpf/tnum.c b/kernel/bpf/tnum.c
> > index 3d7127f439a1..b4f4a4beb0c9 100644
> > --- a/kernel/bpf/tnum.c
> > +++ b/kernel/bpf/tnum.c
> > @@ -111,6 +111,11 @@ struct tnum tnum_xor(struct tnum a, struct tnum b)
> >         return TNUM(v & ~mu, mu);
> >  }
> >
> > +struct tnum tnum_not(struct tnum a)
> > +{
> > +       return TNUM(~a.value & ~a.mask, a.mask);
> > +}
> > +
> 
> In isolation this does look like it's implementing the tnum version of
> ~x, so I have no objections to this. But I'm not sure it actually
> simplifies anything in my patches. But let's see, once it lands,
> please send a follow up applying this tnum_not().

Okay, will send once it lands.

[...]
diff mbox series

Patch

diff --git a/include/linux/tnum.h b/include/linux/tnum.h
index 1c3948a1d6ad..817065df1297 100644
--- a/include/linux/tnum.h
+++ b/include/linux/tnum.h
@@ -46,6 +46,8 @@  struct tnum tnum_and(struct tnum a, struct tnum b);
 struct tnum tnum_or(struct tnum a, struct tnum b);
 /* Bitwise-XOR, return @a ^ @b */
 struct tnum tnum_xor(struct tnum a, struct tnum b);
+/* Bitwise-NOT, return ~@a */
+struct tnum tnum_not(struct tnum a);
 /* Multiply two tnums, return @a * @b */
 struct tnum tnum_mul(struct tnum a, struct tnum b);
 
diff --git a/kernel/bpf/tnum.c b/kernel/bpf/tnum.c
index 3d7127f439a1..b4f4a4beb0c9 100644
--- a/kernel/bpf/tnum.c
+++ b/kernel/bpf/tnum.c
@@ -111,6 +111,11 @@  struct tnum tnum_xor(struct tnum a, struct tnum b)
 	return TNUM(v & ~mu, mu);
 }
 
+struct tnum tnum_not(struct tnum a)
+{
+	return TNUM(~a.value & ~a.mask, a.mask);
+}
+
 /* Generate partial products by multiplying each bit in the multiplier (tnum a)
  * with the multiplicand (tnum b), and add the partial products after
  * appropriately bit-shifting them. Instead of directly performing tnum addition