From: John Fastabend <john.fastabend@gmail.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>,
Yafang Shao <laoar.shao@gmail.com>
Cc: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com,
andrii@kernel.org, martin.lau@linux.dev, eddyz87@gmail.com,
song@kernel.org, yonghong.song@linux.dev, kpsingh@kernel.org,
sdf@google.com, haoluo@google.com, jolsa@kernel.org,
bpf@vger.kernel.org
Subject: Re: [PATCH v2 bpf-next 1/2] bpf: Add bits iterator
Date: Thu, 29 Feb 2024 14:19:34 -0800 [thread overview]
Message-ID: <65e102f6ebef2_33719208c8@john.notmuch> (raw)
In-Reply-To: <CAEf4BzYK4o558CcQt=yzKZH+M-eD3z0GpdUORcapJKXAHZJy-g@mail.gmail.com>
Andrii Nakryiko wrote:
> On Wed, Feb 28, 2024 at 6:16 PM Yafang Shao <laoar.shao@gmail.com> wrote:
> >
> > On Wed, Feb 28, 2024 at 2:04 PM Andrii Nakryiko
> > <andrii.nakryiko@gmail.com> wrote:
> > >
> > > On Tue, Feb 27, 2024 at 6:25 PM Yafang Shao <laoar.shao@gmail.com> wrote:
> > > >
> > > > On Wed, Feb 28, 2024 at 9:24 AM Andrii Nakryiko
> > > > <andrii.nakryiko@gmail.com> wrote:
> > > > >
> > > > > On Sun, Feb 25, 2024 at 2:07 AM Yafang Shao <laoar.shao@gmail.com> wrote:
> > > > > >
> > > > > > Add three new kfuncs for the bits iterator:
> > > > > > - bpf_iter_bits_new
> > > > > > Initialize a new bits iterator for a given memory area. Due to the
> > > > > > limitation of bpf memalloc, the max number of bits that can be iterated
> > > > > > over is limited to (4096 * 8).
> > > > > > - bpf_iter_bits_next
> > > > > > Get the next bit in a bpf_iter_bits
> > > > > > - bpf_iter_bits_destroy
> > > > > > Destroy a bpf_iter_bits
> > > > > >
> > > > > > The bits iterator facilitates the iteration of the bits of a memory area,
> > > > > > such as cpumask. It can be used in any context and on any address.
> > > > > >
> > > > > > Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> > > > > > ---
> > > > > > kernel/bpf/helpers.c | 100 +++++++++++++++++++++++++++++++++++++++++++
> > > > > > 1 file changed, 100 insertions(+)
> > > > > >
> > > > > > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> > > > > > index 93edf730d288..052f63891834 100644
> > > > > > --- a/kernel/bpf/helpers.c
> > > > > > +++ b/kernel/bpf/helpers.c
> > > > > > @@ -2542,6 +2542,103 @@ __bpf_kfunc void bpf_throw(u64 cookie)
> > > > > > WARN(1, "A call to BPF exception callback should never return\n");
> > > > > > }
> > > > > >
> > > > > > +struct bpf_iter_bits {
> > > > > > + __u64 __opaque[2];
> > > > > > +} __aligned(8);
> > > > > > +
> > > > > > +struct bpf_iter_bits_kern {
> > > > > > + unsigned long *bits;
> > > > > > + u32 nr_bits;
> > > > > > + int bit;
> > > > > > +} __aligned(8);
> > > > > > +
> > > > > > +/**
> > > > > > + * bpf_iter_bits_new() - Initialize a new bits iterator for a given memory area
> > > > > > + * @it: The new bpf_iter_bits to be created
> > > > > > + * @unsafe_ptr__ign: A ponter pointing to a memory area to be iterated over
> > > > > > + * @nr_bits: The number of bits to be iterated over. Due to the limitation of
> > > > > > + * memalloc, it can't greater than (4096 * 8).
> > > > > > + *
> > > > > > + * This function initializes a new bpf_iter_bits structure for iterating over
> > > > > > + * a memory area which is specified by the @unsafe_ptr__ign and @nr_bits. It
> > > > > > + * copy the data of the memory area to the newly created bpf_iter_bits @it for
> > > > > > + * subsequent iteration operations.
> > > > > > + *
> > > > > > + * On success, 0 is returned. On failure, ERR is returned.
> > > > > > + */
> > > > > > +__bpf_kfunc int
> > > > > > +bpf_iter_bits_new(struct bpf_iter_bits *it, const void *unsafe_ptr__ign, u32 nr_bits)
> > > > > > +{
> > > > > > + struct bpf_iter_bits_kern *kit = (void *)it;
> > > > > > + u32 size = BITS_TO_BYTES(nr_bits);
> > > > > > + int err;
> > > > > > +
> > > > > > + BUILD_BUG_ON(sizeof(struct bpf_iter_bits_kern) != sizeof(struct bpf_iter_bits));
> > > > > > + BUILD_BUG_ON(__alignof__(struct bpf_iter_bits_kern) !=
> > > > > > + __alignof__(struct bpf_iter_bits));
> > > > > > +
> > > > > > + if (!unsafe_ptr__ign || !nr_bits) {
> > > > > > + kit->bits = NULL;
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > > > +
> > > > > > + kit->bits = bpf_mem_alloc(&bpf_global_ma, size);
> > > > > > + if (!kit->bits)
> > > > > > + return -ENOMEM;
> > > > >
> > > > > it's probably going to be a pretty common case to do bits iteration
> > > > > for nr_bits<=64, right?
> > > >
> > > > It's highly unlikely.
> > > > Consider the CPU count as an example; There are 256 CPUs on our AMD
> > > > EPYC servers.
> > >
> > > Also consider u64-based bit masks (like struct backtrack_state in
> > > verifier code, which has u32 reg_mask and u64 stack_mask). This
> > > iterator is a generic bits iterator, there are tons of cases of
> > > u64/u32 masks in practice.
> >
> > Should we optimize it as follows?
> >
> > if (nr_bits <= 64) {
> > // do the optimization
> > } else {
> > // fallback to memalloc
> > }
> >
>
> Yep, that's what I'm proposing
When I suggested why not just open code this in BPF earlier I was
mostly thinking of these u64 and u32 masks we have lots of them
in our code base as well.
I have something like this which might be even better than 3
calls depending on your use case,
int find_next_bit(uint64_t bits, int last_bit)
{
int i = last_bit;
for (i = 0; i < sizeof(uint64_t) * 8; i++) {
if (bits & (1 << i))
return i;
}
return -1;
}
Verifier seems plenty happy with above.
Thanks,
John
next prev parent reply other threads:[~2024-02-29 22:19 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-25 10:06 [PATCH v2 bpf-next 0/2] bpf: Add a generic bits iterator Yafang Shao
2024-02-25 10:06 ` [PATCH v2 bpf-next 1/2] bpf: Add " Yafang Shao
2024-02-28 1:24 ` Andrii Nakryiko
2024-02-28 2:25 ` Yafang Shao
2024-02-28 6:04 ` Andrii Nakryiko
2024-02-29 2:15 ` Yafang Shao
2024-02-29 17:26 ` Andrii Nakryiko
2024-02-29 22:19 ` John Fastabend [this message]
2024-03-01 6:40 ` Yafang Shao
2024-03-01 18:01 ` John Fastabend
2024-02-25 10:06 ` [PATCH v2 bpf-next 2/2] selftests/bpf: Add selftest for bits iter Yafang Shao
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=65e102f6ebef2_33719208c8@john.notmuch \
--to=john.fastabend@gmail.com \
--cc=andrii.nakryiko@gmail.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=jolsa@kernel.org \
--cc=kpsingh@kernel.org \
--cc=laoar.shao@gmail.com \
--cc=martin.lau@linux.dev \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.