Skip to content

Add types for parsing DMAR - #370

Merged
martin-hughes merged 1 commit into
rust-osdev:mainfrom
gierens:dmar
Nov 2, 2026
Merged

martin-hughes merged 1 commit into
rust-osdev:mainfrom
gierens:dmar

Conversation

@gierens

@gierens gierens commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

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

@martin-hughes martin-hughes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gierens: Thanks for this!

No comments from me. I want to say thanks for the detailed description, and I particularly liked the demo repo. Kudos.

I'm going to add a few bits of documentation later, but I'm content to do that myself. Thanks again!

@martin-hughes
martin-hughes merged commit 5e059dc into rust-osdev:main Nov 2, 2026
6 checks passed
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

2 participants