|
<< Click to Display Table of Contents >> Navigation: ASA-EMulatR Reference Guide > Introduction > Architecture Overview > Chapter 16 – Device Model & DMA > 16.9 DMA Implementation |
DMA (Direct Memory Access) allows devices to read from and write to GuestMemory directly, without CPU intervention for each byte transferred. In EMulatR, DMA operations are performed by device I/O threads and route through GuestMemory using the AccessKind::DMARead and AccessKind::DMAWrite designators, which enables GuestMemory to apply DMA-specific access policies.
The typical DMA write path (device → GuestMemory): the device I/O thread fills a local data buffer from host-side I/O (e.g., disk read), calls DMACoherencyManager to prepare the transfer (RX path: DeviceToRAM), writes data into GuestMemory via writeBlock() with AccessKind::DMAWrite, and signals coherency completion. The typical DMA read path (GuestMemory → device) follows the TX path: DMACoherencyManager flushes CPU caches for the region (RAMToDevice), reads data from GuestMemory, and delivers it to the host-side I/O path.
DMACoherencyManager (mmio_DMACoherencyManager.h, ~579 lines) ensures that DMA transfers observe correct memory ordering with respect to CPU operations. It manages three coherency concerns:
TX path (RAMToDevice): Before a device reads from GuestMemory (e.g., to fetch DMA descriptors or transmit buffer data), DMACoherencyManager ensures that all prior CPU writes to the affected memory region are visible. In a real Alpha system, this would involve cache flush operations; in EMulatR, it involves draining the affected CPU's write buffer entries that overlap the DMA region.
RX path (DeviceToRAM): After a device writes to GuestMemory (e.g., depositing received network packets or disk read data), DMACoherencyManager ensures that subsequent CPU reads from the affected region see the device-written data, not stale cached values. This involves invalidating any overlapping write buffer entries and, in SMP configurations, coordinating across multiple CPUs.
LL/SC reservation invalidation: DMA writes to memory regions that overlap with an active LL/SC reservation must break the reservation. DMACoherencyManager calls ReservationManager::breakReservationsOnCacheLine() for each 64-byte cache line touched by a DMA write. This prevents a STx_C from succeeding after a device has modified the memory it was protecting.
DMA addresses are physical addresses within the GuestMemory space. DMABufferDescriptor tracks each allocated DMA buffer with its physical address, size, owning device UID, and address mask. The address mask distinguishes 32-bit DMA devices (which can only address the lower 4 GB of physical memory) from 64-bit DMA devices (which can address the full physical address space). The dmaMask field in DeviceTemplate specifies the device's DMA addressing capability.
Invariant: All DMA transfers route through GuestMemory with explicit AccessKind designation. No device may access SafeMemory directly. DMA completion does not imply memory ordering unless enforced by a subsequent interrupt and barrier.
See Also: mmioLib/mmio_DMACoherencyManager.h (~579 lines) – Coherency manager; 15.8 LL/SC Reservation Tracking; 15.12 Diagnostics and DMA Coherency.