Skip to content

Add iommu support to microkit#467

Draft
Cheng-Li1 wants to merge 13 commits intoseL4:mainfrom
au-ts:cheng/iommu-support
Draft

Add iommu support to microkit#467
Cheng-Li1 wants to merge 13 commits intoseL4:mainfrom
au-ts:cheng/iommu-support

Conversation

@Cheng-Li1
Copy link
Copy Markdown

This pull request adds iommu support for Microkit and needs Rust-Sel4 with the iommu support to work.

Supported features:
Map the memory region to a device-visible memory address.

Tests done:
Blk example with iommu feature enabled on x86 qemu and hardware(vb-105).

Cheng-Li1 added 12 commits April 9, 2026 13:25
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
…ure for generating spec in microkit tool.

Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
…e check unused mr and mr page size optimization logic for iomaps support.

Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Comment thread Cargo.toml Outdated
[workspace.dependencies.sel4-capdl-initializer-types]
git = "https://github.com/seL4/rust-sel4"
rev = "7a2321f2d84310ba7a09fe7f5988e6dcecde3566"
path = "/home/cheng/system/rust-sel4/crates/sel4-capdl-initializer/types"
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.

Can you update it to the commit hash that added IOMMU support to the capDL initialiser in rust-sel4 so that the CI works? On that note, you will need to rebase your branch as well, the CI doesn't run when there are conflicts.

@@ -0,0 +1,282 @@
use std::ops::Range;
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.

Missing copyright here

}),
});

const PD_TO_DOMAIN_ID_OFFSET: u16 = 1;
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.

You should explain why this is needed (with kernel source) for future reference.

Comment thread tool/microkit/src/sdf.rs
"Error: iomap for '{}' has address 0x{:x} which exceeds the upper limits of {} in {} '{}' @ {}",
io_map.name,
map_end,
crate::capdl::iomem::VTD_MAX_ADDR,
Copy link
Copy Markdown
Contributor

@dreamliner787-9 dreamliner787-9 Apr 16, 2026

Choose a reason for hiding this comment

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

I feel like VTD_MAX_ADDR should be printed as hex.

}

#[test]
fn test_iommu_valid_on_x86() {
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.

This should be called test_iommu_out_of_bound or similar.

On this note, I would like to see more tests, e.g. overlapping mappings, invalid page size, trying to use IOMMU on non-x86 targets etc.

phys_base: None,
spec_metadata: None,
log_level: LogLevel::Info,
log_level: LogLevel::Debug,
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.

This shouldn't be changed.

sel4::Config,
};

// VTD Page table level is defaulted to the three-level structure even if the hardware supports four level.
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.

I forgot the content of the conversation we had offline about this. But what happens when the target machine only support 3 levels VT-d page table, but we made a 4 levels one (according to VTD_PAGE_TABLE_LEVEL)?

@dreamliner787-9
Copy link
Copy Markdown
Contributor

Your commit history needs to be cleaned up and squashed. Some of the commits checked in code that should not be in Microkit, then other commits removed them.

@dreamliner787-9
Copy link
Copy Markdown
Contributor

A nice to have would be a minimal example showing this in action on QEMU x86, like the arm_smc or x86_64_ioport examples, as a proof that it works.

For example, you can use QEMU's DMA-capable "educational device": https://www.qemu.org/docs/master/specs/edu.html. You copy some data from normal RAM into the device's SRAM with a DMA transaction, then read back the device's SRAM via normal MMIO to verify that the transfer succeeded.

Copy link
Copy Markdown
Contributor

@midnightveil midnightveil left a comment

Choose a reason for hiding this comment

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

Misc things.

I'm not quite sure how this is supposed to be used in the SDF file.

I can only vaguely infer from the error tests you added, but you should add documentation on how to use this and what that means for the layout of the page tables for both.

use sel4_capdl_initializer_types::{
object, CapTableEntry, Fill, FillEntry, FillEntryContent, NamedObject, Object, ObjectId, Spec,
Word,
object::{self},
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.

Why object::{self}. What was wrong with just object?

Comment on lines +398 to +400
for frame_obj_id in frames.iter() {
// Make a cap for this frame.
let frame_cap = capdl_util_make_frame_cap(*frame_obj_id, read, write, false, false);
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.

Suggested change
for frame_obj_id in frames.iter() {
// Make a cap for this frame.
let frame_cap = capdl_util_make_frame_cap(*frame_obj_id, read, write, false, false);
for &frame_obj_id in frames.iter() {
// Make a cap for this frame.
let frame_cap = capdl_util_make_frame_cap(frame_obj_id, read, write, /* what does this mean */ false, /* what does this mean */ false);

// Step 3-4 Create Scheduling Context
// Step 3-4 Create and Map IO Page Table Structure
if kernel_config.iommu {
let mut pci_to_iospace: HashMap<(u8, u8, u8), ObjectId> = HashMap::new();
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.

This is assuming x86-specificness.

Do we not have a PciDev type anyway, that would make this nicer

also what happened to the domain id from the rust-seL4 pr?

};

// VTD Page table level is defaulted to the three-level structure even if the hardware supports four level.
// Sel4 will only attempt to use the four-level structure if the hardware does not supports three level.
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.

seL4.
Check the grammar.


// VTD Page table level is defaulted to the three-level structure even if the hardware supports four level.
// Sel4 will only attempt to use the four-level structure if the hardware does not supports three level.
// https://github.com/seL4/seL4/blob/c406015c389decc4559fd44cb69604ddd24a0ddb/src/plat/pc99/machine/intel-vtd.c#L498
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.

Use a link to a commit tag preferably over a random commit hash, e.g. seL4/seL4/blob/15.0.0.

Comment thread tool/microkit/src/sdf.rs
Comment on lines +161 to +167
pub name: String,
pub pci_bus: u8,
pub pci_dev: u8,
pub dev_func: u8,
pub ioaddr: u64,
pub perms: u8,
pub text_pos: Option<roxmltree::TextPos>,
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.

Same comments as the rust-seL4 PR: the PCI stuff should be part of x86 as itis arch-speicific.

Comment thread tool/microkit/src/sdf.rs
if map_end > crate::capdl::iomem::VTD_MAX_ADDR {
return Err(
format!(
"Error: iomap for '{}' has address 0x{:x} which exceeds the upper limits of {} in {} '{}' @ {}",
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.

{:#x}.

Comment thread tool/microkit/src/sel4.rs
},
ObjectType::AsidPool => Some(object_sizes.asid_pool),
ObjectType::IOPageTable => Some(12),
// It would be best to avoid such catch all case so people might forget to add the size of new object type here.
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.

Fix it or make an issue I think

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2024, UNSW.
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.

year

Comment thread build_sdk.py
@@ -68,7 +68,7 @@
"KernelPlatform": "pc99",
"KernelX86MicroArch": "generic",
# See https://github.com/seL4/microkit/issues/418 for details.
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.

remove this comment if its solved

Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
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.

3 participants