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  }