Guest User

Untitled

a guest
Jul 9th, 2026
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.86 KB | None | 0 0
  1. ● Good question to press on — this is exactly the kind of sequence where people cargo-cult a set/way flush. The answer is no, and it's by construction: a D-cache clean before the
  2. MMU-off window is only needed if something will read or write memory around the cache while dirty lines cover it. The trampoline is deliberately structured so that never happens.
  3. Let me lay out the argument precisely.
  4.  
  5. Dirty cache lines are not "stale" by themselves — they hold the newest data. They only become a hazard when an access bypasses them:
  6.  
  7. 1. a non-cacheable read of a location whose newest value sits in a dirty line (reads old memory), or
  8. 2. a non-cacheable write that lands in memory, later overwritten by the eviction of an older dirty line.
  9.  
  10. Now check the trampoline against that (loader/arch/aarch64/handover.asm):
  11.  
  12. - Before the window: every value needed later is pulled into registers (handover.asm:53-64) while the MMU and caches are still on — these are ordinary WB hits. Then dsb sy; isb.
  13. - Inside the window (M=0, data accesses would be Device-nGnRnE): the instruction stream is exclusively mrs/msr/orr/bic/cbz/b/tlbi/dsb/isb — there is not a single load or store
  14. between the msr sctlr that clears M and the one that sets it again. No data access ⇒ neither hazard case can occur. This is exactly why the struct fields are hoisted into x1–x12 up
  15. front, and the comment at handover.asm:47-52 states that invariant.
  16. - Instruction fetches during the window aren't a problem either: with M=0, I=1 they're Write-Through cacheable, and the trampoline code hasn't been modified since it started
  17. executing, so the I-side is coherent with memory regardless.
  18. - After the window: the MMU comes back with RAM mapped Normal WB — the same attributes everything was written with. The dirty lines are simply valid cached data again; subsequent
  19. accesses hit them and see correct values. Same for the table walker: TCR.IRGN/ORGN = WB matches how the loader wrote the page tables, so walks correctly hit any still-dirty table
  20. lines.
  21. - Evictions during the window are harmless in themselves — an eviction writes back correct data; there's no non-cacheable write for it to clobber.
  22.  
  23. So the "flush before disabling" recipe applies to a different design: it's mandatory when you're going to stay non-cacheable — i.e., hand off with caches disabled or RAM mapped NC,
  24. where the kernel's non-cacheable reads would bypass dirty lines forever. That was precisely the old Hyper handoff (SCTLR = M|SA, everything Normal-NC, NC walker), which did not
  25. clean the cache and was therefore genuinely broken on real hardware — dirty lines from the UEFI phase (page tables, kernel image, boot context) would have been invisible to the
  26. kernel's NC reads and could evict on top of its writes at any time. QEMU/TCG masked it. Switching to a matching-WB handoff is what made the no-flush trampoline legitimate; the
  27. alternative fix would have been keeping the NC handoff and adding a full clean+invalidate by VA over every loader-written structure — strictly worse (set/way cleans are also
  28. architecturally fragile outside of single-core, caches-off contexts).
  29.  
  30. The one memory-coherency obligation that does survive in this design is the I-side vs D-side one for freshly written code — the kernel image was produced by data writes, and
  31. I-fetch doesn't snoop dirty D-lines on real cores. That's handled separately in handover_prepare_for() (dc cvau → dsb ish → ic ivau → dsb ish; isb over the image,
  32. loader/arch/aarch64/handover_impl.c:167), while the mappings are still up.
  33.  
  34. So: no change needed — but it's a sharp check, and the two invariants it rests on (no loads/stores in the MMU-off window, matching WB attributes on both sides) are both documented
  35. in the trampoline comments precisely because breaking either one silently reintroduces the flush requirement.
Advertisement
Add Comment
Please, Sign In to add comment