mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-05-01 05:04:26 +00:00
runtime: Add support for VFIO-AP pass-through
Recognise when a device to be hot-plugged is an IBM Adjunct Processor (AP) device and execute VFIO AP hot-plug accordingly. Includes unittest for recognising and uses CCW for addDeviceToBridge in hotplugVFIODevice if appropriate. Fixes: #491 Signed-off-by: Jakob-Naucke <jakob.naucke@ibm.com> Co-authored-by: Julio Montes <julio.montes@intel.com> Reviewed-by: Alice Frosi <afrosi@redhat.com>
This commit is contained in:
parent
8df06a046e
commit
1236e22475
@ -1305,6 +1305,9 @@ func (q *qemu) hotplugVFIODevice(device *config.VFIODev, op operation) (err erro
|
|||||||
case config.VFIODeviceNormalType:
|
case config.VFIODeviceNormalType:
|
||||||
return q.qmpMonitorCh.qmp.ExecuteVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF, device.Bus, romFile)
|
return q.qmpMonitorCh.qmp.ExecuteVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF, device.Bus, romFile)
|
||||||
case config.VFIODeviceMediatedType:
|
case config.VFIODeviceMediatedType:
|
||||||
|
if utils.IsAPVFIOMediatedDevice(device.SysfsDev) {
|
||||||
|
return q.qmpMonitorCh.qmp.ExecuteAPVFIOMediatedDeviceAdd(q.qmpMonitorCh.ctx, device.SysfsDev)
|
||||||
|
}
|
||||||
return q.qmpMonitorCh.qmp.ExecutePCIVFIOMediatedDeviceAdd(q.qmpMonitorCh.ctx, devID, device.SysfsDev, "", device.Bus, romFile)
|
return q.qmpMonitorCh.qmp.ExecutePCIVFIOMediatedDeviceAdd(q.qmpMonitorCh.ctx, devID, device.SysfsDev, "", device.Bus, romFile)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Incorrect VFIO device type found")
|
return fmt.Errorf("Incorrect VFIO device type found")
|
||||||
@ -1326,6 +1329,9 @@ func (q *qemu) hotplugVFIODevice(device *config.VFIODev, op operation) (err erro
|
|||||||
case config.VFIODeviceNormalType:
|
case config.VFIODeviceNormalType:
|
||||||
return q.qmpMonitorCh.qmp.ExecutePCIVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF, addr, bridge.ID, romFile)
|
return q.qmpMonitorCh.qmp.ExecutePCIVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF, addr, bridge.ID, romFile)
|
||||||
case config.VFIODeviceMediatedType:
|
case config.VFIODeviceMediatedType:
|
||||||
|
if utils.IsAPVFIOMediatedDevice(device.SysfsDev) {
|
||||||
|
return q.qmpMonitorCh.qmp.ExecuteAPVFIOMediatedDeviceAdd(q.qmpMonitorCh.ctx, device.SysfsDev)
|
||||||
|
}
|
||||||
return q.qmpMonitorCh.qmp.ExecutePCIVFIOMediatedDeviceAdd(q.qmpMonitorCh.ctx, devID, device.SysfsDev, addr, bridge.ID, romFile)
|
return q.qmpMonitorCh.qmp.ExecutePCIVFIOMediatedDeviceAdd(q.qmpMonitorCh.ctx, devID, device.SysfsDev, addr, bridge.ID, romFile)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Incorrect VFIO device type found")
|
return fmt.Errorf("Incorrect VFIO device type found")
|
||||||
|
@ -712,30 +712,34 @@ func (q *qemuArchBase) setIgnoreSharedMemoryMigrationCaps(ctx context.Context, q
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemuArchBase) addDeviceToBridge(ID string, t types.Type) (string, types.Bridge, error) {
|
func (q *qemuArchBase) addDeviceToBridge(ID string, t types.Type) (string, types.Bridge, error) {
|
||||||
|
addr, b, err := genericAddDeviceToBridge(q.Bridges, ID, t)
|
||||||
|
if err != nil {
|
||||||
|
return "", b, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%02x", addr), b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func genericAddDeviceToBridge(bridges []types.Bridge, ID string, t types.Type) (uint32, types.Bridge, error) {
|
||||||
var err error
|
var err error
|
||||||
var addr uint32
|
var addr uint32
|
||||||
|
|
||||||
if len(q.Bridges) == 0 {
|
if len(bridges) == 0 {
|
||||||
return "", types.Bridge{}, errors.New("failed to get available address from bridges")
|
return 0, types.Bridge{}, errors.New("failed to get available address from bridges")
|
||||||
}
|
}
|
||||||
|
|
||||||
// looking for an empty address in the bridges
|
// looking for an empty address in the bridges
|
||||||
for _, b := range q.Bridges {
|
for _, b := range bridges {
|
||||||
if t != b.Type {
|
if t != b.Type {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
addr, err = b.AddDevice(ID)
|
addr, err = b.AddDevice(ID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch t {
|
return addr, b, nil
|
||||||
case types.CCW:
|
|
||||||
return fmt.Sprintf("%04x", addr), b, nil
|
|
||||||
case types.PCI, types.PCIE:
|
|
||||||
return fmt.Sprintf("%02x", addr), b, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", types.Bridge{}, fmt.Errorf("no more bridge slots available")
|
return 0, types.Bridge{}, fmt.Errorf("no more bridge slots available")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemuArchBase) removeDeviceFromBridge(ID string) error {
|
func (q *qemuArchBase) removeDeviceFromBridge(ID string) error {
|
||||||
|
@ -269,3 +269,12 @@ func (q *qemuS390x) appendVSock(devices []govmmQemu.Device, vsock types.VSock) (
|
|||||||
func (q *qemuS390x) appendIOMMU(devices []govmmQemu.Device) ([]govmmQemu.Device, error) {
|
func (q *qemuS390x) appendIOMMU(devices []govmmQemu.Device) ([]govmmQemu.Device, error) {
|
||||||
return devices, fmt.Errorf("S390x does not support appending a vIOMMU")
|
return devices, fmt.Errorf("S390x does not support appending a vIOMMU")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *qemuS390x) addDeviceToBridge(ID string, t types.Type) (string, types.Bridge, error) {
|
||||||
|
addr, b, err := genericAddDeviceToBridge(q.Bridges, ID, types.CCW)
|
||||||
|
if err != nil {
|
||||||
|
return "", b, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%04x", addr), b, nil
|
||||||
|
}
|
||||||
|
@ -93,6 +93,7 @@ const (
|
|||||||
procMountsFile = "/proc/mounts"
|
procMountsFile = "/proc/mounts"
|
||||||
|
|
||||||
fieldsPerLine = 6
|
fieldsPerLine = 6
|
||||||
|
vfioAPSysfsDir = "vfio_ap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -141,3 +142,15 @@ func GetDevicePathAndFsType(mountPoint string) (devicePath, fsType string, err e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsAPVFIOMediatedDevice decides whether a device is a VFIO-AP device
|
||||||
|
// by checking for the existence of "vfio_ap" in the path
|
||||||
|
func IsAPVFIOMediatedDevice(sysfsdev string) bool {
|
||||||
|
split := strings.Split(sysfsdev, string(os.PathSeparator))
|
||||||
|
for _, el := range split {
|
||||||
|
if el == vfioAPSysfsDir {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -49,3 +49,19 @@ func TestGetDevicePathAndFsTypeSuccessful(t *testing.T) {
|
|||||||
assert.Equal(path, "proc")
|
assert.Equal(path, "proc")
|
||||||
assert.Equal(fstype, "proc")
|
assert.Equal(fstype, "proc")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsAPVFIOMediatedDeviceFalse(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
// Should be false for a PCI device
|
||||||
|
isAPMdev := IsAPVFIOMediatedDevice("/sys/bus/pci/devices/0000:00:02.0/a297db4a-f4c2-11e6-90f6-d3b88d6c9525")
|
||||||
|
assert.False(isAPMdev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsAPVFIOMediatedDeviceTrue(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
// Typical AP sysfsdev
|
||||||
|
isAPMdev := IsAPVFIOMediatedDevice("/sys/devices/vfio_ap/matrix/a297db4a-f4c2-11e6-90f6-d3b88d6c9525")
|
||||||
|
assert.True(isAPMdev)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user