gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/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 "path/filepath" 13 "strings" 14 15 "github.com/kata-containers/runtime/virtcontainers/device/api" 16 "github.com/kata-containers/runtime/virtcontainers/device/config" 17 "github.com/sirupsen/logrus" 18 ) 19 20 const ( 21 intMax = ^uint(0) 22 23 PCIDomain = "0000" 24 PCIeKeyword = "PCIe" 25 ) 26 27 type PCISysFsType string 28 29 var ( 30 PCISysFsDevices PCISysFsType = "devices" // /sys/bus/pci/devices 31 PCISysFsSlots PCISysFsType = "slots" // /sys/bus/pci/slots 32 ) 33 34 type PCISysFsProperty string 35 36 var ( 37 PCISysFsDevicesClass PCISysFsProperty = "class" // /sys/bus/pci/devices/xxx/class 38 PCISysFsSlotsAddress PCISysFsProperty = "address" // /sys/bus/pci/slots/xxx/address 39 PCISysFsSlotsMaxBusSpeed PCISysFsProperty = "max_bus_speed" // /sys/bus/pci/slots/xxx/max_bus_speed 40 ) 41 42 func deviceLogger() *logrus.Entry { 43 return api.DeviceLogger() 44 } 45 46 /* 47 Identify PCIe device by /sys/bus/pci/slots/xx/max_bus_speed, sample content "8.0 GT/s PCIe" 48 The /sys/bus/pci/slots/xx/address contains bdf, sample content "0000:04:00" 49 bdf format: bus:slot.function 50 */ 51 func isPCIeDevice(bdf string) bool { 52 if len(strings.Split(bdf, ":")) == 2 { 53 bdf = PCIDomain + ":" + bdf 54 } 55 slots, err := ioutil.ReadDir(config.SysBusPciSlotsPath) 56 if err != nil { 57 deviceLogger().WithError(err).WithField("path", config.SysBusPciSlotsPath).Warn("failed to list pci slots") 58 return false 59 } 60 b := strings.Split(bdf, ".")[0] 61 for _, slot := range slots { 62 address := getPCISlotProperty(slot.Name(), PCISysFsSlotsAddress) 63 if b == address { 64 maxBusSpeed := getPCISlotProperty(slot.Name(), PCISysFsSlotsMaxBusSpeed) 65 if strings.Contains(maxBusSpeed, PCIeKeyword) { 66 return true 67 } 68 } 69 } 70 deviceLogger().WithField("dev-bdf", bdf).Debug("can not find slot for bdf of pci device") 71 return false 72 } 73 74 // read from /sys/bus/pci/devices/xxx/property 75 func getPCIDeviceProperty(bdf string, property PCISysFsProperty) string { 76 if len(strings.Split(bdf, ":")) == 2 { 77 bdf = PCIDomain + ":" + bdf 78 } 79 propertyPath := filepath.Join(config.SysBusPciDevicesPath, bdf, string(property)) 80 rlt, err := readPCIProperty(propertyPath) 81 if err != nil { 82 deviceLogger().WithError(err).WithField("path", propertyPath).Warn("failed to read pci device property") 83 return "" 84 } 85 return rlt 86 } 87 88 // read from /sys/bus/pci/slots/xxx/property 89 func getPCISlotProperty(slot string, property PCISysFsProperty) string { 90 propertyPath := filepath.Join(config.SysBusPciSlotsPath, slot, string(property)) 91 rlt, err := readPCIProperty(propertyPath) 92 if err != nil { 93 deviceLogger().WithError(err).WithField("path", propertyPath).Warn("failed to read pci slot property") 94 return "" 95 } 96 return rlt 97 } 98 99 func readPCIProperty(propertyPath string) (string, error) { 100 var ( 101 buf []byte 102 err error 103 ) 104 if buf, err = ioutil.ReadFile(propertyPath); err != nil { 105 return "", fmt.Errorf("failed to read pci sysfs %v, error:%v", propertyPath, err) 106 } 107 return strings.Split(string(buf), "\n")[0], nil 108 } 109 110 func GetVFIODeviceType(deviceFileName string) config.VFIODeviceType { 111 //For example, 0000:04:00.0 112 tokens := strings.Split(deviceFileName, ":") 113 vfioDeviceType := config.VFIODeviceErrorType 114 if len(tokens) == 3 { 115 vfioDeviceType = config.VFIODeviceNormalType 116 } else { 117 //For example, 83b8f4f2-509f-382f-3c1e-e6bfe0fa1001 118 tokens = strings.Split(deviceFileName, "-") 119 if len(tokens) == 5 { 120 vfioDeviceType = config.VFIODeviceMediatedType 121 } 122 } 123 return vfioDeviceType 124 }