aboutsummaryrefslogtreecommitdiffstats
diff options
authorJinjie Ruan <ruanjinjie@huawei.com>2026-05-06 13:52:05 -0400
committerYury Norov <ynorov@nvidia.com>2026-05-28 11:39:16 -0400
commite8620bd7e5e07c025a5e317ebc8c7df95dc63712 (patch)
tree8235998de706f1ae0371795350b414dc73d925b4
parent83aede8131afa99b26034f81fe77181eba38b0c2 (diff)
downloadlinux-next-history-e8620bd7e5e07c025a5e317ebc8c7df95dc63712.tar.gz
arch/riscv: Add bitrev.h file to support rev8 and brev8
The RISC-V Bit-manipulation Extension for Cryptography (Zbkb) provides the 'brev8' instruction, which reverses the bits within each byte. Combined with the 'rev8' instruction (from Zbb or Zbkb), which reverses the byte order of a register, we can efficiently implement 16-bit, 32-bit, and (on RV64) 64-bit bit reversal. This is significantly faster than the default software table-lookup implementation in lib/bitrev.c, as it replaces memory accesses and multiple arithmetic operations with just two or three hardware instructions. Select HAVE_ARCH_BITREVERSE as well as GENERIC_BITREVERSE, and provide <asm/bitrev.h> to utilize these instructions when the Zbkb extension is available at runtime via the alternatives mechanism. [Yury: select the options conditionally on BITREVERSE] Link: https://docs.riscv.org/reference/isa/unpriv/b-st-ext.html Suggested-by: David Laight <david.laight.linux@gmail.com> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> Signed-off-by: Yury Norov <ynorov@nvidia.com>
-rw-r--r--arch/riscv/Kconfig2
-rw-r--r--arch/riscv/include/asm/bitrev.h51
2 files changed, 53 insertions, 0 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index c5754942cf85a..ae2664b4160d0 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -104,6 +104,7 @@ config RISCV
select FUNCTION_ALIGNMENT_8B if DYNAMIC_FTRACE_WITH_CALL_OPS
select GENERIC_ARCH_TOPOLOGY
select GENERIC_ATOMIC64 if !64BIT
+ select GENERIC_BITREVERSE if HAVE_ARCH_BITREVERSE
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
select GENERIC_CPU_DEVICES
select GENERIC_CPU_VULNERABILITIES
@@ -128,6 +129,7 @@ config RISCV
select HAS_IOPORT if MMU
select HAVE_ALIGNED_STRUCT_PAGE
select HAVE_ARCH_AUDITSYSCALL
+ select HAVE_ARCH_BITREVERSE if RISCV_ISA_ZBKB && BITREVERSE
select HAVE_ARCH_HUGE_VMALLOC if HAVE_ARCH_HUGE_VMAP
select HAVE_ARCH_HUGE_VMAP if MMU && 64BIT
select HAVE_ARCH_JUMP_LABEL
diff --git a/arch/riscv/include/asm/bitrev.h b/arch/riscv/include/asm/bitrev.h
new file mode 100644
index 0000000000000..4b9b8d34cc3b2
--- /dev/null
+++ b/arch/riscv/include/asm/bitrev.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_BITREV_H
+#define __ASM_BITREV_H
+
+#include <linux/types.h>
+#include <asm/cpufeature-macros.h>
+#include <asm/hwcap.h>
+#include <asm-generic/bitops/__bitrev.h>
+
+static __always_inline __attribute_const__ u32 __arch_bitrev32(u32 x)
+{
+ unsigned long result;
+
+ if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZBKB))
+ return generic___bitrev32(x);
+
+ asm volatile(
+ ".option push\n"
+ ".option arch,+zbkb\n"
+ "rev8 %0, %1\n"
+ "brev8 %0, %0\n"
+ ".option pop"
+ : "=r" (result) : "r" ((long)x)
+ );
+
+ return result >> (__riscv_xlen - 32);
+}
+
+static __always_inline __attribute_const__ u16 __arch_bitrev16(u16 x)
+{
+ return __arch_bitrev32(x) >> 16;
+}
+
+static __always_inline __attribute_const__ u8 __arch_bitrev8(u8 x)
+{
+ unsigned long result;
+
+ if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZBKB))
+ return generic___bitrev8(x);
+
+ asm volatile(
+ ".option push\n"
+ ".option arch,+zbkb\n"
+ "brev8 %0, %1\n"
+ ".option pop"
+ : "=r" (result) : "r" ((long)x)
+ );
+
+ return result;
+}
+#endif