From 6f0873a2c34efa291deb8113ea2dd2de9b15e567 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Tue, 16 Oct 2018 18:26:56 -0700 Subject: [PATCH 1/2] 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 c396dcd6e..8b460be24 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 9329c02b2..33f4c84bc 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 a44cc63f4..f26f09392 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 58cd76709..43daed369 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 != "" { From 0ae5b142a6ae1199844a5b6d8e60b7cd5d21d06c Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Tue, 16 Oct 2018 18:27:28 -0700 Subject: [PATCH 2/2] qemu: Disable the default romfile used by virtio-pci As we try to make sure we don't pull unneeded dependency when using QEMU or NEMU as the hypervisor, and because SeaBIOS and OVMF firmware already handle what's done by the default efi-virtio.rom binary, this commit gets rid of this dependency by providing a default empty one. Fixes #812 Signed-off-by: Sebastien Boeuf --- virtcontainers/qemu.go | 21 +++++++++++++-------- virtcontainers/qemu_arch_base.go | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/virtcontainers/qemu.go b/virtcontainers/qemu.go index 00e5995be..a2ea92130 100644 --- a/virtcontainers/qemu.go +++ b/virtcontainers/qemu.go @@ -23,6 +23,11 @@ import ( "github.com/kata-containers/runtime/virtcontainers/utils" ) +// romFile is the file name of the ROM that can be used for virtio-pci devices. +// If this file name is empty, this means we expect the firmware used by Qemu, +// such as SeaBIOS or OVMF for instance, to handle this directly. +const romFile = "" + type qmpChannel struct { ctx context.Context path string @@ -744,7 +749,7 @@ func (q *qemu) hotplugBlockDevice(drive *config.BlockDrive, op operation) error // PCI address is in the format bridge-addr/device-addr eg. "03/02" drive.PCIAddr = fmt.Sprintf("%02x", bridge.Addr) + "/" + addr - if err = q.qmpMonitorCh.qmp.ExecutePCIDeviceAdd(q.qmpMonitorCh.ctx, drive.ID, devID, driver, addr, bridge.ID, true); err != nil { + if err = q.qmpMonitorCh.qmp.ExecutePCIDeviceAdd(q.qmpMonitorCh.ctx, drive.ID, devID, driver, addr, bridge.ID, romFile, true); err != nil { return err } } else { @@ -759,7 +764,7 @@ func (q *qemu) hotplugBlockDevice(drive *config.BlockDrive, op operation) error return err } - if err = q.qmpMonitorCh.qmp.ExecuteSCSIDeviceAdd(q.qmpMonitorCh.ctx, drive.ID, devID, driver, bus, scsiID, lun, true); err != nil { + if err = q.qmpMonitorCh.qmp.ExecuteSCSIDeviceAdd(q.qmpMonitorCh.ctx, drive.ID, devID, driver, bus, romFile, scsiID, lun, true); err != nil { return err } } @@ -797,9 +802,9 @@ func (q *qemu) hotplugVFIODevice(device *config.VFIODev, op operation) error { if q.state.HotplugVFIOOnRootBus { switch device.Type { case config.VFIODeviceNormalType: - return q.qmpMonitorCh.qmp.ExecuteVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF) + return q.qmpMonitorCh.qmp.ExecuteVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF, romFile) case config.VFIODeviceMediatedType: - return q.qmpMonitorCh.qmp.ExecutePCIVFIOMediatedDeviceAdd(q.qmpMonitorCh.ctx, devID, device.SysfsDev, "", "") + return q.qmpMonitorCh.qmp.ExecutePCIVFIOMediatedDeviceAdd(q.qmpMonitorCh.ctx, devID, device.SysfsDev, "", "", romFile) default: return fmt.Errorf("Incorrect VFIO device type found") } @@ -812,9 +817,9 @@ func (q *qemu) hotplugVFIODevice(device *config.VFIODev, op operation) error { switch device.Type { case config.VFIODeviceNormalType: - return q.qmpMonitorCh.qmp.ExecutePCIVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF, addr, bridge.ID) + return q.qmpMonitorCh.qmp.ExecutePCIVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF, addr, bridge.ID, romFile) case config.VFIODeviceMediatedType: - return q.qmpMonitorCh.qmp.ExecutePCIVFIOMediatedDeviceAdd(q.qmpMonitorCh.ctx, devID, device.SysfsDev, addr, bridge.ID) + return q.qmpMonitorCh.qmp.ExecutePCIVFIOMediatedDeviceAdd(q.qmpMonitorCh.ctx, devID, device.SysfsDev, addr, bridge.ID, romFile) default: return fmt.Errorf("Incorrect VFIO device type found") } @@ -882,7 +887,7 @@ func (q *qemu) hotplugNetDevice(drive *VethEndpoint, op operation) error { return err } drive.PCIAddr = fmt.Sprintf("%02x/%s", bridge.Addr, addr) - if err = q.qmpMonitorCh.qmp.ExecuteNetPCIDeviceAdd(q.qmpMonitorCh.ctx, drive.NetPair.Name, devID, drive.NetPair.TAPIface.HardAddr, addr, bridge.ID, int(q.config.NumVCPUs)); err != nil { + if err = q.qmpMonitorCh.qmp.ExecuteNetPCIDeviceAdd(q.qmpMonitorCh.ctx, drive.NetPair.Name, devID, drive.NetPair.TAPIface.HardAddr, addr, bridge.ID, romFile, int(q.config.NumVCPUs)); err != nil { return err } } else { @@ -1000,7 +1005,7 @@ func (q *qemu) hotplugAddCPUs(amount uint32) (uint32, error) { socketID := fmt.Sprintf("%d", hc.Properties.Socket) coreID := fmt.Sprintf("%d", hc.Properties.Core) threadID := fmt.Sprintf("%d", hc.Properties.Thread) - if err := q.qmpMonitorCh.qmp.ExecuteCPUDeviceAdd(q.qmpMonitorCh.ctx, driver, cpuID, socketID, coreID, threadID); err != nil { + if err := q.qmpMonitorCh.qmp.ExecuteCPUDeviceAdd(q.qmpMonitorCh.ctx, driver, cpuID, socketID, coreID, threadID, romFile); err != nil { // don't fail, let's try with other CPU continue } diff --git a/virtcontainers/qemu_arch_base.go b/virtcontainers/qemu_arch_base.go index f8e6a61f9..707afc95b 100644 --- a/virtcontainers/qemu_arch_base.go +++ b/virtcontainers/qemu_arch_base.go @@ -518,7 +518,7 @@ func (q *qemuArchBase) appendVhostUserDevice(devices []govmmQemu.Device, attr co case config.VhostUserBlk: } - qemuVhostUserDevice.VhostUserType = govmmQemu.VhostUserDeviceType(attr.Type) + qemuVhostUserDevice.VhostUserType = govmmQemu.DeviceDriver(attr.Type) qemuVhostUserDevice.SocketPath = attr.SocketPath qemuVhostUserDevice.CharDevID = utils.MakeNameID("char", attr.DevID, maxDevIDSize)