iommu: AMD-Vi backend behind the vendor-neutral core
The second hardware backend. The IOMMU core, DMA-region capabilities, and per-device enforcement are unchanged; this adds AMD-Vi (IVRS) as an alternative to Intel VT-d (DMAR) under the same Backend vtable. - parseIvrs records the IOMMU control-register base from the first IVHD; the platform layer gains iommu_is_amd, and the core picks the backend by vendor at init. VT-d and AMD-Vi are mutually exclusive on real hardware. - iommu-amd.zig: a 2 MiB device table (every DTE zeroed = deny-all until a device is claimed), AMD native-format page tables (4 KiB leaves), a command buffer (INVALIDATE_DEVTAB_ENTRY / INVALIDATE_IOMMU_PAGES / COMPLETION_WAIT) and an event log for faults. The DTE forwards interrupts unmapped, so MSI passthrough works exactly as on VT-d. - The boot log and the iommu self-test are now vendor-aware. **UNTESTED on real AMD hardware** — danos is developed on Intel, so this is validated only against QEMU's amd-iommu, and every log line and doc says so. QEMU quirk handled: its amd-iommu does not observe the COMPLETION_WAIT store form, but consumes the command ring synchronously on the tail-register write, so invalidations are already applied by the time we poll — the backend warns once and proceeds. Cases: amd-iommu (detection + scratch-domain walker) and amd-iommu-usb-storage (full storage stack through AMD device-table translation with per-grant capabilities), both green. 106/106. This completes the IOVA/IOMMU-enforcement track: per-device DMA domains on both vendors, with buffers reachable only through delegated capabilities.
This commit is contained in:
+29
-13
@@ -32,6 +32,7 @@ const platform = @import("platform");
|
||||
const devices_broker = @import("devices-broker.zig");
|
||||
const log = @import("log.zig");
|
||||
const intel = @import("iommu-intel.zig");
|
||||
const amd = @import("iommu-amd.zig");
|
||||
|
||||
const page_size: u64 = abi.page_size;
|
||||
const page_mask: u64 = page_size - 1;
|
||||
@@ -104,22 +105,32 @@ pub fn init() void {
|
||||
kind = .none;
|
||||
return;
|
||||
}
|
||||
// Only Intel VT-d for now; AMD-Vi (iommu-amd.zig) selects here when its detection
|
||||
// (IVRS) lands. A present-but-unsupported unit stays fail-open with a logged reason.
|
||||
if (intel.detect(info)) |be| {
|
||||
backend = be;
|
||||
kind = .intel_vtd;
|
||||
// Pick the backend by vendor. A present-but-unusable unit stays fail-open with a
|
||||
// logged reason rather than half-enabling.
|
||||
if (info.iommu_is_amd) {
|
||||
if (amd.detect(info)) |be| {
|
||||
backend = be;
|
||||
kind = .amd_vi;
|
||||
} else {
|
||||
kind = .none;
|
||||
log.write("/system/kernel: WARNING AMD-Vi present but unusable — staying fail-open\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
kind = .none;
|
||||
log.write("/system/kernel: WARNING IOMMU present but unusable — staying fail-open\n");
|
||||
return;
|
||||
if (intel.detect(info)) |be| {
|
||||
backend = be;
|
||||
kind = .intel_vtd;
|
||||
} else {
|
||||
kind = .none;
|
||||
log.write("/system/kernel: WARNING IOMMU present but unusable — staying fail-open\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The root table starts empty: every device's context entry is not-present, so any
|
||||
// DMA faults until the device's driver claims it (confineDevice gives it a private
|
||||
// domain). PCI functions are enumerated post-boot by the ring-3 pci-bus driver, so
|
||||
// there is nothing to attach at init anyway.
|
||||
intel.enable();
|
||||
// The translation structures start empty: every device is denied until its driver
|
||||
// claims it (confineDevice gives it a private domain). PCI functions are enumerated
|
||||
// post-boot by the ring-3 pci-bus driver, so there is nothing to attach at init.
|
||||
if (kind == .amd_vi) amd.enable() else intel.enable();
|
||||
logEnabled(info);
|
||||
}
|
||||
|
||||
@@ -421,6 +432,11 @@ fn hardwareId(domain: u16) u16 {
|
||||
}
|
||||
|
||||
fn logEnabled(info: platform.PlatformInformation) void {
|
||||
if (kind == .amd_vi) {
|
||||
log.write("/system/kernel: iommu online (AMD-Vi) — UNTESTED on real AMD hardware (QEMU-verified only)\n");
|
||||
log.print(" levels : {d} (48-bit)\n", .{backend.levels});
|
||||
return;
|
||||
}
|
||||
log.write("/system/kernel: iommu online (Intel VT-d)\n");
|
||||
log.print(" version : 0x{x}\n", .{info.iommu_version});
|
||||
log.print(" agaw : {d} levels\n", .{backend.levels});
|
||||
|
||||
Reference in New Issue
Block a user