Skip to content

Add types for parsing DMAR - #370

Open
gierens wants to merge 1 commit into
rust-osdev:mainfrom
gierens:dmar
Open

gierens wants to merge 1 commit into
rust-osdev:mainfrom
gierens:dmar

Conversation

@gierens

@gierens gierens commented Oct 15, 2026 •

Copy link
Copy Markdown

This adds sdt::dmar module containing the types for parsing ACPI DMAR
tables. It follows the definitions in the "Intel(R) Virtualization
Technology for Directed I/O Architecture Specification"
(https://software.intel.com/content/dam/develop/public/us/en/documents/vt-directed-io-spec.pdf)
section 8.1.

At the root is the Dmar with the function entries, returning an iterator over
the DmarEntry enum. This can contain the structs DrhdEntry, RmrrEntry,
AtsrEntry, RhsaEntry, AnddEntry, SatcEntry, or SidpEntry. Some of these
contain DeviceScopes also returned as iterator.

For testing I created a small repo with a minimal kernel and runner program
that you can find here: https://github.com/gierens/acpi-dmar-demo
It just sets up the logger, page table, allocator, and then parses the ACPI
tables, of which it then prints the DMAR, entries, and device scopes.
cargo run launches the kernel in QEMU with
-machine q35,accel=kvm,kernel_irqchip=split -device intel-iommu,intremap=on,caching-mode=on
(see https://github.com/gierens/acpi-dmar-demo/blob/main/src/main.rs#L31-L34)
which yields a single DRHD entry in DMAR.

Using the following code:

let dmar = platform.tables.find_table::<Dmar>().unwrap();
let dmar = dmar.get();
log::info!("DMAR: {dmar:?}");
for entry in dmar.entries() {
    log::info!("DMAR entry: {entry:?}");
    if let DmarEntry::Drhd(drhd) = entry {
        for scope in drhd.device_scopes() {
            log::info!("Device scope: {scope:?}, path: {:?}", scope.path());
        }
    }
}

in kernel/src/main.rs (see https://github.com/gierens/acpi-dmar-demo/blob/main/kernel/src/main.rs#L42-L52) it then prints:

INFO : DMAR: Dmar { header: SdtHeader { signature: "DMAR", length: 120, revision: 1, checksum: 4, oem_id: [66, 79, 67, 72, 83, 32], oem_table_id: [66, 88, 80, 67, 32, 32, 32, 32], oem_revision: 1, creator_id: [66, 88, 80, 67], creator_revision: 1 }, host_address_width: 47, flags: 1, _reserved: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], _pinned: PhantomPinned }
INFO : DMAR entry: Drhd(DrhdEntry { header: DmarEntryHeader { entry_type: 0, length: 72 }, flags: 0, size: 0, segment_number: 0, register_base_address: 4275634176 })
INFO : Device scope: DeviceScope { scope_type: 3, length: 8, flags: 0, _reserved: 0, enumeration_id: 0, start_bus_number: 255 }, path: Ok([DeviceScopePathComponent { device: 0, function: 0 }])
INFO : Device scope: DeviceScope { scope_type: 1, length: 8, flags: 0, _reserved: 0, enumeration_id: 0, start_bus_number: 0 }, path: Ok([DeviceScopePathComponent { device: 0, function: 0 }])
INFO : Device scope: DeviceScope { scope_type: 1, length: 8, flags: 0, _reserved: 0, enumeration_id: 0, start_bus_number: 0 }, path: Ok([DeviceScopePathComponent { device: 1, function: 0 }])
INFO : Device scope: DeviceScope { scope_type: 1, length: 8, flags: 0, _reserved: 0, enumeration_id: 0, start_bus_number: 0 }, path: Ok([DeviceScopePathComponent { device: 2, function: 0 }])
INFO : Device scope: DeviceScope { scope_type: 1, length: 8, flags: 0, _reserved: 0, enumeration_id: 0, start_bus_number: 0 }, path: Ok([DeviceScopePathComponent { device: 31, function: 0 }])
INFO : Device scope: DeviceScope { scope_type: 1, length: 8, flags: 0, _reserved: 0, enumeration_id: 0, start_bus_number: 0 }, path: Ok([DeviceScopePathComponent { device: 31, function: 2 }])
INFO : Device scope: DeviceScope { scope_type: 1, length: 8, flags: 0, _reserved: 0, enumeration_id: 0, start_bus_number: 0 }, path: Ok([DeviceScopePathComponent { device: 31, function: 3 }])

This fixes #105 , probably better to open another issue for IVRS

@gierens
gierens force-pushed the dmar branch 2 times, most recently from 1397d52 to 2dd0557 Compare October 16, 2026 12:29
@gierens
gierens marked this pull request as draft October 16, 2026 12:31
This adds sdt::dmar module containing the types for parsing ACPI DMAR
tables. It follows the definitions in the "Intel(R) Virtualization
Technology for Directed I/O Architecture Specification"
(https://software.intel.com/content/dam/develop/public/us/en/documents/vt-directed-io-spec.pdf)
section 8.1.

At the root is the Dmar with the function entries, returning an iterator
over the DmarEntry enum. This can contain the structs DrhdEntry,
RmrrEntry, AtsrEntry, RhsaEntry, AnddEntry, SatcEntry, and SidpEntry.
Some of these contain DeviceScopes also returned as iterator.

Signed-off-by: Sandro-Alessio Gierens <sandro@gierens.de>
@gierens
gierens marked this pull request as ready for review October 16, 2026 12:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parse the DMAR

1 participant