Skip to content

safl/iommu

Repository files navigation

iommu: inspect and configure the IOMMU in Linux

iommu

PyPI Python Test

iommu is a small CLI for inspecting the current IOMMU mode and switching between them. It rewrites the bootloader's kernel command line; the change applies on the next boot.

Install

pipx install iommu

Or standalone (single-file, stdlib only, no pip needed):

curl -fsSL https://raw.githubusercontent.com/safl/iommu/main/src/iommu/iommu.py \
  -o ~/.local/bin/iommu && chmod +x ~/.local/bin/iommu

Shell completion

iommu --print-completion bash > ~/.local/share/bash-completion/completions/iommu

Open a new shell (or source the file) and tab-completion is live: sudo iommu <TAB> lists show off-for-uio off-for-vfio strict pt.

Usage

$ iommu --help
usage: iommu [-h] [--version] [--verbose] [--print-completion SHELL]
             <action> ...

Inspect and configure the IOMMU in Linux

positional arguments:
  <action>
    show                print current mode and cmdline (default)
    off-for-uio         IOMMU drivers disabled; uio_pci_generic works
    off-for-vfio        IOMMU drivers disabled + noiommu knob; vfio-pci works
                        without isolation
    strict              IOMMU on, translating for every device
    pt                  IOMMU on, host-owned devices in passthrough (most
                        common)

options:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  --verbose             Enable verbose logging
  --print-completion SHELL
                        Print shell completion script to stdout and exit

Each set-mode action also takes a --dry-run flag; iommu <mode> --help prints the per-action help.

A few common invocations:

iommu                              # = iommu show (no-arg default)
iommu show                         # cmdline, mode, iommufd + vfio-cdev availability
iommu pt --dry-run                 # preview without writing GRUB
sudo iommu pt && sudo reboot       # most common: IOMMU on, host passthrough
sudo iommu strict                  # IOMMU on, translating for all devices
sudo iommu off-for-uio             # IOMMU disabled, uio_pci_generic ready
sudo iommu off-for-vfio            # IOMMU disabled + noiommu knob, vfio-pci ready

iommu show sample output (here from a WSL host with the IOMMU disabled by the WSL kernel; on a typical bare-metal host the cmdline contains the intel_iommu / amd_iommu / iommu=pt tokens and mode reads one of off-for-uio, off-for-vfio, strict, or pt):

cmdline:   initrd=\initrd.img WSL_ROOT_INIT=1 panic=-1 nr_cpus=16 hv_utils.timesync_implicit=1 console=hvc0 debug pty.legacy_count=0 WSL_ENABLE_CRASH_DUMP=1
mode:      unset
iommufd:   absent (/dev/iommu)
vfio-cdev: 0 device(s) at /dev/vfio/devices

Related

  • devbind: inspect and control PCI device-driver binding in Linux.
  • hugepages: inspect and manage Linux hugepages.

Background

The Linux IOMMU (Intel VT-d, AMD-Vi) sits between the CPU and PCI devices, translating and isolating DMA. User space tools that talk to PCI devices directly (vfio-pci for VM passthrough, vfio-pci or uio_pci_generic for DPDK/SPDK and xNVMe/uPCIe) interact with the IOMMU substrate differently depending on which mode the kernel was booted with.

Modes

Four substrate modes, mutually exclusive.

off-for-uio

Kernel parameters: intel_iommu=off amd_iommu=off

The IOMMU drivers don't load. No DMA isolation anywhere. uio_pci_generic binds and works. vfio-pci does not work here; there are no IOMMU groups for it to bind against. Zero overhead, zero protection; appropriate on trusted hardware or for development where the IOMMU is undesirable.

off-for-vfio

Kernel parameters: intel_iommu=off amd_iommu=off vfio.enable_unsafe_noiommu_mode=1

Same as off-for-uio (IOMMU off, no DMA isolation), but also tells the vfio module to expose "noiommu" groups so vfio-pci binds without an IOMMU backing it. As unsafe as off-for-uio (same lack of isolation), just a different user space driver framework. Use this when your user space driver stack (DPDK/SPDK and xNVMe/uPCIe) requires vfio-pci but you can't or don't want to turn the IOMMU on.

strict

Kernel parameters: intel_iommu=on amd_iommu=on

The IOMMU drivers load and every DMA from every device is translated, including host-owned devices. Maximum isolation; defends the host kernel from malicious or buggy DMA. Highest per-DMA overhead. This is what "IOMMU on" traditionally meant.

pt (passthrough)

Kernel parameters: intel_iommu=on amd_iommu=on iommu=pt

The IOMMU drivers load but host-owned devices skip translation (the passthrough domain). Devices bound to vfio-pci get switched to an isolated translating domain. Best of both worlds: native host performance plus full vfio isolation for VM-passthrough / user space drivers. The most common production configuration.

Modifiers

Independent of the substrate mode, one further knob sometimes applies:

Unsafe interrupts (cmdline)

On platforms without Interrupt Remapping, vfio-pci passthrough refuses to bind by default. Two tokens lift that restriction:

vfio_iommu_type1.allow_unsafe_interrupts=1
iommufd.allow_unsafe_interrupts=1

Only meaningful when combined with strict or pt. This tool does not write them automatically today; they are listed here for awareness.

What this tool does not control

  • iommufd vs legacy vfio groups. Both APIs ride on top of the substrate modes above. On kernel 6.5+, vfio-pci exposes the legacy /dev/vfio/<group> container API and the iommufd cdev API at /dev/vfio/devices/vfioN (backed by /dev/iommu) simultaneously; whichever the user space consumer asks for is what it gets. iommu doesn't pick.
  • iommu.strict={0,1}. IOTLB-flush policy (lazy vs strict). An orthogonal perf-vs-isolation knob; modern x86 defaults to lazy.
  • Architecture-specific IOMMU drivers beyond Intel VT-d / AMD-Vi (e.g. arm-smmu). Out of scope.

Bootloader handling

iommu <mode> auto-detects the bootloader manager and writes the new cmdline:

  • grubby (Fedora / RHEL): one --update-kernel=ALL invocation to add the target tokens, one to remove the others.
  • /etc/default/grub + update-grub (Debian / Ubuntu): rewrites GRUB_CMDLINE_LINUX in place, then runs update-grub.

--dry-run shows the intended write without applying it; runs as any user, no root needed for the preview. The real write requires root (reading /proc/cmdline for show does not).

About

Inspect and configure the IOMMU isolation level in Linux

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors