[PATCH 6/6] Add SHA3 acceleration for RISC-V "B" extension

Jussi Kivilinna jussi.kivilinna at iki.fi
Mon Jan 6 16:08:53 CET 2025


* cipher/keccak.c (USE_RISCV_B): New.
[USE_RISCV_B]: (ANDN64, ROL64, keccak_riscv_b_64_ops): New.
(keccak_init) [USE_RISCV_B]: Use 'keccak_riscv_b_64_ops' if
HWF_RISCV_IMAFDC and HWF_RISCV_B available.
--

Patch adds RISC-V "B" extension acceleration for SHA3.

Benchmark on SpacemiT K1 (1600 Mhz):

Before:
                |  nanosecs/byte   mebibytes/sec   cycles/byte
 SHA3-256       |     22.98 ns/B     41.51 MiB/s     36.76 c/B

After (2x faster):
                |  nanosecs/byte   mebibytes/sec   cycles/byte
 SHA3-256       |     11.15 ns/B     85.57 MiB/s     17.83 c/B

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 cipher/keccak.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/cipher/keccak.c b/cipher/keccak.c
index 44cc9f71..4ada6b4c 100644
--- a/cipher/keccak.c
+++ b/cipher/keccak.c
@@ -91,6 +91,15 @@
 #endif /* USE_S390X_CRYPTO */
 
 
+/* GCM_USE_RISCV_B indicates whether to compile GCM with RISC-V "B" extension
+ * code. */
+#undef USE_RISCV_B
+#if defined (__riscv) && (__riscv_xlen == 64) && \
+    defined(HAVE_GCC_INLINE_ASM_RISCV)
+# define USE_RISCV_B 1
+#endif
+
+
 /* x86-64 vector register assembly implementations use SystemV ABI, ABI
  * conversion needed on Win64 through function attribute. */
 #undef ASM_FUNC_ABI
@@ -359,7 +368,6 @@ static inline void absorb_lanes64_1(u64 *dst, const byte *in)
   dst[0] ^= buf_get_le64(in + 8 * 0);
 }
 
-
 # define ANDN64(x, y) (~(x) & (y))
 # define ROL64(x, n) (((x) << ((unsigned int)n & 63)) | \
 		      ((x) >> ((64 - (unsigned int)(n)) & 63)))
@@ -450,6 +458,48 @@ static const keccak_ops_t keccak_bmi2_64_ops =
 #endif /* USE_64BIT_BMI2 */
 
 
+/* Construct 64-bit RISC-V "B" extension implementation. */
+#ifdef USE_RISCV_B
+
+# define ANDN64(x, y) ({ \
+			u64 tmp; \
+			asm (".option push;\n\t" \
+			    ".option arch, +zbb;\n\t" \
+			    "andn %0, %1, %2;\n\t" \
+			    ".option pop;\n\t" \
+			    : "=r" (tmp) \
+			    : "r" (y), "r" (x)); \
+			tmp; })
+
+# define ROL64(x, n) ({ \
+			u64 tmp; \
+			asm (".option push;\n\t" \
+			    ".option arch, +zbb;\n\t" \
+			    "rori %0, %1, %2;\n\t" \
+			    ".option pop;\n\t" \
+			    : "=r" (tmp) \
+			    : "r" (x), "I" ((64 - n) & 63)); \
+			tmp; })
+
+# define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute64_riscv_b
+# define KECCAK_F1600_ABSORB_FUNC_NAME keccak_absorb_lanes64_riscv_b
+# include "keccak_permute_64.h"
+
+# undef ANDN64
+# undef ROL64
+# undef KECCAK_F1600_PERMUTE_FUNC_NAME
+# undef KECCAK_F1600_ABSORB_FUNC_NAME
+
+static const keccak_ops_t keccak_riscv_b_64_ops =
+{
+  .permute = keccak_f1600_state_permute64_riscv_b,
+  .absorb = keccak_absorb_lanes64_riscv_b,
+  .extract = keccak_extract64,
+};
+
+#endif /* USE_RISCV_B */
+
+
 /* 64-bit Intel AVX512 implementation. */
 #ifdef USE_64BIT_AVX512
 
@@ -1002,6 +1052,10 @@ keccak_init (int algo, void *context, unsigned int flags)
   else if (features & HWF_INTEL_FAST_SHLD)
     ctx->ops = &keccak_shld_64_ops;
 #endif
+#ifdef USE_RISCV_B
+  else if ((features & HWF_RISCV_IMAFDC) && (features & HWF_RISCV_B))
+    ctx->ops = &keccak_riscv_b_64_ops;
+#endif
 
   /* Set input block size, in Keccak terms this is called 'rate'. */
 
-- 
2.45.2




More information about the Gcrypt-devel mailing list