From d208c8a81b1b96dca72cc88dfabdd20df69d9303 Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Mon, 20 Apr 2026 21:12:51 +0800 Subject: [PATCH 1/2] bitops: Define generic __bitrev8/16/32 for reuse Define generic __bitrev8/16/32 using the implementation in , so they can be reused in , such as RISCV. And introduce a NEED_BYTE_REVERSE_TABLE Kconfig option, so byte_rev_table is only compiled when !HAVE_ARCH_BITREVERSE or when an architecture (like RISC-V) explicitly selects it as a fallback. This avoids bloating the .data section for architectures that have full hardware bit-reverse support and don't need the table. Reviewed-by: Yury Norov Signed-off-by: Jinjie Ruan Signed-off-by: Linux RISC-V bot --- include/asm-generic/bitops/__bitrev.h | 25 +++++++++++++++++++++++++ include/linux/bitrev.h | 20 ++++---------------- lib/Kconfig | 4 ++++ lib/bitrev.c | 4 ++-- 4 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 include/asm-generic/bitops/__bitrev.h diff --git a/include/asm-generic/bitops/__bitrev.h b/include/asm-generic/bitops/__bitrev.h new file mode 100644 index 00000000000000..9d7d3d3693646e --- /dev/null +++ b/include/asm-generic/bitops/__bitrev.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_GENERIC_BITOPS___BITREV_H_ +#define _ASM_GENERIC_BITOPS___BITREV_H_ + +#ifdef CONFIG_NEED_BYTE_REVERSE_TABLE +#include + +extern u8 const byte_rev_table[256]; +static __always_inline __attribute_const__ u8 generic___bitrev8(u8 byte) +{ + return byte_rev_table[byte]; +} + +static __always_inline __attribute_const__ u16 generic___bitrev16(u16 x) +{ + return (generic___bitrev8(x & 0xff) << 8) | generic___bitrev8(x >> 8); +} + +static __always_inline __attribute_const__ u32 generic___bitrev32(u32 x) +{ + return (generic___bitrev16(x & 0xffff) << 16) | generic___bitrev16(x >> 16); +} +#endif /* CONFIG_NEED_BYTE_REVERSE_TABLE */ + +#endif /* _ASM_GENERIC_BITOPS___BITREV_H_ */ diff --git a/include/linux/bitrev.h b/include/linux/bitrev.h index d35b8ec1c485cb..11620a70e77626 100644 --- a/include/linux/bitrev.h +++ b/include/linux/bitrev.h @@ -12,22 +12,10 @@ #define __bitrev8 __arch_bitrev8 #else -extern u8 const byte_rev_table[256]; -static inline u8 __bitrev8(u8 byte) -{ - return byte_rev_table[byte]; -} - -static inline u16 __bitrev16(u16 x) -{ - return (__bitrev8(x & 0xff) << 8) | __bitrev8(x >> 8); -} - -static inline u32 __bitrev32(u32 x) -{ - return (__bitrev16(x & 0xffff) << 16) | __bitrev16(x >> 16); -} - +#include +#define __bitrev32 generic___bitrev32 +#define __bitrev16 generic___bitrev16 +#define __bitrev8 generic___bitrev8 #endif /* CONFIG_HAVE_ARCH_BITREVERSE */ #define __bitrev8x4(x) (__bitrev32(swab32(x))) diff --git a/lib/Kconfig b/lib/Kconfig index 0f2fb96106476c..75cbb647b1da79 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -62,6 +62,10 @@ config HAVE_ARCH_BITREVERSE This option enables the use of hardware bit-reversal instructions on architectures which support such operations. +config NEED_BYTE_REVERSE_TABLE + bool + default y if !HAVE_ARCH_BITREVERSE + config ARCH_HAS_STRNCPY_FROM_USER bool diff --git a/lib/bitrev.c b/lib/bitrev.c index 81b56e0a7f325b..d9d5ee00229c9b 100644 --- a/lib/bitrev.c +++ b/lib/bitrev.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -#ifndef CONFIG_HAVE_ARCH_BITREVERSE +#ifdef CONFIG_NEED_BYTE_REVERSE_TABLE #include #include #include @@ -44,4 +44,4 @@ const u8 byte_rev_table[256] = { }; EXPORT_SYMBOL_GPL(byte_rev_table); -#endif /* CONFIG_HAVE_ARCH_BITREVERSE */ +#endif /* CONFIG_NEED_BYTE_REVERSE_TABLE */ From 7af812566b7180fbc4f5a2daf4a4f28b3baaea1a Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Mon, 20 Apr 2026 21:12:52 +0800 Subject: [PATCH 2/2] 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 NEED_BYTE_REVERSE_TABLE, and provide to utilize these instructions when the Zbkb extension is available at runtime via the alternatives mechanism. Link: https://docs.riscv.org/reference/isa/unpriv/b-st-ext.html Signed-off-by: Jinjie Ruan Signed-off-by: Linux RISC-V bot --- arch/riscv/Kconfig | 2 ++ arch/riscv/include/asm/bitrev.h | 51 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 arch/riscv/include/asm/bitrev.h diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 90c531e6abf5cf..465545200379d4 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -128,6 +128,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 select HAVE_ARCH_HUGE_VMALLOC if HAVE_ARCH_HUGE_VMAP select HAVE_ARCH_HUGE_VMAP if MMU && 64BIT select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL @@ -207,6 +208,7 @@ config RISCV select LOCK_MM_AND_FIND_VMA select MMU_GATHER_RCU_TABLE_FREE if SMP && MMU select MODULES_USE_ELF_RELA if MODULES + select NEED_BYTE_REVERSE_TABLE select OF select OF_EARLY_FLATTREE select OF_IRQ diff --git a/arch/riscv/include/asm/bitrev.h b/arch/riscv/include/asm/bitrev.h new file mode 100644 index 00000000000000..4b9b8d34cc3b2e --- /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 +#include +#include +#include + +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