Home · ASPLOS 2025 · Security, Privacy & Trusted Execution

Reload+Reload: Exploiting Cache and Memory Contention Side Channel on AMD SEV

Li-Chung Chiang and Shih-Wei Li

Conference
ASPLOS 2025
Published
2025
Pages
1014-1027
Citations
8

AMD's encrypted-VM feature stops a malicious cloud host from reading a tenant's memory in plaintext, but deliberately still lets it read the ciphertext — and reverse-engineering (Academia Sinica and NTU) shows that the very machinery enforcing this isolation leaks — a host read to an address a VM owns silently flushes the VM's cached copies of nearby addresses, and two entities touching the same 64-byte block at once collide measurably, so timing those reads recovers what the VM is accessing even when the VM turns its own caching off.

The argument in one glance

  1. Problem

    The cloud host is the attacker, and the hardware is supposed to stop it

    A tenant renting a virtual machine must trust the host it runs on. AMD encrypts VM memory so a malicious host cannot read secrets in plaintext, and adds hardware checks so it cannot tamper with them.

  2. What people did

    Encrypt the memory, tag the caches, but still allow reads

    Each VM gets an identifier; memory is encrypted under a per-VM key, and cache lines are labelled with the owner so only a matching entity can use cached data. The design deliberately keeps one hole open: the host may read the ciphertext.

  3. Why it fell short

    The isolation machinery itself is measurable through timing

    The mechanism that keeps one entity from using another's cached data does so by flushing on a tag mismatch, and something coordinates concurrent accesses to the same physical location. Both are observable — a read that would be encrypted still moves the cache and still contends.

  4. This paper's idea

    Time the reads you are already allowed to make

    A host read to a VM-owned address flushes the VM's cached copies within a 2-kilobyte neighbourhood, and simultaneous reads to the same 64-byte block are slower. Measuring the latency of the reads the host is permitted to issue reveals what the VM is touching — even when the VM disables its own caching.

Why this problem is worth solving

The whole point of this technology is to let you not trust the machine you rent.

In a public cloud, your virtual machine runs on hardware controlled by the provider, and a compromised or malicious host can normally read anything in your memory. AMD’s answer encrypts each VM’s memory under a key the host never sees, held in a secure coprocessor, so the plaintext is invisible even to the entity that owns the physical machine. The latest version adds integrity protection — the host is forbidden from writing to VM memory, checked against a table that records which VM owns each physical page. But one capability is granted on purpose: the host is still allowed to read a VM’s pages, receiving the encrypted bytes rather than the plaintext. That read access exists for practical reasons of running the machine, and encryption is supposed to make it harmless. This paper is about the ways it is not harmless, because reading still has physical consequences that leak.

The isolation between VMs is enforced by a label on every cached line.

Encrypted memory alone does not stop one VM from using another’s cached data, because data in the cache is decrypted. So the hardware tags each cache line with the identifier of its owning VM, and permits an entity to use a cached line only when its own identifier matches the tag. What happens on a mismatch is the crux. Rather than simply deny the access, the hardware flushes — it removes the mismatched line from the cache. And whatever logic in the memory system coordinates two entities reaching for the same physical location at once has to serialise them, which takes time. Neither of these is a bug in the ordinary sense; they are how the isolation is implemented. The finding here is that implementation is a signal, readable by anyone who can time their own memory accesses, which the host always can.

