Skip to content

fix(devices): expose VFIO IOMMU group nodes for PCI passthrough - #817

Open
silentone12725 wants to merge 4 commits into
kernalix7:mainfrom
silentone12725:feat/pci-vfio-passthrough
Open

fix(devices): expose VFIO IOMMU group nodes for PCI passthrough#817
silentone12725 wants to merge 4 commits into
kernalix7:mainfrom
silentone12725:feat/pci-vfio-passthrough

Conversation

@silentone12725

@silentone12725 silentone12725 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix PCI passthrough for the containerized QEMU backend by exposing the VFIO
IOMMU-group device nodes required by assigned PCI devices.

Previously, WinPodX added only the global VFIO control device:

/dev/vfio/vfio

to the generated container configuration. A PCI device bound to vfio-pci
also requires its corresponding IOMMU-group device node:

/dev/vfio/<group>

Without that node inside the container, QEMU cannot open the assigned VFIO
device even when the host-side device has been correctly bound to
vfio-pci.

This PR resolves the IOMMU group for each configured PCI device and exposes
the corresponding /dev/vfio/<group> node alongside /dev/vfio/vfio.

Changes

VFIO device-node discovery

Updated host_device_nodes() in src/winpodx/core/devices.py so PCI
passthrough now:

  • adds /dev/vfio/vfio when at least one PCI device is assigned;
  • resolves the IOMMU group for every assigned PCI device;
  • adds /dev/vfio/<group> for each resolved group;
  • de-duplicates group nodes when multiple PCI functions belong to the same
    IOMMU group;
  • keeps USB handling unchanged.

This is necessary because /dev/vfio/vfio is only the VFIO control device.
The actual assigned PCI device is accessed by QEMU through the VFIO group
character device.

For example, a PCI device in IOMMU group 14 now results in:

/dev/vfio/vfio
/dev/vfio/14

instead of only:

/dev/vfio/vfio

Compose generation

Updated src/winpodx/core/pod/compose.py so the VFIO nodes returned by
host_device_nodes() are included in the generated container device list.

The existing USB live-passthrough handling remains separate:
/dev/bus/usb continues to be managed by the USB-specific path rather than
being duplicated in this block.

The SELinux handling for PCI passthrough is also preserved: exposing VFIO
character devices requires the existing label=disable behavior on SELinux
hosts because the normal container label cannot access those host device
nodes.

Tests

Expanded tests/test_devices.py to cover the VFIO group-node behavior,
including:

  • PCI assignments exposing both /dev/vfio/vfio and the corresponding
    /dev/vfio/<group>;
  • multiple PCI functions in the same IOMMU group producing only one group
    node;
  • USB behavior remaining unchanged;
  • generated compose content containing the required VFIO nodes;
  • PCI-only configurations retaining the required SELinux handling.

The targeted device test suites pass:

43 passed in 0.17s

with:

env PYTHONPATH="$PWD/src" python -m pytest \
    tests/test_devices.py \
    tests/test_device_cli.py \
    -q

Formatting and linting

The changed Python files were formatted with Ruff.

Validation:

ruff check src/ tests/
and ruff format --check src/ tests/

Result:

All checks passed!
253 files already formatted

git diff --check also reports no whitespace errors.

Documentation

Updated both changelogs under [Unreleased]:

  • CHANGELOG.md
  • docs/CHANGELOG.ko.md

They now document why exposing only /dev/vfio/vfio was insufficient and
that WinPodX also exposes and de-duplicates the required VFIO IOMMU-group
nodes.

Validation

The directly affected device and compose functionality has been validated
with the targeted test suites:

43 passed in 0.17s

Ruff and formatting checks also pass with no whitespace errors.

Commits

8a8addb6 fix(devices): expose VFIO IOMMU group nodes for PCI passthrough
93642fe style: format VFIO passthrough changes
7726829 docs: document VFIO IOMMU group fix

Checklist

  • Targeted device/compose tests pass (43 passed)
  • ruff check src/ tests/: zero errors
  • ruff format --check src/ tests/: formatted
  • Documentation updated (CHANGELOG, docs: both ko & en)
  • No hardcoded paths, credentials, or personal info

@kernalix7 kernalix7 self-assigned this Aug 10, 2026
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.

2 participants