Skip to content

Commit 9921c02

Browse files
committed
Add 'vfio' mode to pkg/nvcdi for generating CDI specs for NVIDIA passthrough GPUs
Signed-off-by: Christopher Desiniotis <[email protected]>
1 parent 80a78e6 commit 9921c02

File tree

4 files changed

+105
-0
lines changed

4 files changed

+105
-0
lines changed

cmd/nvidia-ctk/cdi/generate/generate.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ func (m command) validateFlags(c *cli.Context, opts *options) error {
155155
case nvcdi.ModeNvml:
156156
case nvcdi.ModeWsl:
157157
case nvcdi.ModeManagement:
158+
case nvcdi.ModeVfio:
158159
default:
159160
return fmt.Errorf("invalid discovery mode: %v", opts.mode)
160161
}

pkg/nvcdi/api.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ const (
3939
// ModeCSV configures the CDI spec generator to generate a spec based on the contents of CSV
4040
// mountspec files.
4141
ModeCSV = "csv"
42+
// ModeVfio configures the CDI spec generator to generate a VFIO spec.
43+
ModeVfio = "vfio"
4244
)
4345

4446
// Interface defines the API for the nvcdi package

pkg/nvcdi/lib-vfio.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
# Copyright (c) NVIDIA CORPORATION. All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
**/
16+
17+
package nvcdi
18+
19+
import (
20+
"fmt"
21+
22+
"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/spec"
23+
"github.com/container-orchestrated-devices/container-device-interface/pkg/cdi"
24+
"github.com/container-orchestrated-devices/container-device-interface/specs-go"
25+
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvlib/device"
26+
)
27+
28+
type vfiolib nvcdilib
29+
30+
var _ Interface = (*vfiolib)(nil)
31+
32+
// GetSpec should not be called for vfiolib
33+
func (l *vfiolib) GetSpec() (spec.Interface, error) {
34+
return nil, fmt.Errorf("Unexpected call to vfiolib.GetSpec()")
35+
}
36+
37+
// GetAllDeviceSpecs returns the device specs for all available devices.
38+
func (l *vfiolib) GetAllDeviceSpecs() ([]specs.Device, error) {
39+
var deviceSpecs []specs.Device
40+
41+
devices, err := l.nvpcilib.GetGPUs()
42+
if err != nil {
43+
return nil, fmt.Errorf("failed getting NVIDIA GPUs: %v", err)
44+
}
45+
46+
for idx, dev := range devices {
47+
if dev.Driver == "vfio-pci" {
48+
l.logger.Debugf("Found NVIDIA device: address=%s, driver=%s, iommu_group=%d, deviceId=%x",
49+
dev.Address, dev.Driver, dev.IommuGroup, dev.Device)
50+
deviceSpecs = append(deviceSpecs, specs.Device{
51+
Name: fmt.Sprintf("%d", idx),
52+
ContainerEdits: specs.ContainerEdits{
53+
DeviceNodes: []*specs.DeviceNode{
54+
&specs.DeviceNode{
55+
Path: fmt.Sprintf("/dev/vfio/%d", dev.IommuGroup),
56+
},
57+
},
58+
},
59+
})
60+
}
61+
}
62+
63+
return deviceSpecs, nil
64+
}
65+
66+
// GetCommonEdits returns common edits for ALL devices.
67+
// Note, currently there are no common edits.
68+
func (l *vfiolib) GetCommonEdits() (*cdi.ContainerEdits, error) {
69+
return &cdi.ContainerEdits{ContainerEdits: &specs.ContainerEdits{}}, nil
70+
}
71+
72+
// GetGPUDeviceEdits should not be called for vfiolib
73+
func (l *vfiolib) GetGPUDeviceEdits(device.Device) (*cdi.ContainerEdits, error) {
74+
return nil, fmt.Errorf("Unexpected call to vfiolib.GetGPUDeviceEdits()")
75+
}
76+
77+
// GetGPUDeviceSpecs should not be called for vfiolib
78+
func (l *vfiolib) GetGPUDeviceSpecs(int, device.Device) (*specs.Device, error) {
79+
return nil, fmt.Errorf("Unexpected call to vfiolib.GetGPUDeviceSpecs()")
80+
}
81+
82+
// GetMIGDeviceEdits should not be called for vfiolib
83+
func (l *vfiolib) GetMIGDeviceEdits(device.Device, device.MigDevice) (*cdi.ContainerEdits, error) {
84+
return nil, fmt.Errorf("Unexpected call to vfiolib.GetMIGDeviceEdits()")
85+
}
86+
87+
// GetMIGDeviceSpecs should not be called for vfiolib
88+
func (l *vfiolib) GetMIGDeviceSpecs(int, device.Device, int, device.MigDevice) (*specs.Device, error) {
89+
return nil, fmt.Errorf("Unexpected call to vfiolib.GetMIGDeviceSpecs()")
90+
}

pkg/nvcdi/lib.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvlib/device"
2727
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvlib/info"
2828
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvml"
29+
30+
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvpci"
2931
)
3032

3133
type wrapper struct {
@@ -53,6 +55,8 @@ type nvcdilib struct {
5355

5456
infolib info.Interface
5557

58+
nvpcilib nvpci.Interface
59+
5660
mergedDeviceOptions []transform.MergedDeviceOption
5761
}
5862

@@ -114,6 +118,14 @@ func New(opts ...Option) (Interface, error) {
114118
l.class = "mofed"
115119
}
116120
lib = (*mofedlib)(l)
121+
case ModeVfio:
122+
if l.class == "" {
123+
l.class = "pgpu"
124+
}
125+
if l.nvpcilib == nil {
126+
l.nvpcilib = nvpci.New()
127+
}
128+
lib = (*vfiolib)(l)
117129
default:
118130
return nil, fmt.Errorf("unknown mode %q", l.mode)
119131
}

0 commit comments

Comments
 (0)