From: Leon Hwang <leon.hwang@linux.dev>
To: bpf@vger.kernel.org
Cc: ast@kernel.org, andrii@kernel.org, daniel@iogearbox.net,
Leon Hwang <leon.hwang@linux.dev>
Subject: [RFC PATCH bpf-next 3/4] bpf, arm64: Add 64bit bitops kfuncs support
Date: Mon, 9 Feb 2026 23:59:14 +0800 [thread overview]
Message-ID: <20260209155919.19015-4-leon.hwang@linux.dev> (raw)
In-Reply-To: <20260209155919.19015-1-leon.hwang@linux.dev>
Implement JIT inlining of the 64bit bitops kfuncs on arm64.
bpf_clz64(), bpf_ffs64(), bpf_fls64(), and bpf_bitrev64() are always
supported using mandatory ARMv8 CLZ/RBIT instructions. bpf_ctz64() is
implemented via RBIT + CLZ, or via the native CTZ instruction when
FEAT_CSSC is available. bpf_rol64() and bpf_ror64() are always
supported via RORV.
bpf_popcnt64() is not supported as the native population count
instruction requires NEON/SIMD registers, which should not be touched
from BPF programs.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
arch/arm64/net/bpf_jit_comp.c | 143 ++++++++++++++++++++++++++++++++++
1 file changed, 143 insertions(+)
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 2dc5037694ba..b91896cef247 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -1199,6 +1199,123 @@ static int add_exception_handler(const struct bpf_insn *insn,
return 0;
}
+static inline u32 a64_clz64(u8 rd, u8 rn)
+{
+ /*
+ * Arm Architecture Reference Manual for A-profile architecture
+ * (Document number: ARM DDI 0487)
+ *
+ * A64 Base Instruction Descriptions
+ * C6.2 Alphabetical list of A64 base instructions
+ *
+ * C6.2.91 CLZ
+ *
+ * Count leading zeros
+ *
+ * This instruction counts the number of consecutive binary zero bits,
+ * starting from the most significant bit in the source register,
+ * and places the count in the destination register.
+ */
+ /* CLZ Xd, Xn */
+ return 0xdac01000 | (rn << 5) | rd;
+}
+
+static inline u32 a64_ctz64(u8 rd, u8 rn)
+{
+ /*
+ * Arm Architecture Reference Manual for A-profile architecture
+ * (Document number: ARM DDI 0487)
+ *
+ * A64 Base Instruction Descriptions
+ * C6.2 Alphabetical list of A64 base instructions
+ *
+ * C6.2.144 CTZ
+ *
+ * Count trailing zeros
+ *
+ * This instruction counts the number of consecutive binary zero bits,
+ * starting from the least significant bit in the source register,
+ * and places the count in the destination register.
+ *
+ * This instruction requires FEAT_CSSC.
+ */
+ /* CTZ Xd, Xn */
+ return 0xdac01800 | (rn << 5) | rd;
+}
+
+static inline u32 a64_rbit64(u8 rd, u8 rn)
+{
+ /*
+ * Arm Architecture Reference Manual for A-profile architecture
+ * (Document number: ARM DDI 0487)
+ *
+ * A64 Base Instruction Descriptions
+ * C6.2 Alphabetical list of A64 base instructions
+ *
+ * C6.2.320 RBIT
+ *
+ * Reverse bits
+ *
+ * This instruction reverses the bit order in a register.
+ */
+ /* RBIT Xd, Xn */
+ return 0xdac00000 | (rn << 5) | rd;
+}
+
+static inline bool supports_cssc(void)
+{
+ /*
+ * Documentation/arch/arm64/cpu-feature-registers.rst
+ *
+ * ID_AA64ISAR2_EL1 - Instruction set attribute register 2
+ *
+ * CSSC
+ */
+ return cpuid_feature_extract_unsigned_field(read_sanitised_ftr_reg(SYS_ID_AA64ISAR2_EL1),
+ ID_AA64ISAR2_EL1_CSSC_SHIFT);
+}
+
+static int emit_bitops(struct jit_ctx *ctx, s32 imm)
+{
+ const u8 r0 = bpf2a64[BPF_REG_0];
+ const u8 r1 = bpf2a64[BPF_REG_1];
+ const u8 r2 = bpf2a64[BPF_REG_2];
+ const u8 tmp = bpf2a64[TMP_REG_1];
+
+ switch (imm) {
+ case BPF_CLZ64:
+ emit(a64_clz64(r0, r1), ctx);
+ break;
+ case BPF_CTZ64:
+ case BPF_FFS64:
+ if (supports_cssc()) {
+ emit(a64_ctz64(r0, r1), ctx);
+ } else {
+ emit(a64_rbit64(tmp, r1), ctx);
+ emit(a64_clz64(r0, tmp), ctx);
+ }
+ break;
+ case BPF_FLS64:
+ emit(a64_clz64(tmp, r1), ctx);
+ emit(A64_NEG(1, tmp, tmp), ctx);
+ emit(A64_ADD_I(1, r0, tmp, 64), ctx);
+ break;
+ case BPF_BITREV64:
+ emit(a64_rbit64(r0, r1), ctx);
+ break;
+ case BPF_ROL64:
+ emit(A64_NEG(1, tmp, r2), ctx);
+ emit(A64_DATA2(1, r0, r1, tmp, RORV), ctx);
+ break;
+ case BPF_ROR64:
+ emit(A64_DATA2(1, r0, r1, r2, RORV), ctx);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
/* JITs an eBPF instruction.
* Returns:
* 0 - successfully JITed an 8-byte eBPF instruction.
@@ -1451,6 +1568,11 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
case BPF_ALU64 | BPF_ARSH | BPF_K:
emit(A64_ASR(is64, dst, dst, imm), ctx);
break;
+ case BPF_ALU64 | BPF_BITOPS:
+ ret = emit_bitops(ctx, imm);
+ if (ret)
+ return ret;
+ break;
/* JUMP reg */
case BPF_JMP | BPF_JA | BPF_X:
@@ -3207,3 +3329,24 @@ void bpf_jit_free(struct bpf_prog *prog)
bpf_prog_unlock_free(prog);
}
+
+bool bpf_jit_inlines_bitops(s32 imm)
+{
+ switch (imm) {
+ case BPF_CLZ64:
+ case BPF_CTZ64:
+ case BPF_FFS64:
+ case BPF_FLS64:
+ case BPF_BITREV64:
+ /* They use RBIT/CLZ/CTZ which are mandatory in ARM64 */
+ return true;
+ case BPF_POPCNT64:
+ /* We should not touch NEON/SIMD register to support popcnt64 */
+ return false;
+ case BPF_ROL64:
+ case BPF_ROR64:
+ return true;
+ default:
+ return false;
+ }
+}
--
2.52.0
next prev parent reply other threads:[~2026-02-09 16:00 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-09 15:59 [RFC PATCH bpf-next 0/4] bpf: Introduce 64bit bitops kfuncs Leon Hwang
2026-02-09 15:59 ` [RFC PATCH bpf-next 1/4] " Leon Hwang
2026-02-11 3:05 ` Alexei Starovoitov
2026-02-11 3:29 ` Leon Hwang
2026-02-09 15:59 ` [RFC PATCH bpf-next 2/4] bpf, x86: Add 64bit bitops kfuncs support for x86_64 Leon Hwang
2026-02-09 15:59 ` Leon Hwang [this message]
2026-02-09 15:59 ` [RFC PATCH bpf-next 4/4] selftests/bpf: Add tests for 64bit bitops kfuncs Leon Hwang
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=20260209155919.19015-4-leon.hwang@linux.dev \
--to=leon.hwang@linux.dev \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
/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