Articles

Speculative Execution Explained: Speed vs Security

Speculative execution lets a CPU guess ahead and run instructions before it knows they're needed, buying speed at the cost of the timing side channels behind Spectre and Meltdown.

Chisato Chisato · · 4 min read
Close-up of a computer chip on a fingertip

Speculative execution is a CPU performance technique where the processor guesses the outcome of a branch or the result of a slow operation and starts executing instructions based on that guess, before it actually knows whether the guess is correct. If the guess is right, the CPU has already done useful work and saved time. If it’s wrong, the CPU discards the speculative results and starts over — but the guess-and-discard cycle, done well, is far faster on average than waiting to be certain before every instruction.

Why CPUs guess at all

Modern processors are pipelined: many instructions are in flight simultaneously, at different stages of being decoded and executed, rather than running strictly one after another. This works well for straight-line code, but branches — if statements, loop conditions, function calls through a pointer — break the pipeline’s flow. The CPU can’t know which instructions come next until the branch condition is evaluated, and evaluating it might itself take many cycles, especially if it depends on a value still being fetched from memory.

Stalling the pipeline until every branch resolves would waste enormous amounts of otherwise idle execution capacity. So instead, the CPU predicts. See branch prediction and out-of-order execution for the mechanics of how that prediction is made — pattern history in a branch predictor, informed by how the same branch resolved in the recent past. Speculative execution is what the CPU does with that prediction: it doesn’t just predict, it actually starts running the predicted path, retiring the results only if the prediction turns out correct.

What happens when the guess is wrong

When a speculatively executed branch turns out to have been mispredicted, the CPU has to unwind: discard the speculative results, flush the pipeline of instructions that were executing down the wrong path, and restart from the correct branch. This is called a pipeline flush, and it’s expensive relative to a correctly predicted branch — but modern branch predictors are right often enough (well above 90% for typical code) that the average-case speedup from speculating outweighs the cost of the occasional flush.

Crucially, “discarding the results” in the architectural sense — the registers and memory the program can see — doesn’t mean the speculation left no trace. That gap between architectural state and microarchitectural state is exactly what created a new class of vulnerability.

The security problem: timing side channels

Speculatively executed instructions can still touch the CPU cache even though their results are never committed to visible program state. If a speculative instruction reads memory it shouldn’t have permission to read — because the permission check itself hadn’t completed before the CPU started speculating — that memory access can still change what’s sitting in the cache. And cache state is measurable: a subsequent, architecturally valid instruction can time how long it takes to access different memory locations. A cache hit is fast; a cache miss is slow. That timing difference leaks information about what the speculative instruction touched, even though the speculative instruction’s actual result was discarded.

This is the mechanism behind Spectre and Meltdown, the two vulnerability classes disclosed in early 2018 that put speculative execution security on the map. Spectre tricks a victim process into speculatively executing code that accesses memory it shouldn’t, using the attacker’s own carefully crafted inputs to manipulate the branch predictor. Meltdown exploited a more specific flaw in some processors that allowed speculative execution to read privileged kernel memory from user space entirely, before the permission check caught up. Both rely on the same underlying pattern: speculation leaves a measurable trace in the cache even when its results never touch program-visible state, and a timing attack is enough to read that trace out.

How it’s mitigated

Fixing this class of vulnerability without eliminating speculative execution — which would erase a large fraction of modern CPU performance — took multiple layers:

  • Hardware changes. Newer CPU designs add barriers that prevent certain speculative paths from executing across privilege boundaries, or that block speculative results from leaving a cache trace at all in sensitive contexts.
  • Software mitigations. Operating systems and compilers added specific barrier instructions (like retpolines and fencing instructions) that block the specific speculative patterns these attacks rely on, inserted at points where untrusted code could otherwise manipulate a victim’s branch predictor.
  • Isolation boundaries. Stricter separation between privilege levels and between tenants on shared hardware reduces how much an attacker’s speculative probing can actually reach.

None of these approaches eliminate speculative execution itself — that would mean giving up a large share of the performance gains it provides. They narrow the attack surface: making it harder to influence what a victim speculates on, and harder to read out the cache-timing signal afterward.

Speculative execution vs simple pipelining

Simple pipeliningSpeculative execution
Handles branches byStalling until resolvedGuessing and executing ahead
Wrong-guess costN/A (no guess made)Pipeline flush, discarded work
PerformanceLower on branch-heavy codeHigher, given accurate prediction
Security exposureNone from this mechanismCache-timing side channels (Spectre, Meltdown class)

The takeaway

Speculative execution is a trade CPUs make deliberately: guess ahead on likely-correct paths, and the average-case speedup outweighs the cost of occasionally guessing wrong. That trade held up fine as a pure performance question for decades — until it became clear that discarded speculative work isn’t perfectly invisible. It still moves data through the cache, and cache timing is measurable from software. The CPU architectures shipping today still speculate aggressively; they just do it with more mitigations around privilege boundaries than they did before 2018, because the alternative — turning speculation off — was never a realistic option for performance-sensitive hardware.

Chisato Chisato · · 4 min read

What Is Virtual Memory? Paging and Address Translation

Virtual memory gives every process its own private address space, mapped to physical RAM by the OS and CPU — enabling isolation, swapping, and overcommit.

#Hardware #Computer Science #Performance
Chisato Chisato · · 5 min read

What Is Memory Interleaving?

Memory interleaving spreads consecutive addresses across multiple memory banks so the system can access them in parallel instead of one at a time.

#Hardware #Computer Science #Performance
Chisato Chisato · · 5 min read

Big-Endian vs Little-Endian: Byte Order Explained

Endianness decides whether a multi-byte number's most or least significant byte is stored first in memory. Why it matters and how to spot it.

#Hardware #Computer Science #Performance