github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/virtcontainers/device/drivers/utils.go (about) 1 // Copyright (c) 2017-2018 Intel Corporation 2 // Copyright (c) 2018 Huawei Corporation 3 // 4 // SPDX-License-Identifier: Apache-2.0 5 // 6 7 package drivers 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "os" 13 "path/filepath" 14 "strings" 15 16 "github.com/kata-containers/runtime/virtcontainers/device/api" 17 "github.com/kata-containers/runtime/virtcontainers/device/config" 18 "github.com/sirupsen/logrus" 19 ) 20 21 const ( 22 intMax = ^uint(0) 23 24 PCIDomain = "0000" 25 PCIeKeyword = "PCIe" 26 27 PCIConfigSpaceSize = 256 28 ) 29 30 type PCISysFsType string 31 32 var ( 33 PCISysFsDevices PCISysFsType = "devices" // /sys/bus/pci/devices 34 PCISysFsSlots PCISysFsType = "slots" // /sys/bus/pci/slots 35 ) 36 37 type PCISysFsProperty string 38 39 var ( 40 PCISysFsDevicesClass PCISysFsProperty = "class" // /sys/bus/pci/devices/xxx/class 41 PCISysFsSlotsAddress PCISysFsProperty = "address" // /sys/bus/pci/slots/xxx/address 42 PCISysFsSlotsMaxBusSpeed PCISysFsProperty = "max_bus_speed" // /sys/bus/pci/slots/xxx/max_bus_speed 43 ) 44 45 func deviceLogger() *logrus.Entry { 46 return api.DeviceLogger() 47 } 48 49 /* 50 Identify PCIe device by /sys/bus/pci/slots/xx/max_bus_speed, sample content "8.0 GT/s PCIe" 51 The /sys/bus/pci/slots/xx/address contains bdf, sample content "0000:04:00" 52 bdf format: bus:slot.function 53 */ 54 func isPCIeDevice(bdf string) bool { 55 if len(strings.Split(bdf, ":")) == 2 { 56 bdf = PCIDomain + ":" + bdf 57 } 58 59 configPath := filepath.Join(config.SysBusPciDevicesPath, bdf, "config") 60 fi, err := os.Stat(configPath) 61 if err != nil { 62 deviceLogger().WithField("dev-bdf", bdf).WithField("error", err).Warning("Couldn't stat() configuration space file") 63 return false //Who knows? 64 } 65 66 // Plain PCI devices hav 256 bytes of configuration space, 67 // PCI-Express devices have 4096 bytes 68 return fi.Size() > PCIConfigSpaceSize 69 } 70 71 // read from /sys/bus/pci/devices/xxx/property 72 func getPCIDeviceProperty(bdf string, property PCISysFsProperty) string { 73 if len(strings.Split(bdf, ":")) == 2 { 74 bdf = PCIDomain + ":" + bdf 75 } 76 propertyPath := filepath.Join(config.SysBusPciDevicesPath, bdf, string(property)) 77 rlt, err := readPCIProperty(propertyPath) 78 if err != nil { 79 deviceLogger().WithError(err).WithField("path", propertyPath).Warn("failed to read pci device property") 80 return "" 81 } 82 return rlt 83 } 84 85 func readPCIProperty(propertyPath string) (string, error) { 86 var ( 87 buf []byte 88 err error 89 ) 90 if buf, err = ioutil.ReadFile(propertyPath); err != nil { 91 return "", fmt.Errorf("failed to read pci sysfs %v, error:%v", propertyPath, err) 92 } 93 return strings.Split(string(buf), "\n")[0], nil 94 } 95 96 func GetVFIODeviceType(deviceFileName string) config.VFIODeviceType { 97 //For example, 0000:04:00.0 98 tokens := strings.Split(deviceFileName, ":") 99 vfioDeviceType := config.VFIODeviceErrorType 100 if len(tokens) == 3 { 101 vfioDeviceType = config.VFIODeviceNormalType 102 } else { 103 //For example, 83b8f4f2-509f-382f-3c1e-e6bfe0fa1001 104 tokens = strings.Split(deviceFileName, "-") 105 if len(tokens) == 5 { 106 vfioDeviceType = config.VFIODeviceMediatedType 107 } 108 } 109 return vfioDeviceType 110 }