The ISA Is Not the Whole Machine

This series studies a specific security question about commercial RISC-V processors: does an open instruction-set architecture tell us enough to know whether speculative execution is safe? The focus is the relationship among the RISC-V ISA, concrete out-of-order implementations such as the SiFive P550 and T-Head Xuantie C910/C920, and the compilers, kernels, firmware, and deployment practices that rely on them. The practical goal is to learn how to separate what a processor is required to guarantee from what a particular implementation merely happens to do.

That distinction matters because RISC-V is often described through its openness and simplicity. Those properties are real and important. They explain why many independent organizations can build processors around a shared instruction-set foundation. But they do not mean that every processor built on that foundation has the same predictors, caches, speculation behavior, or security boundaries. An ISA can make programs portable while leaving important parts of the machine’s internal behavior to implementers.

RISC-V is a foundation, not a finished machine

An instruction-set architecture is the interface that software is meant to see. It defines instructions, registers, memory behavior, privilege mechanisms, and other programmer-visible rules. RISC-V International describes RISC-V as an open, modular, customizable, royalty-free ISA whose specifications are developed and maintained by contributing members. That model changes who can design and adapt a processor. It does not turn the processor into a standardized physical object.

The boundary is especially important for security. The ISA can specify what an instruction means when it commits, while leaving open how a core predicts a branch, how many instructions it keeps in flight, how prediction structures are indexed, or how internal state is cleared. Those choices can be invisible during ordinary program execution and still matter when an attacker measures timing or another side effect. RISC-V’s extension model makes the range wider: optional standard extensions and vendor-specific additions may change both capabilities and assumptions, and custom semantics can be difficult for outsiders to analyze. Portability of an instruction stream is therefore not the same thing as portability of every security property that surrounds its execution.

The difference becomes important when performance depends on work that software does not directly see. A simple in-order core may wait for an instruction’s dependencies to resolve before proceeding. A superscalar out-of-order core may instead keep many instructions in flight, predict which way control flow will go, and begin useful work before every condition is known. Both can execute valid RISC-V programs. Their internal machinery—and therefore the ways information can move through that machinery—can be very different.

That flexibility is one of RISC-V’s strengths. It supports small embedded designs, research processors, and higher-performance commercial cores without requiring all of them to share one implementation strategy. It also creates a security responsibility that is easy to miss: a security property cannot be assumed to exist merely because the same ISA name appears on the box. If the property depends on prediction, caching, instruction issue, or serialization, it needs either an architectural guarantee or a way for software to discover the implementation’s behavior safely.

The distinction is not academic. The USENIX study at the center of this series examined the SiFive P550 and T-Head Xuantie C910/C920, which the authors identify as the commercially available out-of-order RISC-V processors available to them at the time of writing. They did not study an abstract “RISC-V processor.” They studied named designs with particular predictor structures, firmware settings, and software environments. That choice is what turns a general concern into evidence about hardware that can be deployed.

It also changes the question a maintainer or operator should ask. “Is the RISC-V port hardened?” is too broad to answer from a source tree or an ISA manual. The useful questions are narrower: which concrete core is running, which prediction features are active, what does the firmware configure, and what instruction sequence does the compiler or JIT actually emit? The answer may differ between two products that run the same binary and between two configurations of one product. A security claim becomes meaningful only when its owner, operating conditions, and boundary are named.

flowchart LR A["Open RISC-V ISA"] --> B["Independent microarchitectural implementation choices"] A --> D["Compiler and kernel assumptions"] B --> C["Predictors and speculative execution"] F["Firmware and deployment configuration"] --> C D --> E["Generated software behavior"] C --> G["Observed speculation-security properties"] E --> G

The flow is deliberately not one-way. The ISA influences what software can express, but the concrete core determines how prediction and transient execution behave. Firmware can enable or disable features. Compilers and kernels can insert, omit, or mis-lower a protection. The security outcome is produced by the interaction, not by the ISA label alone.

This is why a security contract must travel with an implementation rather than stop at the instruction-set boundary. A compiler needs to know what it may safely emit. A kernel needs to know whether a generic barrier name has a real architectural meaning on the current target. Firmware needs to make security-relevant configuration visible instead of leaving it as an undocumented default. Operators need a way to distinguish a tested configuration from an untested one. Without those handoffs, every layer can appear reasonable in isolation while the combined system makes a promise that no layer actually owns.

Why a correct instruction stream can still leak

