Skip to content

Commit 2ed804a

Browse files
committed
vfio: Enable selective vfio-pci binding by BFD
Despite its name, GetGPUByPciBusID returns any NVIDIA PCI device (GPU, NVSwitch, etc.) at the specified address, not just GPUs. Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
1 parent a20a56b commit 2ed804a

File tree

3 files changed

+50
-27
lines changed

3 files changed

+50
-27
lines changed

cmd/vfio-manage/bind.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,14 @@ func (m bindCommand) bindAll() error {
134134

135135
func (m bindCommand) bindDevice() error {
136136
device := m.options.deviceID
137+
// Note: Despite its name, GetGPUByPciBusID returns any NVIDIA PCI device
138+
// (GPU, NVSwitch, etc.) at the specified address, not just GPUs.
137139
nvdev, err := m.nvpciLib.GetGPUByPciBusID(device)
138140
if err != nil {
139-
return fmt.Errorf("failed to get NVIDIA GPU device: %w", err)
141+
return fmt.Errorf("failed to get NVIDIA device: %w", err)
140142
}
141-
if nvdev == nil || !nvdev.IsGPU() {
142-
m.logger.Infof("Device %s is not a GPU", device)
143+
if nvdev == nil || (!nvdev.IsGPU() && !nvdev.IsNVSwitch()) {
144+
m.logger.Infof("Device %s is not an NVIDIA GPU or NVSwitch", device)
143145
return nil
144146
}
145147

cmd/vfio-manage/unbind.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,14 @@ func (m unbindCommand) unbindAll() error {
123123

124124
func (m unbindCommand) unbindDevice() error {
125125
device := m.options.deviceID
126+
// Note: Despite its name, GetGPUByPciBusID returns any NVIDIA PCI device
127+
// (GPU, NVSwitch, etc.) at the specified address, not just GPUs.
126128
nvdev, err := m.nvpciLib.GetGPUByPciBusID(device)
127129
if err != nil {
128-
return fmt.Errorf("failed to get NVIDIA GPU device: %w", err)
130+
return fmt.Errorf("failed to get NVIDIA device: %w", err)
129131
}
130-
if nvdev == nil || !nvdev.IsGPU() {
131-
m.logger.Infof("Device %s is not a GPU", device)
132+
if nvdev == nil || (!nvdev.IsGPU() && !nvdev.IsNVSwitch()) {
133+
m.logger.Infof("Device %s is not an NVIDIA GPU or NVSwitch", device)
132134
return nil
133135
}
134136

scripts/vfio-manage

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,29 @@ unbind_from_other_driver() {
4545
}
4646

4747
is_nvidia_gpu_device() {
48-
gpu=$1
49-
# make sure device class is for NVIDIA GPU
50-
device_class_file=$(readlink -f "/sys/bus/pci/devices/$gpu/class")
48+
dev=$1
49+
# make sure device class is for NVIDIA GPU (3D controller or VGA compatible)
50+
device_class_file=$(readlink -f "/sys/bus/pci/devices/$dev/class")
5151
device_class=$(cat "$device_class_file")
5252
[ "$device_class" = "0x030200" ] || [ "$device_class" = "0x030000" ] || return 1
5353
return 0
5454
}
5555

56+
is_nvidia_nvswitch_device() {
57+
dev=$1
58+
# make sure device class is for NVIDIA NVSwitch (bridge device)
59+
device_class_file=$(readlink -f "/sys/bus/pci/devices/$dev/class")
60+
device_class=$(cat "$device_class_file")
61+
[ "$device_class" = "0x068000" ] || return 1
62+
return 0
63+
}
64+
65+
is_nvidia_device() {
66+
dev=$1
67+
# check if device is either a GPU or NVSwitch
68+
is_nvidia_gpu_device "$dev" || is_nvidia_nvswitch_device "$dev"
69+
}
70+
5671
is_bound_to_vfio() {
5772
gpu=$1
5873

@@ -71,19 +86,21 @@ is_bound_to_vfio() {
7186
}
7287

7388
unbind_device() {
74-
gpu=$1
89+
dev=$1
7590

76-
if ! is_nvidia_gpu_device "$gpu"; then
91+
if ! is_nvidia_device "$dev"; then
7792
return 0
7893
fi
7994

80-
echo "unbinding device $gpu"
81-
unbind_from_driver "$gpu"
82-
#for graphics mode, we need to unbind the auxiliary device as well
83-
aux_dev=$(get_graphics_aux_dev "$gpu")
84-
if [ "$aux_dev" != "NONE" ]; then
85-
echo "gpu $gpu is in graphics mode aux_dev $aux_dev"
86-
unbind_from_driver "$aux_dev"
95+
echo "unbinding device $dev"
96+
unbind_from_driver "$dev"
97+
# for graphics mode GPUs, we need to unbind the auxiliary device as well
98+
if is_nvidia_gpu_device "$dev"; then
99+
aux_dev=$(get_graphics_aux_dev "$dev")
100+
if [ "$aux_dev" != "NONE" ]; then
101+
echo "gpu $dev is in graphics mode aux_dev $aux_dev"
102+
unbind_from_driver "$aux_dev"
103+
fi
87104
fi
88105
}
89106

@@ -136,19 +153,21 @@ get_graphics_aux_dev() {
136153
}
137154

138155
bind_device() {
139-
gpu=$1
156+
dev=$1
140157

141-
if ! is_nvidia_gpu_device "$gpu"; then
142-
echo "device $gpu is not a gpu!"
158+
if ! is_nvidia_device "$dev"; then
159+
echo "device $dev is not an NVIDIA GPU or NVSwitch!"
143160
return 0
144161
fi
145162

146-
bind_pci_device "$gpu"
147-
#for graphics mode, we need to bind the auxiliary device as well
148-
aux_dev=$(get_graphics_aux_dev "$gpu")
149-
if [ "$aux_dev" != "NONE" ]; then
150-
echo "gpu $gpu is in graphics mode aux_dev $aux_dev"
151-
bind_pci_device "$aux_dev"
163+
bind_pci_device "$dev"
164+
# for graphics mode GPUs, we need to bind the auxiliary device as well
165+
if is_nvidia_gpu_device "$dev"; then
166+
aux_dev=$(get_graphics_aux_dev "$dev")
167+
if [ "$aux_dev" != "NONE" ]; then
168+
echo "gpu $dev is in graphics mode aux_dev $aux_dev"
169+
bind_pci_device "$aux_dev"
170+
fi
152171
fi
153172
}
154173

0 commit comments

Comments
 (0)