public inbox for io-uring@vger.kernel.org
 help / color / mirror / Atom feed
From: Pavel Begunkov <asml.silence@gmail.com>
To: io-uring@vger.kernel.org
Cc: asml.silence@gmail.com, bpf@vger.kernel.org, axboe@kernel.dk,
	Alexei Starovoitov <alexei.starovoitov@gmail.com>
Subject: [PATCH 3/3] io_uring/selftests: add regbuf xor example
Date: Mon, 23 Feb 2026 14:12:02 +0000	[thread overview]
Message-ID: <09ea9cdafd870002278c2c8a62023c81aa742e2c.1771850496.git.asml.silence@gmail.com> (raw)
In-Reply-To: <cover.1771850496.git.asml.silence@gmail.com>

Add a kfunc and an example of calculating xor for a registered buffer.
That's useful for cases where the registered buffer is not visible by
user space and exists in-kernel only. The rest depends on the BPF
writer, and one way to use it could be to execute all jobs like xor'ing
at the beginning and the do normal request processing (the example
program just stops). Another approach would be to implement it as a part
of BPF CQE processing.

We'll need to think through the registered buffer kfunc API before
merging anything similar (not to mention implementing it properly).

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 io_uring/bpf-ops.c                            | 29 +++++++
 tools/testing/selftests/io_uring/Makefile     |  2 +-
 .../testing/selftests/io_uring/common-defs.h  |  6 ++
 tools/testing/selftests/io_uring/xor.bpf.c    | 31 +++++++
 tools/testing/selftests/io_uring/xor.c        | 83 +++++++++++++++++++
 5 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/io_uring/xor.bpf.c
 create mode 100644 tools/testing/selftests/io_uring/xor.c

diff --git a/io_uring/bpf-ops.c b/io_uring/bpf-ops.c
index 1ffe7ba73b89..51c239c7cb34 100644
--- a/io_uring/bpf-ops.c
+++ b/io_uring/bpf-ops.c
@@ -9,6 +9,7 @@
 #include "memmap.h"
 #include "bpf-ops.h"
 #include "loop.h"
+#include "rsrc.h"
 
 static DEFINE_MUTEX(io_bpf_ctrl_mutex);
 static const struct btf_type *loop_params_type;
@@ -47,11 +48,39 @@ __u8 *bpf_io_uring_get_region(struct io_ring_ctx *ctx, __u32 region_id,
 	return io_region_get_ptr(r);
 }
 
+__bpf_kfunc
+__u8 bpf_io_uring_xor_regbuf(struct io_ring_ctx *ctx, unsigned idx,
+				size_t size)
+{
+	const struct io_mapped_ubuf *imu;
+	struct io_rsrc_node *node;
+	struct iov_iter iter;
+	__u8 xor_res = 0;
+	__u8 buffer[512];
+	int i, ret;
+
+	node = io_rsrc_node_lookup(&ctx->buf_table, idx);
+	if (!node)
+		return 0;
+	imu = node->buf;
+	if (size > imu->len || size > sizeof(buffer))
+		return 0;
+
+	iov_iter_bvec(&iter, ITER_SOURCE, imu->bvec, imu->nr_bvecs, size);
+	ret = copy_from_iter(buffer, size, &iter);
+	if (ret != size)
+		return 0;
+	for (i = 0; i < size; i++)
+		xor_res ^= buffer[i];
+	return xor_res;
+}
+
 __bpf_kfunc_end_defs();
 
 BTF_KFUNCS_START(io_uring_kfunc_set)
 BTF_ID_FLAGS(func, bpf_io_uring_submit_sqes, KF_SLEEPABLE);
 BTF_ID_FLAGS(func, bpf_io_uring_get_region, KF_RET_NULL);