Spectre makes this interaction visible. Modern out-of-order processors often predict control or data flow so that execution can continue while a branch, memory dependency, or other condition is unresolved. When the prediction is wrong, the processor can discard the instructions that depended on it and preserve architectural correctness. From the program’s visible point of view, the wrong path never happened.

The machine’s internal history is less clean. Instructions on the wrong path may have changed caches, predictor tables, queues, or other microarchitectural state before the processor recognized the mistake. An attacker who can influence a prediction and then observe one of those traces may infer information that the architectural program never returned. The crucial security boundary is therefore not simply “was an invalid instruction committed?” It is “did a transient operation leave an observable effect before the check completed?”

This is why Spectre is not one defect with one universal fix. Different attacks manipulate different forms of internal state. Some influence conditional-branch history and cause a bounds check to be predicted incorrectly. Some redirect an indirect branch through a branch-target structure. Some target the return predictor. Another family relies on a mistaken assumption about whether a load depends on an earlier store. The study groups these as PHT, BTB, RSB, and STL variants and tests them across same-address and cross-address settings, as well as attacks that train the same instruction or a different colliding instruction.

Those distinctions matter because sharing changes the threat. A predictor state that is isolated between user and kernel modes may block one cross-privilege path while leaving same-privilege attacks possible. A predictor that is disabled by default in one firmware configuration may become part of the attack surface when enabled in another. An implementation that does not fall back from one prediction structure to another may support a defense that would be unreliable elsewhere. The ISA alone does not answer these questions.

Nor does speculation automatically imply a practical exploit. A usable path must contain a suitable gadget, allow the attacker enough influence over relevant state, and expose a covert channel that can be measured. The paper’s threat model assumes code execution on the same machine as the victim and seeks architecturally inaccessible data. That is a serious scenario for shared systems, but it is narrower than saying that any RISC-V program is immediately compromised. Careful security analysis must preserve both sides of that statement: speculative behavior can defeat isolation, and exploitability still depends on conditions.

The question beneath the benchmark

The study is significant partly because of what came before it. Earlier RISC-V Spectre research had focused mainly on academic or research-grade processors. Commercial silicon had been examined for other microarchitectural attacks, but the authors describe the commercial out-of-order space as unexplored for a systematic, end-to-end Spectre assessment. Their work moves the discussion from what an experimental core might permit to what named products actually do.

That does not make the result a universal verdict on every RISC-V implementation. The authors also tested particular in-order processors and observed no leakage on those systems. A negative observation on those chips is useful evidence about those configurations, but it is not an ISA-level guarantee. Likewise, treating the C910 and C920 as one core microarchitecture for the relevant analysis does not erase the fact that their firmware defaults can differ. Scope is part of the result.

The deeper issue is how software knows which scope applies. Security code frequently relies on abstractions such as “insert a speculation barrier here,” “mask this index,” or “protect this indirect call.” Those abstractions are only as strong as the lowest layer that implements them. If an instruction is architecturally defined only to order memory, software cannot safely assume that it also stops speculative issue. If a processor-specific instruction appears to halt speculation in a test, that observation may be useful for a deployment, but it is not yet a portable contract.

This creates a gap between three kinds of statements that are often blurred together:

  • The ISA guarantees what software may rely on across conforming implementations.
  • The implementation exhibits behavior that engineers can measure on a particular processor and configuration.
  • The software stack assumes that a familiar mitigation name has the same security meaning everywhere.

Spectre becomes dangerous when the third statement is stronger than the first, while the second remains hidden or undocumented. A kernel can contain a security-aware interface and still emit no effective protection for one architecture. A compiler can provide a mitigation prototype that fails to preserve program correctness. A deployment can report a processor as unaffected simply because its vulnerability-status plumbing has no architecture-specific handler. These are not separate curiosities; they are failures to keep a security promise intact as it crosses boundaries.

The question for RISC-V is therefore not whether openness is good or whether speculation should exist. The useful question is what an explicit speculation contract would require. It would need to say which operations can stop or constrain speculation, make relevant implementation differences discoverable, and give compilers, kernels, and JITs a reliable way to preserve those guarantees. It would also need validation on real hardware, because a shared ISA does not remove the differences among the machines that implement it.

That is the tension this series will follow. RISC-V’s openness makes a broad ecosystem possible. The same openness makes it unsafe to infer a complete security model from the ISA alone. The next step is to examine the speculative execution mechanism itself: how a processor can execute a path it later discards, and how that discarded path can nevertheless become evidence about data it was never supposed to reveal.

References