What people did before, and where it broke

  • Encrypt VM memory so the host cannot read the plaintext. The foundation of the whole technology, and it does prevent direct reading of secrets. Where it broke. It does not conceal what the VM accesses, only what the bytes say, and the access pattern of a cryptographic routine can reveal the key even when every byte is encrypted.
  • Tag cache lines and flush on a mismatch to keep VMs apart. The mechanism that stops one entity using another’s decrypted cached data. Where it broke. The flush is the leak: a host read to a VM-owned address silently evicts the VM’s own cached copies of a whole neighbourhood of addresses, so the host learns, by timing, which neighbourhood the VM just touched.
  • Prime and probe the cache to infer a co-resident VM’s accesses. The established side channel against confidential VMs: fill a cache set with your data, wait, and see what got evicted. Where it broke. It needs to advance the VM one instruction at a time to line up the measurement, which is slow and conspicuous — and a VM can defeat it entirely by turning off caching for its sensitive pages, a defence AMD’s hardware supports.
  • Turn off caching for the sensitive pages. The recommended defence against cache attacks, and it works against them. Where it broke. The contention channel does not go through the cache at all: two entities hitting the same 64-byte block still collide in the memory system whether or not that block is cached, so disabling the cache leaves this signal fully intact.
  • Watch for page faults to track a VM’s pages. A coarse channel that observes which 4-kilobyte pages a VM touches. Where it broke. Four-kilobyte granularity is too coarse to separate the individual table entries a cryptographic routine indexes; the AES key recovery here needs 64-byte resolution, which page faults cannot give.
  • The gap. Every prior attack either was defeated by disabling the cache, or was too coarse to read cryptographic access patterns, or too slow and noisy to run stealthily. Nobody had looked at the enforcement mechanisms themselves as the source of signal.

How the machinery that isolates VMs becomes a channel

From encryption keeping the host out to timing letting it in

  1. new

  2. new

  3. new

  4. new

  5. new

The idea

The permission to read was assumed harmless because it returns ciphertext, but reading is a physical act with side effects. The design reasons that letting the host read encrypted memory gives it nothing, since it cannot decrypt what it reads. That is true about the value returned and false about everything else the read does. Fetching an address the host does not own forces the hardware to reconcile ownership, and the way it reconciles ownership is to flush the rightful owner’s cached copies. So a host read that yields meaningless ciphertext also silently reaches into the VM’s cache and disturbs it in a way the host can measure with a second read of its own. The attacker never touches a secret and never needs to; it uses a granted capability for its documented purpose and reads a side effect. Finding that a mechanism is safe with respect to the value it protects while leaking through a physical consequence nobody accounted for is the same shape as the on-chip memory work covered elsewhere on this site, which shows that hiding keys in SRAM that forgets on power loss still leaks them through the power domain that keeps the SRAM alive.

The finer discovery is a channel that ignores the cache entirely, which is what defeats the standard defence. The cache-flush effect is a cache channel, and the recommended countermeasure against cache channels is to make the sensitive pages uncacheable — AMD’s hardware supports exactly this, and it does stop the flush attack and the older prime-and-probe one. The contention channel steps around it. When two entities read the same 64-byte physical block simultaneously, something in the memory system must order the two accesses, and that serialisation costs measurable time regardless of whether the block is in any cache. So the defence of turning off caching, which is supposed to remove the attack surface, removes only the surface that runs through the cache; the block is still a shared physical resource and concurrent access to it still contends. The key recovery survives with caching disabled at 94 percent accuracy against 100 with it enabled. Discovering that a resource assumed private is silently shared, so that contention on it leaks the pattern of use, is the same realisation the memory-controller timing work covered elsewhere on this site builds on when a victim’s secret-dependent requests slow an attacker’s own requests through the shared controller.

Reading the pattern rather than the data is enough because the pattern is the secret in disguise. Neither channel ever reveals a byte of key material; both reveal only which memory locations the VM accessed. That suffices because a common AES implementation indexes precomputed tables by values derived from the key, so which table entry it touches is a direct function of key bytes. The attack watches, over many encryptions of chosen plaintexts, whether the VM’s last-round table lookup falls in a monitored 64-byte block, bins the resulting ciphertext bytes, and solves for the last-round subkey — from which the full key follows by running the key schedule backwards. The host can even force the vulnerable implementation to run: the VM asks whether the hardware supports accelerated AES, the host answers that query, and a malicious host simply lies, saying no, so the VM falls back to the table-based code. That leaking the access trace of a cryptographic routine is as good as leaking its key is the assumption the whole discipline of constant-time programming exists to deny, and it is the same lever the branch-history attack work covered elsewhere on this site pulls when it reconstructs a secret from the sequence of control-flow decisions rather than any secret value.

