From 6f0873a2c34efa291deb8113ea2dd2de9b15e567 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Tue, 16 Oct 2018 18:26:56 -0700 Subject: [PATCH] vendor: Update govmm vendoring Shortlog: 9c819db qemu: Fix virtio-net-pci QMP command 7fdfc6a qemu: Add support for romfile option e74de3c Update guidelines on security issue reporting ec83abe qemu: Add virtio-balloon device suppport. 4697078 qemu: Show full path to qemu binary at launch time Signed-off-by: Sebastien Boeuf --- Gopkg.lock | 4 +- Gopkg.toml | 2 +- vendor/github.com/intel/govmm/qemu/qemu.go | 239 +++++++++++++++++---- vendor/github.com/intel/govmm/qemu/qmp.go | 77 +++++-- 4 files changed, 262 insertions(+), 60 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index c396dcd6e7..8b460be24d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -123,11 +123,11 @@ revision = "3520598351bb3500a49ae9563f5539666ae0a27c" [[projects]] - digest = "1:c63a5bf4f3fd94ae838ce53e3492c0a467c40d09cada9301d228df7164ba4e55" + digest = "1:6cfbc8646c1b7746e366eacb17a6f6f97f28beabd87eebffe961447419eb60bf" name = "github.com/intel/govmm" packages = ["qemu"] pruneopts = "NUT" - revision = "f03df80fc3dc52f65ed6c7d12806279b44185d32" + revision = "e82e8498c5a214b24ac75e0a05ace556bf91a9ab" [[projects]] digest = "1:672470f31bc4e50f9ba09a1af7ab6035bf8b1452db64dfd79b1a22614bb30710" diff --git a/Gopkg.toml b/Gopkg.toml index 9329c02b20..33f4c84bc1 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -52,7 +52,7 @@ [[constraint]] name = "github.com/intel/govmm" - revision = "f03df80fc3dc52f65ed6c7d12806279b44185d32" + revision = "e82e8498c5a214b24ac75e0a05ace556bf91a9ab" [[constraint]] name = "github.com/kata-containers/agent" diff --git a/vendor/github.com/intel/govmm/qemu/qemu.go b/vendor/github.com/intel/govmm/qemu/qemu.go index a44cc63f4a..f26f093922 100644 --- a/vendor/github.com/intel/govmm/qemu/qemu.go +++ b/vendor/github.com/intel/govmm/qemu/qemu.go @@ -88,8 +88,55 @@ const ( // VirtioRng is the paravirtualized RNG device driver. VirtioRng DeviceDriver = "virtio-rng" + + // VirtioBalloon is the memory balloon device driver. + VirtioBalloon DeviceDriver = "virtio-balloon" + + //VhostUserSCSI represents a SCSI vhostuser device type. + VhostUserSCSI DeviceDriver = "vhost-user-scsi-pci" + + //VhostUserNet represents a net vhostuser device type. + VhostUserNet DeviceDriver = "virtio-net-pci" + + //VhostUserBlk represents a block vhostuser device type. + VhostUserBlk DeviceDriver = "vhost-user-blk-pci" + + // VfioPCI represent a VFIO device type. + VfioPCI DeviceDriver = "vfio-pci" + + // VirtioScsiPCI represents a SCSI device type. + VirtioScsiPCI DeviceDriver = "virtio-scsi-pci" + + // PCIBridgeDriver represents a PCI bridge device type. + PCIBridgeDriver DeviceDriver = "pci-bridge" + + // PCIePCIBridgeDriver represents a PCIe to PCI bridge device type. + PCIePCIBridgeDriver DeviceDriver = "pcie-pci-bridge" ) +// isVirtioPCI is a map indicating if a DeviceDriver is considered as a +// virtio PCI device, which is helpful to determine if the option "romfile" +// applies or not to this specific device. +var isVirtioPCI = map[DeviceDriver]bool{ + NVDIMM: false, + Virtio9P: true, + VirtioNet: true, + VirtioNetPCI: true, + VirtioSerial: true, + VirtioBlock: true, + Console: false, + VirtioSerialPort: false, + VHostVSockPCI: true, + VirtioRng: true, + VirtioBalloon: true, + VhostUserSCSI: true, + VhostUserBlk: true, + VfioPCI: true, + VirtioScsiPCI: true, + PCIBridgeDriver: true, + PCIePCIBridgeDriver: true, +} + // ObjectType is a string representing a qemu object type. type ObjectType string @@ -216,6 +263,9 @@ type FSDevice struct { // DisableModern prevents qemu from relying on fast MMIO. DisableModern bool + + // ROMFile specifies the ROM file being used for this device. + ROMFile string } // Valid returns true if the FSDevice structure is valid and complete. @@ -239,6 +289,9 @@ func (fsdev FSDevice) QemuParams(config *Config) []string { } deviceParams = append(deviceParams, fmt.Sprintf(",fsdev=%s", fsdev.ID)) deviceParams = append(deviceParams, fmt.Sprintf(",mount_tag=%s", fsdev.MountTag)) + if isVirtioPCI[fsdev.Driver] { + deviceParams = append(deviceParams, fmt.Sprintf(",romfile=%s", fsdev.ROMFile)) + } fsParams = append(fsParams, string(fsdev.FSDriver)) fsParams = append(fsParams, fmt.Sprintf(",id=%s", fsdev.ID)) @@ -296,6 +349,9 @@ type CharDevice struct { // DisableModern prevents qemu from relying on fast MMIO. DisableModern bool + + // ROMFile specifies the ROM file being used for this device. + ROMFile string } // Valid returns true if the CharDevice structure is valid and complete. @@ -325,6 +381,9 @@ func (cdev CharDevice) QemuParams(config *Config) []string { if cdev.Name != "" { deviceParams = append(deviceParams, fmt.Sprintf(",name=%s", cdev.Name)) } + if isVirtioPCI[cdev.Driver] { + deviceParams = append(deviceParams, fmt.Sprintf(",romfile=%s", cdev.ROMFile)) + } cdevParams = append(cdevParams, string(cdev.Backend)) cdevParams = append(cdevParams, fmt.Sprintf(",id=%s", cdev.ID)) @@ -388,7 +447,7 @@ func (n NetDeviceType) QemuNetdevParam() string { } // QemuDeviceParam converts to the QEMU -device parameter notation -func (n NetDeviceType) QemuDeviceParam() string { +func (n NetDeviceType) QemuDeviceParam() DeviceDriver { switch n { case TAP: return "virtio-net-pci" @@ -447,6 +506,9 @@ type NetDevice struct { // DisableModern prevents qemu from relying on fast MMIO. DisableModern bool + + // ROMFile specifies the ROM file being used for this device. + ROMFile string } // Valid returns true if the NetDevice structure is valid and complete. @@ -473,8 +535,7 @@ func (netdev NetDevice) QemuDeviceParams(config *Config) []string { return nil } - deviceParams = append(deviceParams, "driver=") - deviceParams = append(deviceParams, netdev.Type.QemuDeviceParam()) + deviceParams = append(deviceParams, fmt.Sprintf("driver=%s", netdev.Type.QemuDeviceParam())) deviceParams = append(deviceParams, fmt.Sprintf(",netdev=%s", netdev.ID)) deviceParams = append(deviceParams, fmt.Sprintf(",mac=%s", netdev.MACAddress)) @@ -510,6 +571,10 @@ func (netdev NetDevice) QemuDeviceParams(config *Config) []string { deviceParams = append(deviceParams, fmt.Sprintf(",vectors=%d", vectors)) } + if isVirtioPCI[netdev.Driver] { + deviceParams = append(deviceParams, fmt.Sprintf(",romfile=%s", netdev.ROMFile)) + } + return deviceParams } @@ -598,6 +663,9 @@ type SerialDevice struct { // DisableModern prevents qemu from relying on fast MMIO. DisableModern bool + + // ROMFile specifies the ROM file being used for this device. + ROMFile string } // Valid returns true if the SerialDevice structure is valid and complete. @@ -619,6 +687,9 @@ func (dev SerialDevice) QemuParams(config *Config) []string { deviceParams = append(deviceParams, ",disable-modern=true") } deviceParams = append(deviceParams, fmt.Sprintf(",id=%s", dev.ID)) + if isVirtioPCI[dev.Driver] { + deviceParams = append(deviceParams, fmt.Sprintf(",romfile=%s", dev.ROMFile)) + } qemuParams = append(qemuParams, "-device") qemuParams = append(qemuParams, strings.Join(deviceParams, "")) @@ -669,6 +740,9 @@ type BlockDevice struct { // DisableModern prevents qemu from relying on fast MMIO. DisableModern bool + + // ROMFile specifies the ROM file being used for this device. + ROMFile string } // Valid returns true if the BlockDevice structure is valid and complete. @@ -699,6 +773,10 @@ func (blkdev BlockDevice) QemuParams(config *Config) []string { deviceParams = append(deviceParams, ",config-wce=off") } + if isVirtioPCI[blkdev.Driver] { + deviceParams = append(deviceParams, fmt.Sprintf(",romfile=%s", blkdev.ROMFile)) + } + blkParams = append(blkParams, fmt.Sprintf("id=%s", blkdev.ID)) blkParams = append(blkParams, fmt.Sprintf(",file=%s", blkdev.File)) blkParams = append(blkParams, fmt.Sprintf(",aio=%s", blkdev.AIO)) @@ -714,18 +792,6 @@ func (blkdev BlockDevice) QemuParams(config *Config) []string { return qemuParams } -// VhostUserDeviceType is a qemu vhost-user device type. -type VhostUserDeviceType string - -const ( - //VhostUserSCSI represents a SCSI vhostuser device type - VhostUserSCSI = "vhost-user-scsi-pci" - //VhostUserNet represents a net vhostuser device type - VhostUserNet = "virtio-net-pci" - //VhostUserBlk represents a block vhostuser device type - VhostUserBlk = "vhost-user-blk-pci" -) - // VhostUserDevice represents a qemu vhost-user device meant to be passed // in to the guest type VhostUserDevice struct { @@ -733,7 +799,10 @@ type VhostUserDevice struct { CharDevID string TypeDevID string //variable QEMU parameter based on value of VhostUserType Address string //used for MAC address in net case - VhostUserType VhostUserDeviceType + VhostUserType DeviceDriver + + // ROMFile specifies the ROM file being used for this device. + ROMFile string } // Valid returns true if there is a valid structure defined for VhostUserDevice @@ -766,6 +835,7 @@ func (vhostuserDev VhostUserDevice) QemuParams(config *Config) []string { var charParams []string var netParams []string var devParams []string + var driver DeviceDriver charParams = append(charParams, "socket") charParams = append(charParams, fmt.Sprintf("id=%s", vhostuserDev.CharDevID)) @@ -774,20 +844,23 @@ func (vhostuserDev VhostUserDevice) QemuParams(config *Config) []string { switch vhostuserDev.VhostUserType { // if network based vhost device: case VhostUserNet: + driver = VhostUserNet netParams = append(netParams, "type=vhost-user") netParams = append(netParams, fmt.Sprintf("id=%s", vhostuserDev.TypeDevID)) netParams = append(netParams, fmt.Sprintf("chardev=%s", vhostuserDev.CharDevID)) netParams = append(netParams, "vhostforce") - devParams = append(devParams, VhostUserNet) + devParams = append(devParams, string(driver)) devParams = append(devParams, fmt.Sprintf("netdev=%s", vhostuserDev.TypeDevID)) devParams = append(devParams, fmt.Sprintf("mac=%s", vhostuserDev.Address)) case VhostUserSCSI: - devParams = append(devParams, VhostUserSCSI) + driver = VhostUserSCSI + devParams = append(devParams, string(driver)) devParams = append(devParams, fmt.Sprintf("id=%s", vhostuserDev.TypeDevID)) devParams = append(devParams, fmt.Sprintf("chardev=%s", vhostuserDev.CharDevID)) case VhostUserBlk: - devParams = append(devParams, VhostUserBlk) + driver = VhostUserBlk + devParams = append(devParams, string(driver)) devParams = append(devParams, "logical_block_size=4096") devParams = append(devParams, "size=512M") devParams = append(devParams, fmt.Sprintf("chardev=%s", vhostuserDev.CharDevID)) @@ -795,6 +868,10 @@ func (vhostuserDev VhostUserDevice) QemuParams(config *Config) []string { return nil } + if isVirtioPCI[driver] { + devParams = append(devParams, fmt.Sprintf("romfile=%s", vhostuserDev.ROMFile)) + } + qemuParams = append(qemuParams, "-chardev") qemuParams = append(qemuParams, strings.Join(charParams, ",")) @@ -813,6 +890,9 @@ func (vhostuserDev VhostUserDevice) QemuParams(config *Config) []string { type VFIODevice struct { // Bus-Device-Function of device BDF string + + // ROMFile specifies the ROM file being used for this device. + ROMFile string } // Valid returns true if the VFIODevice structure is valid and complete. @@ -827,10 +907,17 @@ func (vfioDev VFIODevice) Valid() bool { // QemuParams returns the qemu parameters built out of this vfio device. func (vfioDev VFIODevice) QemuParams(config *Config) []string { var qemuParams []string + var deviceParams []string + + driver := VfioPCI + + deviceParams = append(deviceParams, fmt.Sprintf("%s,host=%s", driver, vfioDev.BDF)) + if isVirtioPCI[driver] { + deviceParams = append(deviceParams, fmt.Sprintf(",romfile=%s", vfioDev.ROMFile)) + } - deviceParam := fmt.Sprintf("vfio-pci,host=%s", vfioDev.BDF) qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, deviceParam) + qemuParams = append(qemuParams, strings.Join(deviceParams, "")) return qemuParams } @@ -850,6 +937,9 @@ type SCSIController struct { // IOThread is the IO thread on which IO will be handled IOThread string + + // ROMFile specifies the ROM file being used for this device. + ROMFile string } // Valid returns true if the SCSIController structure is valid and complete. @@ -866,7 +956,8 @@ func (scsiCon SCSIController) QemuParams(config *Config) []string { var qemuParams []string var devParams []string - devParams = append(devParams, fmt.Sprintf("virtio-scsi-pci,id=%s", scsiCon.ID)) + driver := VirtioScsiPCI + devParams = append(devParams, fmt.Sprintf("%s,id=%s", driver, scsiCon.ID)) if scsiCon.Bus != "" { devParams = append(devParams, fmt.Sprintf("bus=%s", scsiCon.Bus)) } @@ -879,6 +970,9 @@ func (scsiCon SCSIController) QemuParams(config *Config) []string { if scsiCon.IOThread != "" { devParams = append(devParams, fmt.Sprintf("iothread=%s", scsiCon.IOThread)) } + if isVirtioPCI[driver] { + devParams = append(devParams, fmt.Sprintf("romfile=%s", scsiCon.ROMFile)) + } qemuParams = append(qemuParams, "-device") qemuParams = append(qemuParams, strings.Join(devParams, ",")) @@ -916,6 +1010,9 @@ type BridgeDevice struct { // PCI Slot Addr string + + // ROMFile specifies the ROM file being used for this device. + ROMFile string } // Valid returns true if the BridgeDevice structure is valid and complete. @@ -938,28 +1035,35 @@ func (bridgeDev BridgeDevice) Valid() bool { // QemuParams returns the qemu parameters built out of this bridge device. func (bridgeDev BridgeDevice) QemuParams(config *Config) []string { var qemuParams []string - var deviceParam string + var deviceParam []string + var driver DeviceDriver switch bridgeDev.Type { case PCIEBridge: - deviceParam = fmt.Sprintf("pcie-pci-bridge,bus=%s,id=%s", bridgeDev.Bus, bridgeDev.ID) + driver = PCIePCIBridgeDriver + deviceParam = append(deviceParam, fmt.Sprintf("%s,bus=%s,id=%s", driver, bridgeDev.Bus, bridgeDev.ID)) default: + driver = PCIBridgeDriver shpc := "off" if bridgeDev.SHPC { shpc = "on" } - deviceParam = fmt.Sprintf("pci-bridge,bus=%s,id=%s,chassis_nr=%d,shpc=%s", bridgeDev.Bus, bridgeDev.ID, bridgeDev.Chassis, shpc) + deviceParam = append(deviceParam, fmt.Sprintf("%s,bus=%s,id=%s,chassis_nr=%d,shpc=%s", driver, bridgeDev.Bus, bridgeDev.ID, bridgeDev.Chassis, shpc)) } if bridgeDev.Addr != "" { addr, err := strconv.Atoi(bridgeDev.Addr) if err == nil && addr >= 0 { - deviceParam += fmt.Sprintf(",addr=%x", addr) + deviceParam = append(deviceParam, fmt.Sprintf(",addr=%x", addr)) } } + if isVirtioPCI[driver] { + deviceParam = append(deviceParam, fmt.Sprintf(",romfile=%s", bridgeDev.ROMFile)) + } + qemuParams = append(qemuParams, "-device") - qemuParams = append(qemuParams, deviceParam) + qemuParams = append(qemuParams, strings.Join(deviceParam, "")) return qemuParams } @@ -975,16 +1079,14 @@ type VSOCKDevice struct { // DisableModern prevents qemu from relying on fast MMIO. DisableModern bool + + // ROMFile specifies the ROM file being used for this device. + ROMFile string } const ( // MinimalGuestCID is the smallest valid context ID for a guest. MinimalGuestCID uint32 = 3 -) - -const ( - // VhostVSOCKPCI is the VSOCK vhost device type. - VhostVSOCKPCI = "vhost-vsock-pci" // VSOCKGuestCID is the VSOCK guest CID parameter. VSOCKGuestCID = "guest-cid" @@ -1004,7 +1106,8 @@ func (vsock VSOCKDevice) QemuParams(config *Config) []string { var deviceParams []string var qemuParams []string - deviceParams = append(deviceParams, fmt.Sprintf("%s", VhostVSOCKPCI)) + driver := VHostVSockPCI + deviceParams = append(deviceParams, fmt.Sprintf("%s", driver)) if vsock.DisableModern { deviceParams = append(deviceParams, ",disable-modern=true") } @@ -1015,6 +1118,10 @@ func (vsock VSOCKDevice) QemuParams(config *Config) []string { deviceParams = append(deviceParams, fmt.Sprintf(",id=%s", vsock.ID)) deviceParams = append(deviceParams, fmt.Sprintf(",%s=%d", VSOCKGuestCID, vsock.ContextID)) + if isVirtioPCI[driver] { + deviceParams = append(deviceParams, fmt.Sprintf(",romfile=%s", vsock.ROMFile)) + } + qemuParams = append(qemuParams, "-device") qemuParams = append(qemuParams, strings.Join(deviceParams, "")) @@ -1031,6 +1138,8 @@ type RngDevice struct { MaxBytes uint // Period is duration of a read period in seconds Period uint + // ROMFile specifies the ROM file being used for this device. + ROMFile string } // Valid returns true if the RngDevice structure is valid and complete. @@ -1051,12 +1160,17 @@ func (v RngDevice) QemuParams(_ *Config) []string { //-device virtio-rng-pci,rng=rng0,max-bytes=1024,period=1000 var deviceParams []string + driver := VirtioRng objectParams = append(objectParams, "rng-random") objectParams = append(objectParams, "id="+v.ID) - deviceParams = append(deviceParams, string(VirtioRng)) + deviceParams = append(deviceParams, string(driver)) deviceParams = append(deviceParams, "rng="+v.ID) + if isVirtioPCI[driver] { + deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", v.ROMFile)) + } + if v.Filename != "" { objectParams = append(objectParams, "filename="+v.Filename) } @@ -1078,6 +1192,59 @@ func (v RngDevice) QemuParams(_ *Config) []string { return qemuParams } +// BalloonDevice represents a memory balloon device. +type BalloonDevice struct { + DeflateOnOOM bool + DisableModern bool + ID string + + // ROMFile specifies the ROM file being used for this device. + ROMFile string +} + +// QemuParams returns the qemu parameters built out of the BalloonDevice. +func (b BalloonDevice) QemuParams(_ *Config) []string { + var qemuParams []string + var deviceParams []string + + driver := VirtioBalloon + deviceParams = append(deviceParams, string(driver)) + + if b.ID != "" { + deviceParams = append(deviceParams, "id="+b.ID) + } + + if isVirtioPCI[driver] { + deviceParams = append(deviceParams, fmt.Sprintf("romfile=%s", b.ROMFile)) + } + + if b.DeflateOnOOM { + deviceParams = append(deviceParams, "deflate-on-oom=on") + } else { + deviceParams = append(deviceParams, "deflate-on-oom=off") + } + + if b.DisableModern { + deviceParams = append(deviceParams, "disable-modern=on") + } else { + deviceParams = append(deviceParams, "disable-modern=off") + } + + qemuParams = append(qemuParams, "-device") + qemuParams = append(qemuParams, strings.Join(deviceParams, ",")) + + return qemuParams +} + +// Valid returns true if the balloonDevice structure is valid and complete. +func (b BalloonDevice) Valid() bool { + if b.ID == "" { + return false + } + + return true +} + // RTCBaseType is the qemu RTC base time type. type RTCBaseType string @@ -1740,11 +1907,11 @@ func LaunchCustomQemu(ctx context.Context, path string, params []string, fds []* var stderr bytes.Buffer cmd.Stderr = &stderr - logger.Infof("launching qemu with: %v", params) + logger.Infof("launching %s with: %v", path, params) err := cmd.Run() if err != nil { - logger.Errorf("Unable to launch qemu: %v", err) + logger.Errorf("Unable to launch %s: %v", path, err) errStr = stderr.String() logger.Errorf("%s", errStr) } diff --git a/vendor/github.com/intel/govmm/qemu/qmp.go b/vendor/github.com/intel/govmm/qemu/qmp.go index 58cd76709c..43daed369d 100644 --- a/vendor/github.com/intel/govmm/qemu/qmp.go +++ b/vendor/github.com/intel/govmm/qemu/qmp.go @@ -756,7 +756,7 @@ func (q *QMP) ExecuteBlockdevAdd(ctx context.Context, device, blockdevID string) // add. Both strings must be valid QMP identifiers. driver is the name of the // driver,e.g., virtio-blk-pci, and bus is the name of the bus. bus is optional. // shared denotes if the drive can be shared allowing it to be passed more than once. -func (q *QMP) ExecuteDeviceAdd(ctx context.Context, blockdevID, devID, driver, bus string, shared bool) error { +func (q *QMP) ExecuteDeviceAdd(ctx context.Context, blockdevID, devID, driver, bus, romfile string, shared bool) error { args := map[string]interface{}{ "id": devID, "driver": driver, @@ -768,6 +768,10 @@ func (q *QMP) ExecuteDeviceAdd(ctx context.Context, blockdevID, devID, driver, b if shared && (q.version.Major > 2 || (q.version.Major == 2 && q.version.Minor >= 10)) { args["share-rw"] = "on" } + if isVirtioPCI[DeviceDriver(driver)] { + args["romfile"] = romfile + } + return q.executeCommand(ctx, "device_add", args, nil) } @@ -779,7 +783,7 @@ func (q *QMP) ExecuteDeviceAdd(ctx context.Context, blockdevID, devID, driver, b // scsiID is the SCSI id, lun is logical unit number. scsiID and lun are optional, a negative value // for scsiID and lun is ignored. shared denotes if the drive can be shared allowing it // to be passed more than once. -func (q *QMP) ExecuteSCSIDeviceAdd(ctx context.Context, blockdevID, devID, driver, bus string, scsiID, lun int, shared bool) error { +func (q *QMP) ExecuteSCSIDeviceAdd(ctx context.Context, blockdevID, devID, driver, bus, romfile string, scsiID, lun int, shared bool) error { // TBD: Add drivers for scsi passthrough like scsi-generic and scsi-block drivers := []string{"scsi-hd", "scsi-cd", "scsi-disk"} @@ -810,6 +814,9 @@ func (q *QMP) ExecuteSCSIDeviceAdd(ctx context.Context, blockdevID, devID, drive if shared && (q.version.Major > 2 || (q.version.Major == 2 && q.version.Minor >= 10)) { args["share-rw"] = "on" } + if isVirtioPCI[DeviceDriver(driver)] { + args["romfile"] = romfile + } return q.executeCommand(ctx, "device_add", args, nil) } @@ -901,18 +908,25 @@ func (q *QMP) ExecuteNetdevDel(ctx context.Context, netdevID string) error { // using the device_add command. devID is the id of the device to add. // Must be valid QMP identifier. netdevID is the id of nic added by previous netdev_add. // queues is the number of queues of a nic. -func (q *QMP) ExecuteNetPCIDeviceAdd(ctx context.Context, netdevID, devID, macAddr, addr, bus string, queues int) error { +func (q *QMP) ExecuteNetPCIDeviceAdd(ctx context.Context, netdevID, devID, macAddr, addr, bus, romfile string, queues int) error { args := map[string]interface{}{ - "id": devID, - "driver": VirtioNetPCI, - "netdev": netdevID, - "mac": macAddr, - "addr": addr, + "id": devID, + "driver": VirtioNetPCI, + "romfile": romfile, } if bus != "" { args["bus"] = bus } + if addr != "" { + args["addr"] = addr + } + if macAddr != "" { + args["mac"] = macAddr + } + if netdevID != "" { + args["netdev"] = netdevID + } if queues > 0 { // (2N+2 vectors, N for tx queues, N for rx queues, 1 for config, and one for possible control vq) @@ -950,7 +964,7 @@ func (q *QMP) ExecuteDeviceDel(ctx context.Context, devID string) error { // to hot plug PCI devices on PCI(E) bridges, unlike ExecuteDeviceAdd this function receive the // device address on its parent bus. bus is optional. shared denotes if the drive can be shared // allowing it to be passed more than once. -func (q *QMP) ExecutePCIDeviceAdd(ctx context.Context, blockdevID, devID, driver, addr, bus string, shared bool) error { +func (q *QMP) ExecutePCIDeviceAdd(ctx context.Context, blockdevID, devID, driver, addr, bus, romfile string, shared bool) error { args := map[string]interface{}{ "id": devID, "driver": driver, @@ -963,6 +977,9 @@ func (q *QMP) ExecutePCIDeviceAdd(ctx context.Context, blockdevID, devID, driver if shared && (q.version.Major > 2 || (q.version.Major == 2 && q.version.Minor >= 10)) { args["share-rw"] = "on" } + if isVirtioPCI[DeviceDriver(driver)] { + args["romfile"] = romfile + } return q.executeCommand(ctx, "device_add", args, nil) } @@ -971,11 +988,12 @@ func (q *QMP) ExecutePCIDeviceAdd(ctx context.Context, blockdevID, devID, driver // using the device_add command. devID is the id of the device to add. // Must be valid QMP identifier. bdf is the PCI bus-device-function // of the pci device. -func (q *QMP) ExecuteVFIODeviceAdd(ctx context.Context, devID, bdf string) error { +func (q *QMP) ExecuteVFIODeviceAdd(ctx context.Context, devID, bdf, romfile string) error { args := map[string]interface{}{ - "id": devID, - "driver": "vfio-pci", - "host": bdf, + "id": devID, + "driver": "vfio-pci", + "host": bdf, + "romfile": romfile, } return q.executeCommand(ctx, "device_add", args, nil) } @@ -985,12 +1003,13 @@ func (q *QMP) ExecuteVFIODeviceAdd(ctx context.Context, devID, bdf string) error // ExecuteVFIODeviceAdd this function receives the bus and the device address on its parent bus. // bus is optional. devID is the id of the device to add.Must be valid QMP identifier. bdf is the // PCI bus-device-function of the pci device. -func (q *QMP) ExecutePCIVFIODeviceAdd(ctx context.Context, devID, bdf, addr, bus string) error { +func (q *QMP) ExecutePCIVFIODeviceAdd(ctx context.Context, devID, bdf, addr, bus, romfile string) error { args := map[string]interface{}{ - "id": devID, - "driver": "vfio-pci", - "host": bdf, - "addr": addr, + "id": devID, + "driver": "vfio-pci", + "host": bdf, + "addr": addr, + "romfile": romfile, } if bus != "" { args["bus"] = bus @@ -1003,11 +1022,12 @@ func (q *QMP) ExecutePCIVFIODeviceAdd(ctx context.Context, devID, bdf, addr, bus // ExecuteVFIODeviceAdd this function receives the bus and the device address on its parent bus. // devID is the id of the device to add. Must be valid QMP identifier. sysfsdev is the VFIO mediated device. // Both bus and addr are optional. If they are both set to be empty, the system will pick up an empty slot on root bus. -func (q *QMP) ExecutePCIVFIOMediatedDeviceAdd(ctx context.Context, devID, sysfsdev, addr, bus string) error { +func (q *QMP) ExecutePCIVFIOMediatedDeviceAdd(ctx context.Context, devID, sysfsdev, addr, bus, romfile string) error { args := map[string]interface{}{ "id": devID, "driver": "vfio-pci", "sysfsdev": sysfsdev, + "romfile": romfile, } if bus != "" { args["bus"] = bus @@ -1022,7 +1042,7 @@ func (q *QMP) ExecutePCIVFIOMediatedDeviceAdd(ctx context.Context, devID, sysfsd // driver is the CPU model, cpuID must be a unique ID to identify the CPU, socketID is the socket number within // node/board the CPU belongs to, coreID is the core number within socket the CPU belongs to, threadID is the // thread number within core the CPU belongs to. -func (q *QMP) ExecuteCPUDeviceAdd(ctx context.Context, driver, cpuID, socketID, coreID, threadID string) error { +func (q *QMP) ExecuteCPUDeviceAdd(ctx context.Context, driver, cpuID, socketID, coreID, threadID, romfile string) error { args := map[string]interface{}{ "driver": driver, "id": cpuID, @@ -1030,6 +1050,11 @@ func (q *QMP) ExecuteCPUDeviceAdd(ctx context.Context, driver, cpuID, socketID, "core-id": coreID, "thread-id": threadID, } + + if isVirtioPCI[DeviceDriver(driver)] { + args["romfile"] = romfile + } + return q.executeCommand(ctx, "device_add", args, nil) } @@ -1178,14 +1203,24 @@ func (q *QMP) ExecHotplugMemory(ctx context.Context, qomtype, id, mempath string return err } +// ExecuteBalloon sets the size of the balloon, hence updates the memory +// allocated for the VM. +func (q *QMP) ExecuteBalloon(ctx context.Context, bytes uint64) error { + args := map[string]interface{}{ + "value": bytes, + } + return q.executeCommand(ctx, "balloon", args, nil) +} + // ExecutePCIVSockAdd adds a vhost-vsock-pci bus -func (q *QMP) ExecutePCIVSockAdd(ctx context.Context, id, guestCID, vhostfd, addr, bus string, disableModern bool) error { +func (q *QMP) ExecutePCIVSockAdd(ctx context.Context, id, guestCID, vhostfd, addr, bus, romfile string, disableModern bool) error { args := map[string]interface{}{ "driver": VHostVSockPCI, "id": id, "guest-cid": guestCID, "vhostfd": vhostfd, "addr": addr, + "romfile": romfile, } if bus != "" {