diff --git a/virtcontainers/device.go b/virtcontainers/device.go index ffe0be486e..e9943bdb2a 100644 --- a/virtcontainers/device.go +++ b/virtcontainers/device.go @@ -132,7 +132,13 @@ func (device *VFIODevice) attach(h hypervisor, c *Container) error { device.BDF = deviceBDF - if err := h.addDevice(*device, vfioDev); err != nil { + randBytes, err := generateRandomBytes(8) + if err != nil { + return err + } + device.DeviceInfo.ID = hex.EncodeToString(randBytes) + + if err := h.hotplugAddDevice(*device, vfioDev); err != nil { deviceLogger().WithError(err).Error("Failed to add device") return err } diff --git a/virtcontainers/qemu.go b/virtcontainers/qemu.go index c7025230a2..824950fdd3 100644 --- a/virtcontainers/qemu.go +++ b/virtcontainers/qemu.go @@ -638,6 +638,44 @@ func (q *qemu) hotplugBlockDevice(drive Drive, op operation) error { return nil } +func (q *qemu) hotplugVFIODevice(device VFIODevice, op operation) error { + defer func(qemu *qemu) { + if q.qmpMonitorCh.qmp != nil { + q.qmpMonitorCh.qmp.Shutdown() + } + }(q) + + qmp, err := q.qmpSetup() + if err != nil { + return err + } + + q.qmpMonitorCh.qmp = qmp + + devID := "vfio-" + device.DeviceInfo.ID + + if op == addDevice { + addr, bus, err := q.addDeviceToBridge(devID) + if err != nil { + return err + } + + if err := q.qmpMonitorCh.qmp.ExecutePCIVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF, addr, bus); err != nil { + return err + } + } else { + if err := q.removeDeviceFromBridge(devID); err != nil { + return err + } + + if err := q.qmpMonitorCh.qmp.ExecuteDeviceDel(q.qmpMonitorCh.ctx, devID); err != nil { + return err + } + } + + return nil +} + func (q *qemu) hotplugDevice(devInfo interface{}, devType deviceType, op operation) error { switch devType { case blockDev: @@ -646,6 +684,9 @@ func (q *qemu) hotplugDevice(devInfo interface{}, devType deviceType, op operati case cpuDev: vcpus := devInfo.(uint32) return q.hotplugCPUs(vcpus, op) + case vfioDev: + device := devInfo.(VFIODevice) + return q.hotplugVFIODevice(device, op) default: return fmt.Errorf("cannot hotplug device: unsupported device type '%v'", devType) }