Chapter 1 granted your fetch unit a sweeping license: prefetch anything, cache it forever, never snoop stores. Zifencei is the other half of that bargain — the one instruction software uses to close the gap. FENCE.I fence.i Zifencei's one instruction: orders all prior explicit memory accesses (program order, same hart) before all subsequent instruction fetches. Strictly hart-local; cross-hart code publication = writer data-FENCE + each reader FENCE.I. funct12/rs1/rd reserved (ignored). defined in ch. I·5 — open in glossary guarantees that instruction fetches after it (in program order, on this hart) observe every data store before it that is already visible to this hart. RISC-V promises no instruction-fetch coherence instruction-fetch coherence Visibility of data stores to instruction fetches. RISC-V guarantees none by default — fetches may be served from arbitrarily stale prefetched bytes until the hart executes FENCE.I (or a future mechanism). defined in ch. I·5 — open in glossary whatsoever without it.
Two sharp edges:
- Strictly local. FENCE.I says nothing about other harts’ fetches.
Publishing code to a multiprocessor takes a data
FENCEon the writer (so the stores are visible) and then each consuming hart executing its own FENCE.I. - Fetch-before-data ordering is free. An instruction fetch is always ordered before the explicit accesses that instruction performs — you never fence between fetching a load and executing it.
The litmus test
The spec’s own self-modifying-code example (RV32IC): the producer patches
a 16-bit instruction, fences its stores, then raises a flag; the consumer
reads the flag, executes FENCE.I, then runs the patched instruction. The
outcome a0=1, a1=0 — flag seen, patch not seen — is forbidden:
Producer hart
la t0, patch_me
li t1, 0x4585
sh t1, (t0) # patch_me := c.li a1, 1
fence w, w # order the flag write
la t0, flag
li t1, 1
sw t1, (t0) # flag := 1Consumer hart
la t2, flag
lw a0, (t2)
fence.i # fetch barrier
patch_me:
c.li a1, 0 # patched to c.li a1, 1Initially flag = 0. Forbidden: a0=1, a1=0. (Illustrative — real code would loop on the flag before the fence.i.)
What FENCE.I costs, by microarchitecture
The instruction was designed to admit a whole spectrum:
- Simple core, incoherent I$: flush the fetch pipeline and invalidate the entire instruction cache. Correct, brutal, fine for a first core.
- I (or a unified inclusive private L2 invalidates I$ lines on local stores): I and D never diverge — FENCE.I reduces to a fetch-pipeline flush only.
- Uncached instruction RAM: pipeline flush only, same reason.
- Worst case — multi-level incoherent I and D hierarchies: complete flushes of both, every level, on every FENCE.I.
Hardware Designer Notes
For a Linux-bootable core the correctness bar is absolute (the kernel patches itself: alternatives, ftrace, eBPF JIT — all end in fence.i via the kernel’s own paths), but the performance bar is low — it executes rarely. Budget accordingly: whole-I$ invalidate + pipeline flush is a perfectly respectable v1. If you later add a coherent front side, the instruction quietly becomes a pipeline flush and your icache-flush state machine retires.
Minimal Linux-boot hart MUST
- Implement FENCE.I so post-fence fetches see all pre-fence local stores — whatever flushing that takes in YOUR hierarchy
- Ignore funct12/rs1/rd (reserved) — decode must not trap them
- Flush the fetch pipeline in every implementation — even fully coherent ones (prefetched stale bytes may be in flight)
MAY simplify / trap-and-emulate
- Invalidate the whole I$ rather than track anything — correctness over elegance
- Keep I/D coherent via D$ snooping or an inclusive L2 and make FENCE.I nearly free
- Ignore the performance question entirely at first: Linux userspace never issues FENCE.I; the kernel and firmware do, rarely
Check yourself — FENCE.I
1.Hart A writes new code, executes FENCE.I, and jumps to it. Hart B jumps to the same code without any action. What's guaranteed?
2.Why did the Linux ABI remove FENCE.I from user level?
3.Your core has incoherent split I/D caches with a private L2 in front of memory. What must FENCE.I do?