Skip to content

Instantly share code, notes, and snippets.

@AustinSaintAubin
Forked from r15ch13/iommu.sh
Last active May 17, 2025 21:55
Show Gist options
  • Save AustinSaintAubin/16f930da0abd7cf1c6e1536e5eebb898 to your computer and use it in GitHub Desktop.
Save AustinSaintAubin/16f930da0abd7cf1c6e1536e5eebb898 to your computer and use it in GitHub Desktop.
List IOMMU Groups and the connected USB Devices
#!/usr/bin/env bash
# https://chatgpt.com/c/6828dc89-e524-800e-b978-05b3f27626c9
# IOMMU and Device Enumeration Script
# Description: Enumerates IOMMU groups and lists associated PCI and USB devices
# in a neatly formatted, column-aligned table.
# Usage: Run as root or with permissions to read /sys/kernel/iommu_groups,
# and have lspci and lsusb available.
# Output: Columns: IOMMU group, Device ID (vendor:device), Flags (e.g., reset support or USB),
# Address or bus:device, Type (PCI/USB), Description.
# Enable nullglob so patterns that match no files expand to empty
shopt -s nullglob
# Array to collect all output rows
declare -a rows
# Function to queue a row for later formatted output
# queue_row() { rows+=("$1"); }
queue_row() { rows+=("$(printf '%s\t[%s]\t%s\t%s\t%s' "${1}" "${2}" "${3}" "${4}" "${5}")"); }
# Function queue_rowto print all queued rows with column alignment
# print_all_rows() { printf '%s\n' "${rows[@]}" | column -ts $'\t'; }
# Header
rows+=("$(printf '%s\t%s\t%s\t%s\t%s\t%s' "IOMMU" "Device ID" "Flags" "Address" "Type" "Description")");
rows+=("$(printf '%s\t%s\t%s\t%s\t%s\t%s' "--------" "-----------" "-----" "-------" "------------" "--------------------------------------------")");
# Track the last processed IOMMU group ID to control header formatting
last_group_id=""
# Iterate over each IOMMU group directory, sorted numerically
for iommu_group_dir in $(find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V); do
# Iterate over each PCI device in this IOMMU group
for device_dir in "${iommu_group_dir}/devices/"*; do
# Extract the current group ID from the directory name
current_group_id="${iommu_group_dir##*/}"
# Determine group column header for first device in the group
if [[ "$current_group_id" != "$last_group_id" ]]; then
group_col="Group ${current_group_id}"
else
group_col=" L $current_group_id"
fi
last_group_id="$current_group_id"
# Gather PCI information
vendor_device_id=$(lspci -nms "${device_dir##*/}" | awk -F'"' '{printf "%s:%s", $4, $6}')
reset_flag=""
[[ -e "${device_dir}/reset" ]] && reset_flag="[R]"
pci_details=$(lspci -mms "${device_dir##*/}" | awk -F'"' '{printf "%s\t%s\t%s", $1, $2, $6}')
# Queue the PCI row (tab-separated)
# rows+=("${group_col} [${vendor_device_id}] ${reset_flag} ${pci_details}")
# rows+=("$(printf '%s\t[%s]\t[%s]\t%s\t%s' "${group_col}" "${vendor_device_id}" "${reset_flag}" "${pci_details}")")
queue_row "${group_col}" "${vendor_device_id}" "${reset_flag}" "${pci_details}"
# Process any USB interfaces for this device
for usb_dir in "${device_dir}/usb"*/; do
bus_number=$(<"${usb_dir}/busnum")
dev_number=$(<"${usb_dir}/devnum")
group_col=" L $current_group_id"
# Get the lsusb line and parse vendor:product ID and description
usb_line=$(lsusb -s "${bus_number}:${dev_number}")
usb_id=$(awk '{print $6}' <<< "$usb_line")
usb_desc=${usb_line#* $usb_id }
# Queue the USB row using printf to embed tabs correctly
# rows+=("$(printf '\t[%s]\t[%s]\t%s\t%s' "$usb_id" "${bus_number}:${dev_number}" "U" "$usb_desc")")
queue_row "$group_col" "$usb_id" "USB" "${bus_number}:${dev_number}" "$usb_desc"
done
done
done
# Print all collected rows with aligned columns
printf '%s\n' "${rows[@]}" | column -ts $'\t';
@AustinSaintAubin
Copy link
Author

Tested and working on Proxmox 8.4

Example Output

IOMMU     Device ID    Flags  Address   Type                           Description                                                               
--------  -----------  -----  -------   ------------                   --------------------------------------------                              
Group 0   [8086:0c04]         00:00.0   Host bridge                    Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller                    
Group 1   [8086:0c01]         00:01.0   PCI bridge                     Xeon E3-1200 v3/4th Gen Core Processor PCI Express x16 Controller         
    L 1   [10de:13d7]  [R]    01:00.0   VGA compatible controller      GM204M [GeForce GTX 980M]                                                 
    L 1   [10de:0fbb]         01:00.1   Audio device                   GM204 High Definition Audio Controller                                    
Group 2   [8086:8c31]         00:14.0   USB controller                 8 Series/C220 Series Chipset Family USB xHCI                              
    L 2   [1d6b:0002]  USB    3:1       Linux Foundation 2.0 root hub                                                                            
    L 2   [1d6b:0003]  USB    4:1       Linux Foundation 3.0 root hub                                                                            
Group 3   [8086:8c3a]         00:16.0   Communication controller       8 Series/C220 Series Chipset Family MEI Controller #1                     
Group 4   [8086:8c2d]  [R]    00:1a.0   USB controller                 8 Series/C220 Series Chipset Family USB EHCI #2                           
    L 4   [1d6b:0002]  USB    1:1       Linux Foundation 2.0 root hub                                                                            
Group 5   [8086:8c20]  [R]    00:1b.0   Audio device                   8 Series/C220 Series Chipset High Definition Audio Controller             
Group 6   [8086:8c10]  [R]    00:1c.0   PCI bridge                     8 Series/C220 Series Chipset Family PCI Express Root Port #1              
Group 7   [8086:8c14]  [R]    00:1c.2   PCI bridge                     8 Series/C220 Series Chipset Family PCI Express Root Port #3              
Group 8   [8086:8c16]  [R]    00:1c.3   PCI bridge                     8 Series/C220 Series Chipset Family PCI Express Root Port #4              
Group 9   [8086:8c26]  [R]    00:1d.0   USB controller                 8 Series/C220 Series Chipset Family USB EHCI #1                           
    L 9   [1d6b:0002]  USB    2:1       Linux Foundation 2.0 root hub                                                                            
Group 10  [8086:8c4b]         00:1f.0   ISA bridge                     HM87 Express LPC Controller                                               
    L 10  [8086:8c03]         00:1f.2   SATA controller                8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode]  
    L 10  [8086:8c22]         00:1f.3   SMBus                          8 Series/C220 Series Chipset Family SMBus Controller                      
Group 11  [8086:08b1]  [R]    3b:00.0   Network controller             Wireless 7260                                                             
Group 12  [10ec:8168]  [R]    3c:00.0   Ethernet controller            RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment