1/34
Looks like no tags are added yet.
What is Programmed I/O (PIO) and why does it fail at high data rates?
The CPU manually executes loops of load/store instructions to transfer bytes between peripherals and memory. It wastes CPU cycles, stalls instruction pipelines, and is limited by CPU execution speed and bus latency.
What is Direct Memory Access (DMA)?
A hardware feature allowing peripherals to transfer data directly to and from system RAM across the bus without continuous CPU involvement.
What are the four phases of a DMA transfer lifecycle?
What is the difference between a centralized DMA controller and a bus-mastering DMA device?
Centralized DMA uses a shared host controller handling requests (DREQ/DACK) for simple peripherals. Bus-mastering DMA integrates the DMA engine directly into the peripheral (e.g. PCIe endpoint), letting it issue bus read/write transactions autonomously.
What is the difference between register-based DMA and descriptor-based (scatter-gather) DMA?
Register-based DMA uses hardware registers for a single continuous transfer, requiring CPU interrupt intervention between blocks. Descriptor-based DMA uses linked lists or rings of descriptor structs in memory traversed automatically by the DMA engine.
In Linux, what are the three distinct address spaces relevant to DMA?
What is the primary difference between Consistent (Coherent) DMA and Dynamic (Streaming) DMA?
Consistent DMA (dma_alloc_coherent) provides non-cacheable or hardware-coherent memory intended for long-lived control structures like ring descriptors. Dynamic DMA (dma_map_single/sg) maps existing cacheable buffers on-demand for high-throughput data payloads and unmaps them when done.
Why do we use Dynamic DMA instead of just allocating non-cacheable memory for all buffers?
Disabling the cache for bulk data buffers severely degrades CPU performance during subsequent processing like digital signal processing, parsing, or math operations. Dynamic DMA allows the CPU to access data at full cache speeds while ensuring coherency during transfers.
In Dynamic DMA, what cache operation is required for DMA_TO_DEVICE transfers and why?
Cache clean or flush. It pushes dirty cache lines from CPU L1/L2 caches out to physical DRAM so the peripheral reads current data rather than stale memory.
In Dynamic DMA, what cache operation is required for DMA_FROM_DEVICE transfers and why?
Cache invalidate. It clears existing CPU cache lines for that buffer so subsequent CPU reads pull fresh data newly written to DRAM by the peripheral.
Why should you never pass a buffer allocated with vmalloc() to dma_map_single()?
vmalloc() buffers are virtually contiguous but composed of physically fragmented, non-contiguous pages. dma_map_single() assumes physical memory contiguity.
When should you use dma_sync_single_for_cpu() and dma_sync_single_for_device() instead of dma_unmap_single()?
When repeatedly reusing a pre-allocated buffer across multiple transfers without unmapping. It avoids the performance overhead of repeatedly reconfiguring page tables and IOMMU TLB entries.
What is the cache-line sharing or false sharing bug in dynamic DMA?
If an unaligned DMA buffer shares a CPU cache line (e.g. 64 bytes) with unrelated kernel variables, invalidating the cache line for a receive operation silently discards CPU writes made to the neighboring variables.
What is an IOMMU and what are its two main advantages for DMA?
An I/O Memory Management Unit translates peripheral bus addresses (IOVA) to physical DRAM addresses. It allows physically scattered pages to appear contiguous to hardware and isolates peripheral memory access.
What is SWIOTLB (Bounce Buffering)?
A kernel fallback where data is copied through a pre-allocated low-memory buffer when a device cannot physically address the target memory region (e.g. a 32-bit DMA mask on a 64-bit physical address space).
What is kmalloc() in the Linux kernel and what memory guarantee does it provide?
The general-purpose kernel memory allocator built on the SLUB/SLAB allocator. It guarantees the returned memory is both virtually contiguous and physically contiguous.
Why can kmalloc() fail even when free memory is abundant?
External physical memory fragmentation. kmalloc() requires contiguous physical pages, which may not be available in a single contiguous block despite high overall free memory.
What is the difference between GFP_KERNEL and GFP_ATOMIC in kmalloc()?
GFP_KERNEL allows the kernel to sleep, swap, or block to satisfy the allocation, making it safe only in process context. GFP_ATOMIC never sleeps and dips into emergency memory reserves, making it mandatory for interrupt handlers and spinlock critical sections.
Why should a circular ring buffer capacity always be a power of two (2^N)?
It allows the array index wrap to be calculated using a fast bitwise AND operation (index & mask, where mask = capacity
How does a power-of-two circular buffer distinguish between full and empty using free-running indices?
Empty is when (in == out). Full is when (in
Why does a Single-Producer Single-Consumer (SPSC) circular buffer not require mutexes or spinlocks?
The producer modifies only the write pointer (in) and inspects the read pointer (out). The consumer modifies only the read pointer (out) and inspects the write pointer (in). Neither writes to the other pointer, eliminating write-write race conditions.
What is the purpose of memory barriers (acquire/release) in a lockless SPSC circular buffer?
They prevent the CPU or optimizing compiler from reordering operations. A write barrier ensures payload data is fully written to RAM before the write index advances. A read barrier ensures data is read before the read index advances.
What is a spinlock and how does it work?
A synchronization primitive where a thread actively executes a busy-wait loop (spinning on atomic instructions like test-and-set or compare-and-swap) until the lock is released, rather than sleeping.
What is the main advantage and main disadvantage of a spinlock compared to a mutex?
Advantage: Zero context-switch overhead (no saving registers, flushing pipelines, or invoking the scheduler). Disadvantage: Consumes 100% of a CPU core while waiting, burning power and wasting compute time.
Can you use a spinlock to wait for a DMA transfer or hardware peripheral to finish?
No. Spinlocks are exclusively for software synchronization between two CPU cores. Hardware peripherals do not execute lock instructions; waiting on hardware requires polling status registers/descriptors or waiting on an interrupt.
Why can a mutex never be used inside an Interrupt Service Routine (ISR)?
Mutexes can sleep when contended. Interrupt context has no backing process thread or task_struct to suspend and reschedule; sleeping inside an ISR causes an immediate kernel crash or BUG.
What happens if code in process context acquires a regular spin_lock() and the local CPU receives an interrupt that needs the same lock?
Deadlock occurs. The ISR runs on that same CPU and spins forever waiting for the lock, while the process holding the lock is suspended and can never run to release it.
How does spin_lock_irqsave() solve the interrupt deadlock hazard?
It saves the local CPU interrupt state and completely disables hardware interrupts on that local core before acquiring the spinlock, preventing an ISR from interrupting the critical section.
Why is using spinlocks in user space generally discouraged?
User-space threads can be preempted by the OS scheduler while holding the lock. Other threads will then spin fruitlessly for their entire time-slice waiting for an unscheduled thread, causing severe priority inversion and CPU starvation.
What is an adaptive mutex in modern Linux/glibc?
A hybrid mutex that initially acts like a spinlock, spinning for a few hundred cycles in user space in hopes the lock clears quickly. If still held, it falls back to a kernel futex sleep.
What is the difference between the Top Half and Bottom Half of an interrupt handler?
The Top Half (Hard IRQ) runs with high priority in interrupt context, acknowledges hardware, saves volatile data, and schedules the Bottom Half. The Bottom Half (tasklet, workqueue, or threaded IRQ) runs deferred in a context where complex processing, memory allocations, and sleeping locks are allowed.
What does the volatile keyword tell the C compiler?
It prevents the compiler from optimizing away reads or writes, or caching the variable value inside a CPU register. It forces every read and write to access physical memory directly.
What is a torn read in embedded systems?
When a CPU reads a multi-byte variable that exceeds the native bus width in multiple instructions, and an interrupt alters the variable halfway through, leaving the CPU with a corrupt mix of old and new data.
What is an interrupt mask register and what does disable_interrupts() do?
An interrupt mask is a hardware filter in the CPU or interrupt controller that blocks IRQ signals from interrupting the core. disable_interrupts() sets this mask (e.g. CPSID i on ARM or CLI on x86) to create a short atomic critical section.
Why should embedded code use save/restore patterns instead of bare disable/enable interrupt calls?
Bare enable_interrupts() prematurely re-enables interrupts if called inside nested functions that were already in a disabled critical section. A save/restore pattern restores interrupts strictly to their previous state.