← black metal kernel — series index
// black metal kernel — episode 05 of 08
memory layout control:
repr(C) as a weapon
// kernel programming in rust — zero-cost abstractions — no gc — no mercy
repr(C)
virtio
DMA
packed bounds
// 05 — structural alignment vs direct memory access
rust actively reorders fields in standard structs to eliminate padding and minimize memory footprints. this optimization is flawless for application logic but lethal when interacting with real hardware. hardware interfaces, such as DMA controllers or virtio virtual device rings, demand predictably exact bit layouts.
to enforce rigid memory structures, we wield `repr(C)`. it forces rust to align and order structs exactly as a C compiler would, matching the hardware specification byte for byte. the following code illustrates a virtq descriptor ring entry, essential for paravirtualized network and block io passing outside the cpu context.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct BlackVirtqDesc {
pub black_addr: u64,
pub black_len: u32,
pub black_flags: u16,
pub black_next: u16,
}
// expanded — DMA arrays, virtqueues, and padding logic
hardware protocols like virtio require memory to be shared continuously between the host emulator and the guest kernel. our BlackVirtqDesc struct mimics the specification's 16-byte fixed-size expectation perfectly: one 64-bit address (8 bytes), one 32-bit length (4 bytes), and two 16-bit fields (2 + 2 = 4 bytes). total size: 16 bytes. had we relied on rust's default representation, the compiler could reorder the 16-bit fields, catastrophically shifting the indices that the hypervisor controller parses.
when constructing arrays of these structures for Direct Memory Access (DMA), any hidden padding would misalign the n-th element for the DMA engine, corrupting data streams. `repr(C)` disables field reordering and dictates that padding only occurs according to strict C structural boundaries. because our struct natively sums to exactly 16 bytes with its largest generic primitive being 8 bytes (u64 address), there is naturally zero internal padding and it packs compactly.
// 05 / 08 — black_ptr owns its truth — BLACK0X80