[PATCH] 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 and provide <asm/bitrev.h> to utilize these instructions when the Zbkb extension is available at runtime via the alternatives mechanism. Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> --- arch/riscv/Kconfig | 1 + arch/riscv/include/asm/bitrev.h | 46 +++++++++++++++++++++++++++++++++ lib/bitrev.c | 3 --- 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 arch/riscv/include/asm/bitrev.h diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 90c531e6abf5..e7a04b96c0c8 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 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 diff --git a/arch/riscv/include/asm/bitrev.h b/arch/riscv/include/asm/bitrev.h new file mode 100644 index 000000000000..b1977600638a --- /dev/null +++ b/arch/riscv/include/asm/bitrev.h @@ -0,0 +1,46 @@ +/* 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> + +extern u8 const byte_rev_table[256]; +static __always_inline __attribute_const__ u32 __arch_bitrev32(u32 x) +{ + if (IS_ENABLED(CONFIG_RISCV_ISA_ZBKB) && + riscv_has_extension_likely(RISCV_ISA_EXT_ZBKB)) { + unsigned long result = x; + + asm volatile( + ".option push\n" + ".option arch,+zbkb\n" + "rev8 %0, %0\n" + "brev8 %0, %0\n" + ".option pop" + : "+r" (result) + ); + + if (__riscv_xlen == 64) + return (u32)(result >> 32); + + return (u32)result; + } + + return (u32)byte_rev_table[x & 0xff] << 24 | + (u32)byte_rev_table[(x >> 8) & 0xff] << 16 | + (u32)byte_rev_table[(x >> 16) & 0xff] << 8 | + (u32)byte_rev_table[x >> 24]; +} + +static __always_inline __attribute_const__ u16 __arch_bitrev16(u16 x) +{ + return __arch_bitrev32((u32)x) >> 16; +} + +static __always_inline __attribute_const__ u8 __arch_bitrev8(u8 x) +{ + return __arch_bitrev32((u32)x) >> 24; +} +#endif diff --git a/lib/bitrev.c b/lib/bitrev.c index 81b56e0a7f32..05088231f31f 100644 --- a/lib/bitrev.c +++ b/lib/bitrev.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0-only -#ifndef CONFIG_HAVE_ARCH_BITREVERSE #include <linux/types.h> #include <linux/module.h> #include <linux/bitrev.h> @@ -43,5 +42,3 @@ const u8 byte_rev_table[256] = { 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, }; EXPORT_SYMBOL_GPL(byte_rev_table); - -#endif /* CONFIG_HAVE_ARCH_BITREVERSE */ -- 2.34.1
participants (1)
-
Jinjie Ruan