What Defenders Can Reliably Do Today
For current RISC-V systems, the hard security decision is not “which mitigation is best?” in the abstract. It is which defense protects the relevant Spectre path on this processor, in this software layer, under this workload, and with a guarantee strong enough to justify the cost. The available options—SLH, fences, retpolines, branchless dispatch, masking, configuration changes, and runtime probing—solve different problems and carry different assumptions. This chapter compares them as conditional engineering choices rather than as a universal checklist.
Compiler and JIT defenses: choose the property first
SLH: constrain the data path without stopping all speculation
Speculative Load Hardening, or SLH, addresses a PHT-style problem by carrying a speculation predicate through branchless operations. After a conditional branch, the predicate reflects whether execution may be on a misspeculated path. Later loads use that predicate to mask an address or value, creating a dependency that prevents a transient path from using the unsafe result directly. The processor may still speculate, but the speculative load is denied a useful secret-dependent address or value.
That design gives SLH a different cost profile from a broad fence. It targets the data flow following conditional branches instead of halting all speculation at every protected point. The USENIX study reports that an open-source Ultimate SLH implementation for RISC-V exists, but mainstream GCC and LLVM toolchains do not implement RISC-V Spectre mitigations. So SLH is a credible current userspace strategy only for a team willing to integrate, test, and maintain a non-mainstream compiler path or wait for production support.
The reported performance result is comparatively favorable. On the C910, SLH produced a geometric-mean slowdown of 1.34× across the SPEC CPU 2017 test workloads, with results ranging from 0.97× to 2.69×. The paper compares that with roughly 2.5× reported for SLH on x86 in the cited context. These numbers do not make SLH free, and they do not show that every program or every Spectre family is covered. They do show why a data-flow defense can be preferable when the threat is conditional-branch misuse and the workload can tolerate its added dependencies.
SLH also has a scope boundary. It is aimed at Spectre-PHT and is not a substitute for a defense against indirect-branch target poisoning, return prediction, or store-to-load bypass. A compiler cannot apply it as a label and assume that all later code is safe; the implementation must preserve the dependency and the generated code must be checked. The choice is therefore “SLH for applicable userspace data paths, with a supported and validated toolchain,” not “SLH solves Spectre on RISC-V.”
Fence insertion: a direct boundary with a high price
Fence insertion takes a more blunt approach. A compiler can place a barrier after a conditional branch so that speculative execution cannot proceed past a security-critical check. Conceptually, this is easy to explain: let the check resolve before permitting later work. Operationally, it blocks all speculation in that region, including speculation that would have been harmless, and it requires an instruction with the correct security semantics.
RISC-V makes the second condition difficult. The base ISA has no dedicated speculation barrier, and the ordinary fence instruction orders memory operations without guaranteeing that speculative execution stops. The study evaluates fence.i and an rdtime-based sequence as empirical candidates on the C910. Both stop speculation in the tested setting, but their costs differ sharply. Across 23 SPEC CPU 2017 test workloads, fence.i insertion has a geometric-mean slowdown of 46.6×, while the rdtime-based fence has a slowdown of 2.69×.