@@ -473,7 +473,7 @@ for VM in "${VMS[@]}"; do
473
473
# -- MDEV hostdevs: use xmlstarlet to extract UUIDs --
474
474
while IFS= read -r UUID; do
475
475
[[ -n " $UUID " ]] && mdev_to_vm[" $UUID " ]=" $VM "
476
- done < <( echo " $xml " | xmlstarlet sel -T -t -m " //hostdev[@type='mdev']" -v " @uuid" -n 2> /dev/null || true)
476
+ done < <( echo " $xml " | xmlstarlet sel -T -t -m " //hostdev[@type='mdev']/source/address " -v " @uuid" -n 2> /dev/null || true)
477
477
done
478
478
479
479
# Helper: convert a VM name to JSON value (quoted string or null)
@@ -516,6 +516,55 @@ parse_and_add_gpu_properties() {
516
516
fi
517
517
}
518
518
519
+ # Finds and formats mdev instances for a given PCI device (PF or VF).
520
+ # Appends JSON strings for each found mdev instance to the global 'vlist' array.
521
+ # Arguments:
522
+ # $1: mdev_base_path (e.g., /sys/bus/pci/devices/.../mdev_supported_types)
523
+ # $2: bdf (e.g., 01:00.0)
524
+ process_mdev_instances () {
525
+ local mdev_base_path=" $1 "
526
+ local bdf=" $2 "
527
+
528
+ if [[ ! -d " $mdev_base_path " ]]; then
529
+ return
530
+ fi
531
+
532
+ for PROF_DIR in " $mdev_base_path " /* ; do
533
+ [[ -d " $PROF_DIR " ]] || continue
534
+
535
+ local PROFILE_NAME
536
+ if [[ -f " $PROF_DIR /name" ]]; then
537
+ PROFILE_NAME=$( < " $PROF_DIR /name" )
538
+ else
539
+ PROFILE_NAME=$( basename " $PROF_DIR " )
540
+ fi
541
+
542
+ parse_and_add_gpu_properties " $PROF_DIR /description"
543
+
544
+ local DEVICE_DIR=" $PROF_DIR /devices"
545
+ if [[ -d " $DEVICE_DIR " ]]; then
546
+ for UDIR in " $DEVICE_DIR " /* ; do
547
+ [[ -d " $UDIR " ]] || continue
548
+ local MDEV_UUID
549
+ MDEV_UUID=$( basename " $UDIR " )
550
+
551
+ local DOMAIN=" 0x0000"
552
+ local BUS=" 0x${bdf: 0: 2} "
553
+ local SLOT=" 0x${bdf: 3: 2} "
554
+ local FUNC=" 0x${bdf: 6: 1} "
555
+
556
+ local raw
557
+ raw=" ${mdev_to_vm[$MDEV_UUID]:- } "
558
+ local USED_JSON
559
+ USED_JSON=$( to_json_vm " $raw " )
560
+
561
+ vlist+=(
562
+ " {\" mdev_uuid\" :\" $MDEV_UUID \" ,\" profile_name\" :$( json_escape " $PROFILE_NAME " ) ,\" max_instances\" :$MAX_INSTANCES ,\" video_ram\" :$VIDEO_RAM ,\" max_heads\" :$MAX_HEADS ,\" max_resolution_x\" :$MAX_RESOLUTION_X ,\" max_resolution_y\" :$MAX_RESOLUTION_Y ,\" libvirt_address\" :{\" domain\" :\" $DOMAIN \" ,\" bus\" :\" $BUS \" ,\" slot\" :\" $SLOT \" ,\" function\" :\" $FUNC \" },\" used_by_vm\" :$USED_JSON }" )
563
+ done
564
+ fi
565
+ done
566
+ }
567
+
519
568
# === GPU Discovery ===
520
569
521
570
mapfile -t LINES < <( lspci -nnm)
@@ -588,51 +637,9 @@ for LINE in "${LINES[@]}"; do
588
637
# === vGPU (MDEV) instances ===
589
638
VGPU_ARRAY=" []"
590
639
declare -a vlist=()
640
+ # Process mdev on the Physical Function
591
641
MDEV_BASE=" /sys/bus/pci/devices/0000:$PCI_ADDR /mdev_supported_types"
592
- if [[ -d " $MDEV_BASE " ]]; then
593
- for PROF_DIR in " $MDEV_BASE " /* ; do
594
- [[ -d " $PROF_DIR " ]] || continue
595
-
596
- # Read the human-readable profile name from the 'name' file
597
- if [[ -f " $PROF_DIR /name" ]]; then
598
- PROFILE_NAME=$( < " $PROF_DIR /name" )
599
- else
600
- PROFILE_NAME=$( basename " $PROF_DIR " )
601
- fi
602
-
603
- # Fetch max_instance from the description file, if present
604
- parse_and_add_gpu_properties " $PROF_DIR /description"
605
-
606
- # Under each profile, existing UUIDs appear in:
607
- # /sys/bus/pci/devices/0000:$PCI_ADDR/mdev_supported_types/<PROFILE>/devices/*
608
- DEVICE_DIR=" $PROF_DIR /devices"
609
- if [[ -d " $DEVICE_DIR " ]]; then
610
- for UDIR in " $DEVICE_DIR " /* ; do
611
- [[ -d $UDIR ]] || continue
612
- MDEV_UUID=$( basename " $UDIR " )
613
-
614
- # libvirt_address uses PF BDF
615
- DOMAIN=" 0x0000"
616
- BUS=" 0x${PCI_ADDR: 0: 2} "
617
- SLOT=" 0x${PCI_ADDR: 3: 2} "
618
- FUNC=" 0x${PCI_ADDR: 6: 1} "
619
-
620
- # Determine which VM uses this UUID
621
- raw=" ${mdev_to_vm[$MDEV_UUID]:- } "
622
- USED_JSON=$( to_json_vm " $raw " )
623
-
624
- vlist+=(
625
- " {\" mdev_uuid\" :\" $MDEV_UUID \" ,\" profile_name\" :$( json_escape " $PROFILE_NAME " ) ,\" max_instances\" :$MAX_INSTANCES ,\" video_ram\" :$VIDEO_RAM ,\" max_heads\" :$MAX_HEADS ,\" max_resolution_x\" :$MAX_RESOLUTION_X ,\" max_resolution_y\" :$MAX_RESOLUTION_Y ,\" libvirt_address\" :{\" domain\" :\" $DOMAIN \" ,\" bus\" :\" $BUS \" ,\" slot\" :\" $SLOT \" ,\" function\" :\" $FUNC \" },\" used_by_vm\" :$USED_JSON }" )
626
- done
627
- fi
628
- done
629
- if [ ${# vlist[@]} -gt 0 ]; then
630
- VGPU_ARRAY=" [$(
631
- IFS=,
632
- echo " ${vlist[*]} "
633
- ) ]"
634
- fi
635
- fi
642
+ process_mdev_instances " $MDEV_BASE " " $PCI_ADDR "
636
643
637
644
# === VF instances (SR-IOV / MIG) ===
638
645
VF_ARRAY=" []"
@@ -644,6 +651,12 @@ for LINE in "${LINES[@]}"; do
644
651
VF_ADDR=${VF_PATH##*/ } # e.g. "0000:65:00.2"
645
652
VF_BDF=" ${VF_ADDR: 5} " # "65:00.2"
646
653
654
+ # For NVIDIA SR-IOV, check for vGPU (mdev) on the VF itself
655
+ if [[ " $VENDOR_ID " == " 10de" ]]; then
656
+ VF_MDEV_BASE=" $VF_PATH /mdev_supported_types"
657
+ process_mdev_instances " $VF_MDEV_BASE " " $VF_BDF "
658
+ fi
659
+
647
660
DOMAIN=" 0x0000"
648
661
BUS=" 0x${VF_BDF: 0: 2} "
649
662
SLOT=" 0x${VF_BDF: 3: 2} "
@@ -674,6 +687,14 @@ for LINE in "${LINES[@]}"; do
674
687
fi
675
688
fi
676
689
690
+ # Consolidate all vGPU instances (from PF and VFs)
691
+ if [ ${# vlist[@]} -gt 0 ]; then
692
+ VGPU_ARRAY=" [$(
693
+ IFS=,
694
+ echo " ${vlist[*]} "
695
+ ) ]"
696
+ fi
697
+
677
698
# === full_passthrough block ===
678
699
# If vgpu_instances and vf_instances are empty, we can assume full passthrough
679
700
FP_ENABLED=0
0 commit comments