Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/verify-split-files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ on:
- "tests/uv-required-version.sh"
- "tests/docker-lxcfs.sh"
- "tests/java-memory.sh"
- "tests/gpu-pci-class.sh"
- "tests/nvidia-version-pin.sh"
- "tests/external-installer.sh"
- "tests/forge-version-key.sh"
Expand Down Expand Up @@ -88,6 +89,7 @@ on:
- "tests/uv-required-version.sh"
- "tests/docker-lxcfs.sh"
- "tests/java-memory.sh"
- "tests/gpu-pci-class.sh"
- "tests/nvidia-version-pin.sh"
- "tests/external-installer.sh"
- "tests/forge-version-key.sh"
Expand Down Expand Up @@ -170,6 +172,9 @@ jobs:
- name: Java memory drop-in tests
run: bash tests/java-memory.sh

- name: GPU detection by PCI class tests
run: bash tests/gpu-pci-class.sh

- name: NVIDIA userspace version pin tests
run: bash tests/nvidia-version-pin.sh

Expand Down
3 changes: 2 additions & 1 deletion api/sysinfo.func
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ detect_gpu() {
GPU_PASSTHROUGH="unknown"

local gpu_line
gpu_line=$(lspci 2>/dev/null | grep -iE "VGA|3D|Display" | head -1 || true)
# The class field only: the whole line matched "Device 43d0" and "SanDisk Ultra 3D".
gpu_line=$(lspci 2>/dev/null | grep -E '^[^ ]+ (VGA compatible|XGA compatible|3D|Display) controller[ :]' | head -1 || true)

if [[ -n "$gpu_line" ]]; then
GPU_MODEL=$(echo "$gpu_line" | sed 's/.*: //' | sed 's/ (rev .*)$//' | cut -c1-64)
Expand Down
2 changes: 1 addition & 1 deletion incus/backend.func
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ incus_detect_gpu_devices() {
elif grep -q '\[10de:' <<<"$line"; then
NVIDIA_GPUS+=("pci=${pci}")
fi
done < <(lspci -nn -D 2>/dev/null | grep -E 'VGA|Display|3D' || true)
done < <(lspci -nn -D 2>/dev/null | grep -E '^[^ ]+ (VGA compatible|XGA compatible|3D|Display) controller[ :]' || true)

# DRM sysfs fallback (useful on ARM / non-PCI GPUs)
if [[ ${#INTEL_GPUS[@]} -eq 0 && ${#AMD_GPUS[@]} -eq 0 && ${#NVIDIA_GPUS[@]} -eq 0 && -d /sys/class/drm ]]; then
Expand Down
3 changes: 2 additions & 1 deletion lib/hwaccel.func
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ setup_hwaccel() {
GPU_NAMES+=("$gpu_name")
((gpu_count++)) || true
fi
done < <(lspci 2>/dev/null | grep -Ei 'vga|3d|display')
# The class field only: the whole line matched "Device 43d0" and "SanDisk Ultra 3D".
done < <(lspci 2>/dev/null | grep -E '^[^ ]+ (VGA compatible|XGA compatible|3D|Display) controller[ :]')

# Check for AMD APU via CPU vendor if no discrete GPU found
local cpu_vendor
Expand Down
2 changes: 1 addition & 1 deletion pve/backend.func
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ $PCT_OPTIONS_STRING"

# Store PCI info to avoid multiple calls
local pci_vga_info
pci_vga_info=$(lspci -nn 2>/dev/null | grep -E "VGA|Display|3D" || true)
pci_vga_info=$(lspci -nn 2>/dev/null | grep -E '^[^ ]+ (VGA compatible|XGA compatible|3D|Display) controller[ :]' || true)

if [[ -z "$pci_vga_info" ]]; then
msg_debug "No VGA/Display/3D PCI devices found"
Expand Down
46 changes: 46 additions & 0 deletions tests/gpu-pci-class.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -euo pipefail

CORE_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
PATTERN='^[^ ]+ (VGA compatible|XGA compatible|3D|Display) controller[ :]'
passed=0 failed=0

check() {
if [[ "$3" == "$2" ]]; then
echo "PASS $1"
passed=$((passed + 1))
else
echo "FAIL $1: expected <$2>, got <$3>" >&2
failed=$((failed + 1))
fi
}

for f in lib/hwaccel.func api/sysinfo.func pve/backend.func incus/backend.func; do
check "$f filters lspci on the class field" 1 "$(grep -F "lspci" "$CORE_DIR/$f" | grep -cF "grep -E '$PATTERN'")"
done

# From issue #217 and telemetry gpu_model values; the slot says what each is.
lines=(
"02:00.0 USB controller: Advanced Micro Devices, Inc. [AMD] Device 43d0 (rev 01)"
"03:00.0 Non-Volatile memory controller: Sandisk Corp SanDisk Ultra 3D / WD PC SN530, IX SN530, Blue SN550 NVMe SSD (rev 01)"
"04:00.0 Non-Volatile memory controller: Realtek Semiconductor Co., Ltd. RTS5763DL x2 NVMe SSD Controller (rev 01)"
"00:03.0 PCI bridge: Intel Corporation Xeon E5/Core i7 IIO PCI Express Root Port 3d (rev 07)"
"0b:00.1 Audio device: NVIDIA Corporation GA104 High Definition Audio Controller (rev a1)"
"0b:00.0 VGA compatible controller: NVIDIA Corporation GA104 [GeForce RTX 3070] (rev a1)"
"0e:00.0 VGA compatible controller: Intel Corporation Battlemage G21 [Intel Graphics]"
"01:00.0 3D controller: NVIDIA Corporation GP104GL [Tesla P4] (rev a1)"
"00:02.0 Display controller: Intel Corporation HD Graphics 630 (rev 04)"
)
check "plain lspci: only display controllers" "0b:00.0 0e:00.0 01:00.0 00:02.0" \
"$(printf '%s\n' "${lines[@]}" | grep -E "$PATTERN" | awk '{print $1}' | xargs)"

nn=(
"02:00.0 USB controller [0c03]: Advanced Micro Devices, Inc. [AMD] Device [1022:43d0] (rev 01)"
"0b:00.0 VGA compatible controller [0300]: NVIDIA Corporation GA104 [GeForce RTX 3070] [10de:2484] (rev a1)"
"0000:0e:00.0 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e20b]"
)
check "lspci -nn and -D: only display controllers" "0b:00.0 0000:0e:00.0" \
"$(printf '%s\n' "${nn[@]}" | grep -E "$PATTERN" | awk '{print $1}' | xargs)"

printf '%s passed, %s failed\n' "$passed" "$failed"
((failed == 0))
Loading