Following the host as it recovers one AES key byte

Recovering the last-round subkey with the contention channel

The host controls the hypervisor and can trigger the VM to encrypt chosen plaintexts. Nothing here decrypts VM memory; everything is a timing of the host's own reads.

Step 1 of 5

Force the vulnerable code path and locate the tables

When the VM queries whether the processor supports hardware AES, the host answers falsely that it does not, so the VM uses the table-based implementation whose lookups depend on the key. The host then locates the physical address of the tables by watching page-fault sequences.

Locating the address uses a control-channel technique from prior work, matching the sequence of nested page faults against a reference run and counting retired instructions between them. It is a prerequisite, not part of the new channel.

Why it works

  • Encryption hides the value, not the act of reading. The host receives ciphertext, which is useless as data → but the read still forces the hardware to reconcile ownership by flushing the owner’s cached copies, and still contends with a concurrent access → so the physical consequence of the read carries information the encrypted value does not.
  • Enforcing isolation by flushing turns a mismatch into a signal. The hardware could deny a mismatched access silently, but instead it evicts the mismatched lines → and it evicts not one line but the whole 2-kilobyte flush set around the address → so a single timed reread tells the host whether the VM touched anywhere in that set, with no single-stepping.
  • The contention channel does not use the cache, so disabling the cache does not stop it. The recommended defence marks sensitive pages uncacheable, which removes cache-based channels → but two entities reading the same physical block must still be serialised somewhere in the memory system, at measurable cost, cached or not → so the defence leaves this channel fully working, at 94 percent key-recovery accuracy.
  • Sixty-four-byte resolution is exactly what reading a cryptographic table needs. Page-fault channels see 4-kilobyte pages, too coarse to separate individual table entries → whereas contention resolves a single 64-byte block, the granularity of one cache line and of the table blocks AES indexes → which is why this recovers a full key where page-fault attacks cannot.
  • Concurrent measurement is what makes it stealthy. Prime-and-probe must halt the VM one instruction at a time to align its measurement, which is slow and conspicuous → whereas timing the host’s own reads while the VM runs freely needs no single-stepping and no synchronisation → making the observation continuous and far harder to notice.

What it costs (trade-offs and scope)

  • The attacker must already control the hypervisor. This is the assumed threat model for confidential VMs, and it is a strong assumption — the technology exists precisely because that host is untrusted. But it is not an attack a network adversary can mount; it requires having compromised or being the cloud host.
  • Every attack needs the physical address of the target first. Both channels require locating the system physical address of the data to monitor, done with a separate control-channel technique from prior work that matches page-fault sequences. That step is assumed to succeed and is not itself new.
  • The AES recovery depends on forcing a fallback implementation. Modern crypto libraries use hardware AES instructions, which have no secret-dependent memory access and are immune. The attack works only because a malicious host can lie about hardware support and push the VM onto the table-based code; a VM or library that refuses that fallback is not vulnerable to this key recovery.
  • The contention channel is statistical and needs profiling. Unlike the flush channel’s single-measurement reads, contention requires building a template from many encryptions and classifying against it, which is why the AES attack needs a hundred thousand profiling and two hundred thousand attack encryptions.
  • The separation is thin without caching. With the cache enabled the accessing and non-accessing latency distributions barely overlap; with it disabled the signal narrows to a difference of a fraction of a percent in the tail, which is enough for classification but is a small edge that noise could erode in a less controlled setting.
  • The measurements were taken with performance features disabled. Prefetchers, deep sleep states and frequency boosting were turned off in the main configuration to reduce noise, and a specific power-management setting had to be enabled for the attacks to work at all. Re-enabling those features still gave 100 and 90 percent accuracy, but the clean numbers come from a tuned machine.
  • It is one microarchitecture on specific servers. All results are on a particular AMD generation on two server models. Whether the exact flush-set geometry and contention behaviour hold on other generations is not established.
  • Some of the mechanism is inferred, and the vendor would not confirm it. The authors asked whether the flush effect relates to a documented coherence feature and were declined a comment, so the root-cause explanation is their reconstruction from measured behaviour rather than confirmed design.
  • The flush granularity is coarse and configurable. The flush channel resolves only 2 kilobytes, and its exact address layout depends on a memory-interleaving option set in firmware, so what an attacker sees depends on a host configuration choice.
  • The covert-channel comparison is same-core and synchronised. The favourable channel-capacity and noise numbers against prime-and-probe were measured with sender and receiver on sibling logical cores and a shared clock for bit timing, which is a constrained setup chosen for fair comparison.
  • The disclosure was handled and the fixes are partly on the tenant. AMD acknowledged the findings and issued a bulletin, but the recommended mitigations include using constant-time cryptography, which puts part of the defence back on the software running inside the VM rather than the hardware that promised to protect it.

