Last active
August 18, 2024 06:31
-
-
Save JaciBrunning/6be34dfd11b7b8cfa0aab57ad260c518 to your computer and use it in GitHub Desktop.
USB -> PCIe -> IOMMU viewer for linux
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lsusb = `lsusb`.split("\n").reject { |x| x.include?("root") }.map do |e| | |
ar = e.scan(/Bus (\d+) Device \d+: ID [0-9a-f:]+ (.*)/).flatten | |
ar[0] = "usb#{ar[0].to_i}" | |
ar | |
end | |
sysbus = `ls -l /sys/bus/usb/devices`.split("\n").map do |e| | |
e.scan(/(usb\d+) -> .+\/([0-9a-f:\.]+)\/usb\d+/).flatten | |
end.reject { |x| x.empty? } | |
iommu = Dir.glob("/sys/kernel/iommu_groups/*/devices/*").map do |e| | |
arr = e.scan(/iommu_groups\/(\d+)\/devices\/([0-9a-f:\.]+)/).flatten | |
arr[0] = arr[0].to_i | |
pci = `lspci -nns #{arr[1]}`.strip.scan(/\[([0-9a-f:]+)\]/).flatten.last | |
[arr, pci].flatten | |
end | |
mapped = {} | |
lsusb.map do |usb, name| | |
mapped[usb] ||= { devices: [] } | |
pci = sysbus.find { |x| x.first == usb }[1] | |
mmu = iommu.find { |x| x[1] == pci } | |
mapped[usb][:devices] << name | |
mapped[usb][:pci] = pci | |
mapped[usb][:pcidetail] = mmu.last | |
mapped[usb][:iommu] = mmu.first | |
mapped[usb][:iommu_count] = iommu.find_all { |x| x.first == mmu.first }.count | |
end | |
mapped.sort.each do |k, v| | |
puts k | |
puts " - PCI: #{v[:pci]} [#{v[:pcidetail]}]" | |
puts " - IOMMU: Group #{v[:iommu]} (#{v[:iommu_count]} device(s) on group)" | |
puts " - Devices:" | |
puts v[:devices].map { |x| " - #{x}" }.join("\n") | |
end |
Sorry for necro, but I wrote a Python version of your script (so that I don't have to install ruby just for running the script).
Here it is:
#!/usr/bin/env python3
# This is a Python rewrite this of Ruby script:
# https://gist.github.com/JaciBrunning/6be34dfd11b7b8cfa0aab57ad260c518
import re
import subprocess
from pathlib import Path
def flatten(xss):
return [x for xs in xss for x in xs]
lsusb_re = re.compile(r"Bus (\d+) Device \d+: ID [0-9a-f:]+ (.*)")
lsusb = []
for usb in subprocess.run("lsusb", capture_output=True, encoding="utf-8").stdout.split(
"\n"
):
if "root" not in usb and lsusb_re.search(usb):
match = flatten(lsusb_re.findall(usb))
match[0] = f"usb{int(match[0])}"
lsusb.append(match)
sysbus_re = re.compile(r"(usb\d+) -> .+\/([0-9a-f:\.]+)\/usb\d+")
sysbus_list = flatten(
[
sysbus_re.findall(sysbus)
for sysbus in subprocess.run(
["ls", "-l", "/sys/bus/usb/devices"], capture_output=True, encoding="utf-8"
).stdout.split("\n")
if sysbus_re.search(sysbus)
]
)
iommu_re = re.compile(r"iommu_groups\/(\d+)\/devices\/([0-9a-f:\.]+)")
pci_re = re.compile(r"\[([0-9a-f:]+)\]")
iommu_list = []
for path in Path("/sys/kernel/iommu_groups").glob("*/devices/*"):
if iommu_re.search(str(path)):
match = flatten(iommu_re.findall(str(path)))
output = subprocess.run(
["lspci", "-nns", match[1]], capture_output=True, encoding="utf-8"
).stdout
if pci_re.search(output):
match.append(pci_re.findall(output)[-1])
iommu_list.append(match)
mapped = {}
for usb in lsusb:
if usb[0] not in mapped:
mapped[usb[0]] = {"devices": []}
mapped[usb[0]]["iommu_count"] = 0
iommu_group = -1
for sysbus in sysbus_list:
if sysbus[0] == usb[0]:
mapped[usb[0]]["pci"] = sysbus[1]
break
for iommu in iommu_list:
if iommu[1] == mapped[usb[0]]["pci"]:
mapped[usb[0]]["iommu"] = iommu[0]
mapped[usb[0]]["pcidetail"] = iommu[-1]
iommu_group = iommu[0]
break
for iommu in iommu_list:
if iommu[0] == iommu_group:
mapped[usb[0]]["iommu_count"] += 1
mapped[usb[0]]["devices"].append(usb[1])
for usb_id, usb_dict in mapped.items():
devices = ""
for device in usb_dict["devices"]:
devices += f"\n - {device}"
print(f"""{usb_id}
- PCI: {usb_dict["pci"]} [{usb_dict["pcidetail"]}]
- IOMMU: Group {usb_dict["iommu"]} ({usb_dict["iommu_count"]} device(s) in the same IOMMU group)
- USB devices: {devices}""")
Sample output:
usb1
- PCI: 0000:04:00.0 [1b21:3241]
- IOMMU: Group 23 (1 device(s) in the same IOMMU group)
- USB devices:
- Genesys Logic, Inc. Hub
- Genesys Logic, Inc. SD Card Reader and Writer
- Microsoft Corp. Xbox360 Controller
usb3
- PCI: 0000:07:00.1 [1022:149c]
- IOMMU: Group 20 (4 device(s) in the same IOMMU group)
- USB devices:
- Integrated Technology Express, Inc. RGB LED Controller
- Genesys Logic, Inc. Hub
- Genesys Logic, Inc. Hub
- JMTek, LLC. USB PnP Audio Device
usb4
- PCI: 0000:07:00.1 [1022:149c]
- IOMMU: Group 20 (4 device(s) in the same IOMMU group)
- USB devices:
- Genesys Logic, Inc. GL3523 Hub
- SanDisk Corp. SanDisk 3.2 Gen1
usb5
- PCI: 0000:07:00.3 [1022:149c]
- IOMMU: Group 20 (4 device(s) in the same IOMMU group)
- USB devices:
- Intel Corp. AX200 Bluetooth
- Genesys Logic, Inc. Hub
- Keychron Keychron K8 Pro
- Logitech, Inc. Logi Bolt Receiver
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Designed to identify what USB controller is used in each IOMMU group for guest isolation with VFIO
Example output: