Course contentsShow
← Rust
Lesson 1497 of 1,91012. Unsafe Rust and Low-Level AccessFree lesson

DMA Buffer Management

You will manage memory regions for direct memory access by hardware controllers.

In this lesson, you will learn how to safely orchestrate memory regions so that hardware controllers can perform high-speed data transfers without burdening the CPU.

The DMA Paradox

Direct Memory Access (DMA) allows peripherals like network cards or disk controllers to read from and write to system RAM independently of the CPU. The challenge in Rust is that the compiler assumes it has absolute control over memory layout and content. When you hand a buffer pointer to a hardware controller, you are effectively creating a "shared mutable state" with an entity the compiler cannot inspect.

Aligning and Pinning

Hardware controllers often require DMA buffers to be aligned to specific memory boundaries (e.g., 4KB pages) to ensure atomic burst transfers. Furthermore, the buffer must remain at a fixed physical memory location; if the Rust allocator were to move the memory during a transfer, the hardware would write to stale or invalid addresses, leading to catastrophic system instability.

To manage this, we typically define a layout-aware struct and ensure it remains fixed:

#[repr(C, align(4096))]
struct DmaBuffer {
    data: [u8; 4096],
}

// In a real-world scenario, you would allocate this on the heap
// and use a crate like `pinned_drop` or simply leak the Box 
// to ensure it never moves for the lifetime of the DMA operation.
let buffer = Box::leak(Box::new(DmaBuffer { data: [0; 4096] }));
let phys_addr = translate_to_physical(buffer as *const _ as usize);

// Provide this physical address to your hardware via MMIO
dma_controller.set_source_address(phys_addr);

Ensuring Coherency

Beyond pinning, you must handle "cache coherency." Modern CPUs cache memory access. If your CPU writes data to the buffer, that data might live only in the L1/L2 cache, while the DMA controller reads stale data directly from the physical RAM. Before triggering a DMA transfer, you must perform a "cache flush" or "clean" operation to force the CPU cache contents into physical memory. Conversely, after a DMA read, you must "invalidate" the cache to force the CPU to reload the updated data from RAM. Failing to do this causes silent data corruption.

Key Takeaway: DMA buffer management requires strict memory alignment, pinning to prevent relocation, and explicit cache synchronization to ensure the CPU and hardware see the same view of memory.