Skip to content

Commit

Permalink
work around virsh not liking vendor:product pci's
Browse files Browse the repository at this point in the history
  • Loading branch information
ifd3f committed Dec 13, 2024
1 parent a8e305f commit 657a845
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 5 deletions.
6 changes: 6 additions & 0 deletions nix/nixos-modules/astral/vfio/test_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
"type": "usb",
"id": "12c9:2003"
}
],
"gpu": [
{
"type": "pci",
"id": "10de:2482"
}
]
}
}
45 changes: 40 additions & 5 deletions nix/nixos-modules/astral/vfio/vfiohotplug.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3

import re
import logging
import os
import subprocess
Expand Down Expand Up @@ -29,6 +29,14 @@ class Config:
groups: t.Dict[str, t.List[Device]]


@dataclass
class PCIPath:
domain: str
bus: str
slot: str
function: str


def parser():
parser = argparse.ArgumentParser(
prog="vfiohotplug",
Expand Down Expand Up @@ -95,11 +103,21 @@ def assoc_group_name(query: str, config: Config) -> str:

def manage_device(action: str, device: Device, config: Config):
with tempfile.NamedTemporaryFile("w") as f:
xml = f"""<hostdev mode="subsystem" type="{device.type}" managed="yes">
match device.type:
case "usb":
xml = f"""<hostdev mode="subsystem" type="{device.type}" managed="yes">
<source>
<vendor id="{device.vendor}" />
<product id="{device.product}" />
<vendor id="0x{device.vendor}" />
<product id="0x{device.product}" />
</source>
</hostdev>"""
case "pci":
path = find_pci_path(device.vendor, device.product)
xml = f"""
<hostdev mode="subsystem" type="pci" managed="yes">
<source>
<address domain="0x{path.domain}" bus="0x{path.bus}" slot="0x{path.slot}" function="0x{path.function}"/>
</source>
</hostdev>"""
logger.debug("Writing XML file %r: %r", f.name, xml)

Expand Down Expand Up @@ -155,7 +173,24 @@ def parse_device(d: dict) -> Device:
vendor, product = d["id"].split(":")
except ValueError:
raise ValueError(f"ID not in <vendor>:<product> form: {d['id']}")
return Device(dt, "0x" + vendor, "0x" + product)
return Device(dt, vendor, product)


def find_pci_path(vendor: str, product: str) -> PCIPath:
vpid = f"{vendor}:{product}"
logger.debug("querying path of device %s", vpid)
output = (
subprocess.check_output(["lspci", "-d", vpid, "-D"])
.decode()
.strip()
.splitlines()
)

results = [
PCIPath(*re.match(r"(\d+):(\d+):(\d+).(\d+).*", l).groups()) for l in output
]
logger.info("associated pci:%s to paths: %r", vpid, results)
return results[0]


if __name__ == "__main__":
Expand Down

0 comments on commit 657a845

Please sign in to comment.