001Notes

Hardware Memory Path: From Virtual Address to DRAM, MMIO, and DMA

An interactive map of what can happen after a user instruction touches memory: translation, TLBs, caches, page walks, DRAM, MMIO, PCIe, IOMMU, and DMA.

Article details
Status
Building Publicly
Subcategory
Memory Path
Last reviewed
26 Aug 2026

This is a teaching map for the path from a user instruction to the machinery that may satisfy the memory access.

The point is to see which structure owns progress at each step.

Memory Sequence

Architecture Model

Demo order: finish the instruction-side fetch and walk, then launch the data-side load path.
Split first-level TLBs with a shared translation fallback tier.
Animated user program to kernel context to cache, DRAM, MMIO, ACPI, PCIe, NVMe, GPU, and DMA topologyA schematic showing a Firefox user thread, kernel-space task structures, per-core CPU and MMU state, per-core instruction and data translation caches, a shared last-level cache, virtual-address field breakdown, page-table walk, a platform address detector, memory controller, DRAM banks and cells, an MMIO BAR window, firmware-described ACPI GAS targets, a PCIe fabric with GPU and NVMe endpoints, and an IOMMU DMA-remap contrast path. Active steps highlight ownership, translation, cache lookup, route selection, uncached device-register access, and data return paths.User ThreadFirefox user instructioninstruction address + operand0x1234:mov rax, [0x4567][0x4567] holds= 0x1122334455667788Kernel Contexttask_structmm_structpt_regsPGD rootCPU Core 0Registers + TLB Front EndCache HierarchyMMURIP0x0000000000001234CR3task_struct_pgd baseREGS + Addr GenRAX=0x0000000000000000RSP=0x00007fffffffe000RFL=0x0000000000000202DATA_VA=0x4567ITLBset 0x10 pendingcode PFN pendingDTLBset 0x23 pendingVPN -> PFN pendingUnified TLBRIP + DATA_VA share one poolone translation lookup bankSTLBfallbackshared tierL1Iset 0x10 tag pending64B code linetag=-- state=pendingL2lookup pendingprivate line emptytag=-- owner=core0L1D8-way / set 0x23 / 64Bw0 tag=0x001ab20 missw1 tag=0x001aa80 missw2 tag=0x001ac10 missw3 tag=0x001a900 missw4 tag=0x001ab00 missw5 tag=0x001ab34 missw6 tag=0x001abff missw7 tag=0x001ad20 missqword pendingIndexset waitTagtag waitGateretire waitL3 / LLClookup pendingshared 64B lineslice=0 set=-- tag=--owner=shared state=idlepayload pendingPT-WalkI/D walk idleSplit VADATA_VA from addr-genorder: sequential9 + 9 + 9 + 9 + 120x0000000000004567PML4 = 0x000PDPT = 0x000PD = 0x000PT = 0x004off = 0x567Page Walktarget VA pendingPML4E (8B)PDPTE (8B)PDE (8B)PTE (8B)PA = PFN || off0x000000001ab34567PA Routerange pendingroute pendingACPI / GASXSDT/FADT idleGAS pendingtarget pendingMMIO / BARBAR idleuncached pathreg pendingIOMMU / DMARID/IOVA idleremap idledest pendingFixed HW Targetsselector idleGAS target pendingwidth / semantics pendingPM1 / PMTMRHPETEC / GPE / SCI fixed eventsPCIe Fabricroot port / BAR decode idleposted cfg/mmio path idleGPUBAR0 regs idlestatus / engine controlNVMeBAR0 regs idleSQ tail / CQ head / DMAMemory ControllerRAMbank + row + colrow buffer idlepayload pendingrow closedline pendingqword pendingsequence:fast DTLB+L1D pathcore0 dtlb:pendingwalker:idlecache:pendingroute:pendingdram decode:idletimeline:sequential / I then D
control or request issueaddress translation pathdata return pathactive component for this stepinstalled context or dormant structure
Step 1 / 5

How This Flow Works

Core 0 RIP starts an instruction-side ITLB miss

Core 0 begins at `RIP=0x0000000000001234`: the instruction fetch misses in `ITLB`, walks from `CR3`, pulls the RAM-backed code line into `L1I`, and only then does the decoded `mov rax, [0x0000000000004567]` hand the operand address into the register-side load path.

This frame is still on the instruction side. Core 0 is using `RIP` to fetch and translate the code page before the later data-side load can even exist, so the highlighted walk and fills belong to the code bytes, not yet to the operand payload.

The active walker, `L1I`, shared cache, and DRAM nodes show the instruction line moving upward into the core. Only after decode does the address-generation path hand `0x0000000000004567` into the register block for the later `DTLB` and `L1D` sequence.

Example`RIP = 0x0000000000001234`; `ITLB = miss`

CaveatInstruction bytes and payload bytes are separate flows even when one assembly line triggers both.

Architecture Effect

Parallel workVIPT can start the VA-indexed set probe while the DTLB resolves the PFN.

Serial gateThe PA tag still gates whether the early set probe can retire the load.

This selected model changes the order of cache-index, tag-check, and translation work.

Machine State Snapshot

Boundary Notes

    Why This Step Matters

    Primary references

    1. Linux kernel DMA mapping guide
    2. Intel 64 and IA-32 Optimization Reference Manual
    Diagram