SP RISC-V 64-bit: new implementation - #11135
Conversation
|
Code generated with PR: |
|
SM2 code: |
dgarske
left a comment
There was a problem hiding this comment.
Review findings - wolfSSL PR 11135 and wolfsm PR 33 (RISC-V 64-bit SP)
Testing performed on 2026-08-13 against wolfssl-alt2 pr11135 (commit 124b5c0d7) and wolfsm pr33 (commit 4b1f214), cross-compiled with the Microchip PolarFire SoC Yocto toolchain (GCC 13.3.0, riscv64-mchp-linux, default rv64imafdc/lp64d) and executed under qemu-riscv64 8.2.2.
What passes
The implementation itself is in good shape. With --enable-all --enable-sp-asm --enable-riscv-asm:
sp_riscv64.cis correctly selected as the only SP backend (nosp_c64.oin the build).testwolfcryptpasses completely - RSA, DH, ECC P-256/384/521, SAKKE, ML-KEM, and the full OpenSSL-compat suite.-O1,-Os,-O2and-Ofastall build and pass.- wolfsm PR 33's
sp_sm2_riscv64.ccompiles and is the only SM2 backend selected; SM2P256V1 key generation, ECDHE, ECDSA sign and verify all execute, and SM3/SM4-CBC/SM4-GCM benchmark clean. - The code is base RV64IM only (no Zb*, Zk*, or V), so it runs on cores without any ISA extensions. Verified by compiling clean at
-march=rv64imac -mabi=lp64(PolarFire SoC E51) as well asrv64gc/lp64d(U54), with GCC 8.3.0 and GCC 15.1.0 in addition to 13.3.0.
1. sp_riscv64.c fails to build at -O0, or with -fno-omit-frame-pointer at any level
Severity: high. This is the one finding that should block merge.
wolfcrypt/src/sp_riscv64.c: In function 'sp_2048_sqr_16':
wolfcrypt/src/sp_riscv64.c:5989:1: error: s0 cannot be used in 'asm' here
s0 is the frame pointer (fp) on RISC-V. Three assembly blocks list it in their clobber list, so any build in which GCC must keep a frame pointer is rejected.
Reproduced matrix (same compiler, same defines, only the flags differ):
| Flags | Result |
|---|---|
-O0 |
FAIL |
-O0 -fPIC |
FAIL |
-O2 -fno-omit-frame-pointer |
FAIL |
-O1 / -Os / -O2 / -Ofast |
ok |
Affected sites, all in fully-unrolled 16-limb squaring routines:
| Line of clobber list | Function |
|---|---|
wolfcrypt/src/sp_riscv64.c:5987 |
sp_2048_sqr_16 (definition at 4223) |
wolfcrypt/src/sp_riscv64.c:11293 |
sp_2048_sqr_16 (definition at 9529) |
wolfcrypt/src/sp_riscv64.c:72039 |
sp_1024_sqr_16 (definition at 70275) |
This is not a simple register rename. The clobber list is t0-t6, a2-a7, s1-s11, plus s0 - 25 registers - and the two "+r" operands take 2 more, for 27. RISC-V has 32 GPRs of which zero, ra, sp, gp and tp are unusable, leaving 27 only when s0 is not reserved as a frame pointer. So the routine currently fits exactly, and only when the frame pointer is omitted. Freeing a register (spilling one value to the stack) in the generator looks like the real fix.
Worth noting for context: -fno-omit-frame-pointer is not exotic - Ubuntu and Fedora both build with frame pointers enabled by default now for profiling, and -O0 is a normal debug build.
For comparison, neither sp_arm64.c nor sp_x86_64.c ever clobbers its platform's frame-pointer register (x29 / rbp) - zero occurrences in each. wolfsm's sp_sm2_riscv64.c is also clean (zero s0 clobbers), so this is confined to sp_riscv64.c.
2. CI never compiles the new file
.github/configs/multi-arch.json has five riscv64 jobs and none of them passes --enable-sp-asm:
| Job | --enable-sp-asm |
--enable-riscv-asm |
CFLAGS |
|---|---|---|---|
riscv64-o0 |
no | yes | -O0 |
riscv64-o1-no-fp-ecc |
no | yes | -O1 -UFP_ECC |
riscv64-os |
no | yes | -Os |
riscv64-o2 |
no | yes | -O2 |
riscv64-ofast |
no | yes | -Ofast |
So 83,000 lines of new assembly land with no CI coverage at all. Adding --enable-sp-asm to at least one riscv64 entry would fix that - and note that adding it to riscv64-o0 would immediately surface finding 1, which is a good argument for doing exactly that once the s0 issue is resolved.
The explanatory comment at .github/workflows/multi-arch.yml:58-63 ("riscv64's --enable-riscv-asm (unlike the other arches' --enable-sp-asm) does not bring it in") is now stale and should be updated alongside.
3. WOLFSSL_SP_RISCV64_ASM is documented nowhere
grep -rn WOLFSSL_SP_RISCV64_ASM doc/ examples/ returns zero hits. Three specific places are now wrong or incomplete:
doc/ASM_AND_MATH_DEFINES.md:541-542states the opposite of what is now true: "RISC-V has no specialised SP assembly, so useWOLFSSL_SP_RISCV64for the inline tier."doc/ASM_AND_MATH_DEFINES.md:100- the per-CPU table row for RISC-V 64 readsadd WOLFSSL_SP_RISCV64, WOLFSSL_RISCV_ASM (+ extension defines), with no mention of the new macro. Compare the Aarch64 row directly above it, which does listWOLFSSL_SP_ARM64_ASM.doc/ASM_AND_MATH_DEFINES.md:222- the word-size table listsWOLFSSL_SP_RISCV64/WOLFSSL_SP_RISCV32but not the_ASMvariant.
The near-miss naming makes this more than a cosmetic gap: WOLFSSL_SP_RISCV64 and WOLFSSL_SP_RISCV64_ASM differ by a suffix and select completely different implementations, so a reader who follows the current documentation silently gets the slow inline tier.
4. user_settings_embedded.h cannot select the new backend
examples/configs/user_settings_embedded.h:848-851:
#elif WC_CFG_CPU_RISCV64
#if WC_CFG_ASM_SP
#define WOLFSSL_SP_RISCV64
#endifWC_CFG_ASM_SP is the switch that means "give me big-number assembly", so on RISC-V 64 it should now emit WOLFSSL_SP_RISCV64_ASM. As written, anyone configuring an embedded build through this template gets the inline tier and none of the new code, with no indication anything is missing.
The per-CPU source-file list in the same file's header comment (lines 58-68) also needs wolfcrypt/src/sp_riscv64.c adding, next to the existing sp_arm64.c / sp_x86_64.c entries.
5. No HAVE___UINT128_T fallback on the RISC-V 64 SP path
wolfssl/wolfcrypt/sp_int.h:254 sets SP_WORD_SIZE 64 unconditionally for WOLFSSL_SP_RISCV64_ASM and WOLFSSL_SP_RISCV64, but the sp_int_word / sp_int_sword typedefs at lines 326-330 are only emitted when WOLFSSL_UINT128_T_DEFINED is set, which in turn requires HAVE___UINT128_T. A user_settings.h build that does not define it therefore fails deep inside sp_int.c with:
wolfcrypt/src/sp_int.c:6666:5: error: unknown type name 'sp_int_word'
The x86_64 path two dozen lines above handles this - sp_int.h:217-218 degrades to SP_WORD_SIZE 32 when HAVE___UINT128_T is absent. The RISC-V path has no equivalent.
This pre-dates the PR for the WOLFSSL_SP_RISCV64 spelling, but the PR extends the same condition to WOLFSSL_SP_RISCV64_ASM, so it now affects the new code path too. Autotools masks it because configure probes for the type and passes -DHAVE___UINT128_T=1; only hand-written builds hit it. Either mirror the x86_64 fallback, or auto-define from __SIZEOF_INT128__, or at minimum document the requirement.
6. wolfsm install.sh does not copy the new MSVC assembly file
Severity: low. wolfsm PR 33 adds sp_sm2_x86_64_asm.asm (the masm/MSVC counterpart to the existing GNU-as .S), but install.sh copies only the .S:
31: cp sp_sm2_x86_64.c $WOLFSSL_DIR/wolfcrypt/src/
32: cp sp_sm2_x86_64_asm.S $WOLFSSL_DIR/wolfcrypt/src/
So the new file never reaches a wolfSSL tree and cannot be used by a Visual Studio build. The RISC-V addition on line 33 is correct - this is only about the x86_64 masm file that came along in the same commit.
Suggested minimum before merge
- Fix the
s0clobber in the three squaring routines (finding 1). - Add
--enable-sp-asmto at least one riscv64 CI job so the file is compiled at all (finding 2), ideallyriscv64-o0once finding 1 is fixed. - Document
WOLFSSL_SP_RISCV64_ASMand correct the three stale statements indoc/ASM_AND_MATH_DEFINES.md(finding 3). - Emit the new macro from
user_settings_embedded.h(finding 4).
Findings 5 and 6 are fine to handle separately.
Implementation of all SP algorithms/parameters for RISC-V 64-bit CPU.
|
fixed review issues |
|
Both builds below are
1.45x to 2.07x on everything the backend covers, with RSA private-key operations gaining most. The flat rows are the expected ones: Brainpool P-256 falls through to the generic path in both builds, and AES/SHA-256 are governed by |
Description
Implementation of all SP algorithms/parameters for RISC-V 64-bit CPU.
Testing
Tested all algorithms including SAKKE and SM2 for SP ASM for RISC-V 64-bit.