The evaluation

Three ways to spy on a confidential VM from the host

PropertyPrime and probe the cacheWatch page faultsTime the reads you are allowed to make
Resolution of what it sees
Whether it survives the VM disabling its cacheNot relevant — it uses page faults
How it observesBy trapping page faults
AES key recoveryPossible at 64-byte granularityFails — cannot reach 64 bytes
Covert-channel capacityNot the comparison made
Attacks run from a KVM hypervisor against SEV-SNP-protected VMs on AMD EPYC Zen 3 servers, recovering AES-128 keys from OpenSSL's table implementation and carrying a Spectre-leaked secret over a covert channel, reproduced across SEV, SEV-ES and SEV-SNP.Underlined values explain themselves when clicked.

Check yourself

Check your understanding

  1. 1. Why does encrypting VM memory fail to prevent these attacks?

  2. 2. Why does the recommended defence of disabling the cache not stop the finer attack?

  3. 3. Why is reading only the VM's access pattern, never its data, enough to recover an AES key?

  4. 4. Which limitation most qualifies the result?

Sources

The paper is “Reload+Reload: Exploiting Cache and Memory Contention Side Channel on AMD SEV” by Li-Chung Chiang and Shih-Wei Li, published at ASPLOS 2025, pages 1014-1027, DOI 10.1145/3676641.3716017. The authors are at Academia Sinica and National Taiwan University.

This explainer is written from the full 14-page text. Everything above comes from the paper’s own sections: the background on AMD’s Secure Encrypted Virtualization and its versions, the address-space identifier tagging of cache lines, the nested page tables and reverse map table, and the per-page caching control that lets a VM mark pages uncacheable; the cache-flush experiment establishing that a mismatched-tag access flushes a 2-kilobyte flush set, the dependence of the flush-set layout on the memory-interleaving firmware setting, and the reproduction across SEV, SEV-ES, SEV-SNP, cross-VM and same-core settings; the memory-contention experiments with single and multiple blocks, both with caching enabled and disabled, and the formalisation of contention between entities with different identifiers; the attack formulation covering the threat model, the control-channel technique for locating the target’s physical address, and the Reload+Reload-flush-set and Reload+Reload-memory-block attacks with their measurement approaches; the AES case study with its forced fallback via CPUID emulation, the last-round key-recovery method, the profiling and attack phases with signal-to-noise-optimised latency-band selection and Gaussian templates, and the accuracy and timing results under both cache settings and two BIOS configurations; the Spectre covert-channel case study; the covert-channel capacity and noise-resilience comparisons against L1 and L2 prime-and-probe; the discussion of how the attacks compare to prime-and-probe, page-fault and other SEV attacks; and the mitigations including fixing the flush effect, restricting hypervisor reads, and adopting data-oblivious cryptography, together with the disclosure timeline and AMD’s security bulletin.

Related papers on Security, Privacy & Trusted Execution

See all 153 →