diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 90c531e6abf5cf..05f2b2166a8380 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 diff --git a/arch/riscv/include/asm/bitrev.h b/arch/riscv/include/asm/bitrev.h new file mode 100644 index 00000000000000..eef263cc6655b6 --- /dev/null +++ b/arch/riscv/include/asm/bitrev.h @@ -0,0 +1,55 @@ +/* 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 = (unsigned long)x; + + if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZBKB)) + return generic___bitrev32(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); +#else + return (u32)result; +#endif +} + +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) +{ + unsigned long result = (unsigned long)x; + + if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZBKB)) + return generic___bitrev8(x); + + asm volatile( + ".option push\n" + ".option arch,+zbkb\n" + "brev8 %0, %0\n" + ".option pop" + : "+r" (result) + ); + + return (u8)result; +} +#endif diff --git a/include/asm-generic/bitops/__bitrev.h b/include/asm-generic/bitops/__bitrev.h new file mode 100644 index 00000000000000..1b8c0f464d267b --- /dev/null +++ b/include/asm-generic/bitops/__bitrev.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_GENERIC_BITOPS___BITREV_H_ +#define _ASM_GENERIC_BITOPS___BITREV_H_ + +#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 /* _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/bitrev.c b/lib/bitrev.c index 81b56e0a7f325b..05088231f31fd4 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 #include #include @@ -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 */