mirror of
https://github.com/aljazceru/kata-containers.git
synced 2026-01-24 16:54:26 +01:00
Currently, isPCIeDevice() attempts to determine if a (host) device is PCI-Express capable by looking up its link speed via the PCI slots information in sysfs. This is a) complicated and b) wrong. PCI-e devices don't have to have slots information, so this frequently fails. Instead determine if devices are PCI-e by checking for the presence of PCIe extended configuration space by looking at the size of the "config" file in sysfs. Forward ported from 6bf93b23 in the Kata 1.x runtime repository. Fixes: #611 Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
111 lines
3.0 KiB
Go
111 lines
3.0 KiB
Go
// Copyright (c) 2017-2018 Intel Corporation
|
|
// Copyright (c) 2018 Huawei Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package drivers
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/api"
|
|
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/device/config"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
const (
|
|
intMax = ^uint(0)
|
|
|
|
PCIDomain = "0000"
|
|
PCIeKeyword = "PCIe"
|
|
|
|
PCIConfigSpaceSize = 256
|
|
)
|
|
|
|
type PCISysFsType string
|
|
|
|
var (
|
|
PCISysFsDevices PCISysFsType = "devices" // /sys/bus/pci/devices
|
|
PCISysFsSlots PCISysFsType = "slots" // /sys/bus/pci/slots
|
|
)
|
|
|
|
type PCISysFsProperty string
|
|
|
|
var (
|
|
PCISysFsDevicesClass PCISysFsProperty = "class" // /sys/bus/pci/devices/xxx/class
|
|
PCISysFsSlotsAddress PCISysFsProperty = "address" // /sys/bus/pci/slots/xxx/address
|
|
PCISysFsSlotsMaxBusSpeed PCISysFsProperty = "max_bus_speed" // /sys/bus/pci/slots/xxx/max_bus_speed
|
|
)
|
|
|
|
func deviceLogger() *logrus.Entry {
|
|
return api.DeviceLogger()
|
|
}
|
|
|
|
/*
|
|
Identify PCIe device by /sys/bus/pci/slots/xx/max_bus_speed, sample content "8.0 GT/s PCIe"
|
|
The /sys/bus/pci/slots/xx/address contains bdf, sample content "0000:04:00"
|
|
bdf format: bus:slot.function
|
|
*/
|
|
func isPCIeDevice(bdf string) bool {
|
|
if len(strings.Split(bdf, ":")) == 2 {
|
|
bdf = PCIDomain + ":" + bdf
|
|
}
|
|
|
|
configPath := filepath.Join(config.SysBusPciDevicesPath, bdf, "config")
|
|
fi, err := os.Stat(configPath)
|
|
if err != nil {
|
|
deviceLogger().WithField("dev-bdf", bdf).WithField("error", err).Warning("Couldn't stat() configuration space file")
|
|
return false //Who knows?
|
|
}
|
|
|
|
// Plain PCI devices hav 256 bytes of configuration space,
|
|
// PCI-Express devices have 4096 bytes
|
|
return fi.Size() > PCIConfigSpaceSize
|
|
}
|
|
|
|
// read from /sys/bus/pci/devices/xxx/property
|
|
func getPCIDeviceProperty(bdf string, property PCISysFsProperty) string {
|
|
if len(strings.Split(bdf, ":")) == 2 {
|
|
bdf = PCIDomain + ":" + bdf
|
|
}
|
|
propertyPath := filepath.Join(config.SysBusPciDevicesPath, bdf, string(property))
|
|
rlt, err := readPCIProperty(propertyPath)
|
|
if err != nil {
|
|
deviceLogger().WithError(err).WithField("path", propertyPath).Warn("failed to read pci device property")
|
|
return ""
|
|
}
|
|
return rlt
|
|
}
|
|
|
|
func readPCIProperty(propertyPath string) (string, error) {
|
|
var (
|
|
buf []byte
|
|
err error
|
|
)
|
|
if buf, err = ioutil.ReadFile(propertyPath); err != nil {
|
|
return "", fmt.Errorf("failed to read pci sysfs %v, error:%v", propertyPath, err)
|
|
}
|
|
return strings.Split(string(buf), "\n")[0], nil
|
|
}
|
|
|
|
func GetVFIODeviceType(deviceFileName string) config.VFIODeviceType {
|
|
//For example, 0000:04:00.0
|
|
tokens := strings.Split(deviceFileName, ":")
|
|
vfioDeviceType := config.VFIODeviceErrorType
|
|
if len(tokens) == 3 {
|
|
vfioDeviceType = config.VFIODeviceNormalType
|
|
} else {
|
|
//For example, 83b8f4f2-509f-382f-3c1e-e6bfe0fa1001
|
|
tokens = strings.Split(deviceFileName, "-")
|
|
if len(tokens) == 5 {
|
|
vfioDeviceType = config.VFIODeviceMediatedType
|
|
}
|
|
}
|
|
return vfioDeviceType
|
|
}
|