+BTF_ID_FLAGS(func, bpf_io_uring_xor_regbuf, KF_SLEEPABLE);
 BTF_KFUNCS_END(io_uring_kfunc_set)
 
 static const struct btf_kfunc_id_set bpf_io_uring_kfunc_set = {
diff --git a/tools/testing/selftests/io_uring/Makefile b/tools/testing/selftests/io_uring/Makefile
index e0581f96d98a..3b139964f537 100644
--- a/tools/testing/selftests/io_uring/Makefile
+++ b/tools/testing/selftests/io_uring/Makefile
@@ -3,7 +3,7 @@ include ../../../build/Build.include
 include ../../../scripts/Makefile.arch
 include ../../../scripts/Makefile.include
 
-TEST_GEN_PROGS := nops_loop overflow unreg cp rate_limiter
+TEST_GEN_PROGS := nops_loop overflow unreg cp rate_limiter xor
 
 # override lib.mk's default rules
 OVERRIDE_TARGETS := 1
diff --git a/tools/testing/selftests/io_uring/common-defs.h b/tools/testing/selftests/io_uring/common-defs.h
index dae3b0fe8588..ee6c36eae426 100644
--- a/tools/testing/selftests/io_uring/common-defs.h
+++ b/tools/testing/selftests/io_uring/common-defs.h
@@ -49,4 +49,10 @@ struct rate_limiter_state {
 	int res;
 };
 
+struct xor_state {
+	unsigned regbuf_idx;
+	unsigned xor_size;
+	__u8 xor_res;
+};
+
 #endif /* IOU_TOOLS_COMMON_DEFS_H */
diff --git a/tools/testing/selftests/io_uring/xor.bpf.c b/tools/testing/selftests/io_uring/xor.bpf.c
new file mode 100644
index 000000000000..c7c3b46ca1bf
--- /dev/null
+++ b/tools/testing/selftests/io_uring/xor.bpf.c
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include "vmlinux.h"
+#include "common-defs.h"
+
+char LICENSE[] SEC("license") = "Dual BSD/GPL";
+
+const volatile struct ring_info ri;
+
+SEC("struct_ops.s/xor_step")
+int BPF_PROG(xor_step, struct io_ring_ctx *ring, struct iou_loop_params *ls)
+{
+	struct xor_state *xs;
+
+	xs = (void *)bpf_io_uring_get_region(ring, IOU_REGION_MEM,
+				sizeof(*xs));
+	if (!xs)
+		return IOU_LOOP_STOP;
+
+	xs->xor_res = bpf_io_uring_xor_regbuf(ring, xs->regbuf_idx,
+						xs->xor_size);
+	return IOU_LOOP_STOP;
+}
+
+SEC(".struct_ops.link")
+struct io_uring_bpf_ops xor_ops = {
+	.loop_step = (void *)xor_step,
+};
diff --git a/tools/testing/selftests/io_uring/xor.c b/tools/testing/selftests/io_uring/xor.c
new file mode 100644
index 000000000000..c2e7d6af2c92
--- /dev/null
+++ b/tools/testing/selftests/io_uring/xor.c
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/stddef.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <bpf/libbpf.h>
+#include <io_uring/mini_liburing.h>
+
+#include "helpers.h"
+#include "xor.bpf.skel.h"
+
+int main()
+{
+	struct xor_state *xs;
+	struct bpf_link *link;
+	struct xor *skel;
+	struct ring_ctx ctx;
+	__u8 *buffer;
+	size_t buf_size = 512;
+	struct iovec iov;
+	__u8 xorv = 0;
+	int ret, i;
+
+	ring_ctx_create(&ctx, sizeof(*xs));
+
+	skel = xor__open();
+	if (!skel) {
+		fprintf(stderr, "can't generate skeleton\n");
+		exit(1);
+	}
+	skel->struct_ops.xor_ops->ring_fd = ctx.ring.ring_fd;
+	skel->rodata->ri = ctx.ri;
+
+	ret = xor__load(skel);
+	if (ret) {
+		fprintf(stderr, "failed to load skeleton\n");
+		exit(1);
+	}
+	link = bpf_map__attach_struct_ops(skel->maps.xor_ops);
+	if (!link) {
+		fprintf(stderr, "failed to attach ops\n");
+		return 1;
+	}
+
+
+	buffer = aligned_alloc(4096, buf_size);
+	if (!buffer) {
+		fprintf(stderr, "allocation failed\n");
+		return 1;
+	}
+
+	srand((unsigned)time(NULL));
+	for (i = 0; i < buf_size; i++) {
+		buffer[i] = rand() % 256;
+		xorv ^= buffer[i];
+	}
+
+	iov.iov_len = buf_size;
+	iov.iov_base = buffer;
+	ret = io_uring_register_buffers(&ctx.ring, &iov, 1);
+	if (ret < 0) {
+		fprintf(stderr, "can't register buffer\n");
+		return 1;
+	}
+
+	xs = ctx.region;
+	xs->regbuf_idx = 0;
+	xs->xor_size = buf_size;
+	ring_ctx_run(&ctx);
+
+	if (xs->xor_res != xorv) {
+		fprintf(stderr, "invalid result, %i %i\n", xorv, xs->xor_res);
+		return 1;
+	}
+
+	bpf_link__destroy(link);
+	xor__destroy(skel);
+	ring_ctx_destroy(&ctx);
+	return 0;
+}
-- 
2.52.0


  parent reply	other threads:[~2026-02-23 14:12 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-23 14:11 [PATCH 0/3] extra io_uring BPF examples Pavel Begunkov
2026-02-23 14:12 ` [PATCH 1/3] io_uring/selftests: add BPF'ed cp example Pavel Begunkov
2026-02-23 14:12 ` [PATCH 2/3] io_uring/selftests: add rate limiter BPF program Pavel Begunkov
2026-02-23 14:12 ` Pavel Begunkov [this message]
2026-02-23 14:14 ` [PATCH 0/3] extra io_uring BPF examples Jens Axboe
2026-02-23 14:32   ` Pavel Begunkov
2026-02-23 14:39     ` Jens Axboe
2026-02-23 15:06       ` Pavel Begunkov

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=09ea9cdafd870002278c2c8a62023c81aa742e2c.1771850496.git.asml.silence@gmail.com \
    --to=asml.silence@gmail.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=axboe@kernel.dk \
    --cc=bpf@vger.kernel.org \
    --cc=io-uring@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox