qemu: Allow disable-modern option from QMP

For devices that actually support the option disable-modern, this
current commit provides a proper flag to the caller. This will allow
for better support when used in nested environment as virtio-pci
devices should rely on virtio 0.9 instead of 1.0 due to a bug in
KVM.

Fixes #80

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2018-12-04 14:03:03 -08:00
parent 908b6aab14
commit f9b31c0f80
2 changed files with 38 additions and 8 deletions

View File

@ -810,7 +810,10 @@ func (q *QMP) ExecuteBlockdevAddWithCache(ctx context.Context, device, blockdevI
// add. Both strings must be valid QMP identifiers. driver is the name of the // 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. // 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. // 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, romfile string, shared bool) error { // disableModern indicates if virtio version 1.0 should be replaced by the
// former version 0.9, as there is a KVM bug that occurs when using virtio
// 1.0 in nested environments.
func (q *QMP) ExecuteDeviceAdd(ctx context.Context, blockdevID, devID, driver, bus, romfile string, shared, disableModern bool) error {
args := map[string]interface{}{ args := map[string]interface{}{
"id": devID, "id": devID,
"driver": driver, "driver": driver,
@ -824,6 +827,10 @@ func (q *QMP) ExecuteDeviceAdd(ctx context.Context, blockdevID, devID, driver, b
} }
if isVirtioPCI[DeviceDriver(driver)] { if isVirtioPCI[DeviceDriver(driver)] {
args["romfile"] = romfile args["romfile"] = romfile
if disableModern {
args["disable-modern"] = disableModern
}
} }
return q.executeCommand(ctx, "device_add", args, nil) return q.executeCommand(ctx, "device_add", args, nil)
@ -837,7 +844,10 @@ 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 // 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 // for scsiID and lun is ignored. shared denotes if the drive can be shared allowing it
// to be passed more than once. // to be passed more than once.
func (q *QMP) ExecuteSCSIDeviceAdd(ctx context.Context, blockdevID, devID, driver, bus, romfile string, scsiID, lun int, shared bool) error { // disableModern indicates if virtio version 1.0 should be replaced by the
// former version 0.9, as there is a KVM bug that occurs when using virtio
// 1.0 in nested environments.
func (q *QMP) ExecuteSCSIDeviceAdd(ctx context.Context, blockdevID, devID, driver, bus, romfile string, scsiID, lun int, shared, disableModern bool) error {
// TBD: Add drivers for scsi passthrough like scsi-generic and scsi-block // TBD: Add drivers for scsi passthrough like scsi-generic and scsi-block
drivers := []string{"scsi-hd", "scsi-cd", "scsi-disk"} drivers := []string{"scsi-hd", "scsi-cd", "scsi-disk"}
@ -870,6 +880,10 @@ func (q *QMP) ExecuteSCSIDeviceAdd(ctx context.Context, blockdevID, devID, drive
} }
if isVirtioPCI[DeviceDriver(driver)] { if isVirtioPCI[DeviceDriver(driver)] {
args["romfile"] = romfile args["romfile"] = romfile
if disableModern {
args["disable-modern"] = disableModern
}
} }
return q.executeCommand(ctx, "device_add", args, nil) return q.executeCommand(ctx, "device_add", args, nil)
@ -962,7 +976,10 @@ func (q *QMP) ExecuteNetdevDel(ctx context.Context, netdevID string) error {
// using the device_add command. devID is the id of the device to add. // 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. // 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. // queues is the number of queues of a nic.
func (q *QMP) ExecuteNetPCIDeviceAdd(ctx context.Context, netdevID, devID, macAddr, addr, bus, romfile string, queues int) error { // disableModern indicates if virtio version 1.0 should be replaced by the
// former version 0.9, as there is a KVM bug that occurs when using virtio
// 1.0 in nested environments.
func (q *QMP) ExecuteNetPCIDeviceAdd(ctx context.Context, netdevID, devID, macAddr, addr, bus, romfile string, queues int, disableModern bool) error {
args := map[string]interface{}{ args := map[string]interface{}{
"id": devID, "id": devID,
"driver": VirtioNetPCI, "driver": VirtioNetPCI,
@ -981,6 +998,9 @@ func (q *QMP) ExecuteNetPCIDeviceAdd(ctx context.Context, netdevID, devID, macAd
if netdevID != "" { if netdevID != "" {
args["netdev"] = netdevID args["netdev"] = netdevID
} }
if disableModern {
args["disable-modern"] = disableModern
}
if queues > 0 { if queues > 0 {
// (2N+2 vectors, N for tx queues, N for rx queues, 1 for config, and one for possible control vq) // (2N+2 vectors, N for tx queues, N for rx queues, 1 for config, and one for possible control vq)
@ -1038,7 +1058,10 @@ 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 // 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 // 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. // allowing it to be passed more than once.
func (q *QMP) ExecutePCIDeviceAdd(ctx context.Context, blockdevID, devID, driver, addr, bus, romfile string, shared bool) error { // disableModern indicates if virtio version 1.0 should be replaced by the
// former version 0.9, as there is a KVM bug that occurs when using virtio
// 1.0 in nested environments.
func (q *QMP) ExecutePCIDeviceAdd(ctx context.Context, blockdevID, devID, driver, addr, bus, romfile string, shared, disableModern bool) error {
args := map[string]interface{}{ args := map[string]interface{}{
"id": devID, "id": devID,
"driver": driver, "driver": driver,
@ -1053,6 +1076,10 @@ func (q *QMP) ExecutePCIDeviceAdd(ctx context.Context, blockdevID, devID, driver
} }
if isVirtioPCI[DeviceDriver(driver)] { if isVirtioPCI[DeviceDriver(driver)] {
args["romfile"] = romfile args["romfile"] = romfile
if disableModern {
args["disable-modern"] = disableModern
}
} }
return q.executeCommand(ctx, "device_add", args, nil) return q.executeCommand(ctx, "device_add", args, nil)
@ -1290,6 +1317,9 @@ func (q *QMP) ExecuteBalloon(ctx context.Context, bytes uint64) error {
} }
// ExecutePCIVSockAdd adds a vhost-vsock-pci bus // ExecutePCIVSockAdd adds a vhost-vsock-pci bus
// disableModern indicates if virtio version 1.0 should be replaced by the
// former version 0.9, as there is a KVM bug that occurs when using virtio
// 1.0 in nested environments.
func (q *QMP) ExecutePCIVSockAdd(ctx context.Context, id, guestCID, vhostfd, addr, bus, romfile 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{}{ args := map[string]interface{}{
"driver": VHostVSock, "driver": VHostVSock,

View File

@ -528,7 +528,7 @@ func TestQMPNetPCIDeviceAdd(t *testing.T) {
cfg := QMPConfig{Logger: qmpTestLogger{}} cfg := QMPConfig{Logger: qmpTestLogger{}}
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh) q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
checkVersion(t, connectedCh) checkVersion(t, connectedCh)
err := q.ExecuteNetPCIDeviceAdd(context.Background(), "br0", "virtio-0", "02:42:ac:11:00:02", "0x7", "", "", 8) err := q.ExecuteNetPCIDeviceAdd(context.Background(), "br0", "virtio-0", "02:42:ac:11:00:02", "0x7", "", "", 8, false)
if err != nil { if err != nil {
t.Fatalf("Unexpected error %v", err) t.Fatalf("Unexpected error %v", err)
} }
@ -569,7 +569,7 @@ func TestQMPDeviceAdd(t *testing.T) {
blockdevID := fmt.Sprintf("drive_%s", volumeUUID) blockdevID := fmt.Sprintf("drive_%s", volumeUUID)
devID := fmt.Sprintf("device_%s", volumeUUID) devID := fmt.Sprintf("device_%s", volumeUUID)
err := q.ExecuteDeviceAdd(context.Background(), blockdevID, devID, err := q.ExecuteDeviceAdd(context.Background(), blockdevID, devID,
"virtio-blk-pci", "", "", true) "virtio-blk-pci", "", "", true, false)
if err != nil { if err != nil {
t.Fatalf("Unexpected error %v", err) t.Fatalf("Unexpected error %v", err)
} }
@ -594,7 +594,7 @@ func TestQMPSCSIDeviceAdd(t *testing.T) {
blockdevID := fmt.Sprintf("drive_%s", volumeUUID) blockdevID := fmt.Sprintf("drive_%s", volumeUUID)
devID := fmt.Sprintf("device_%s", volumeUUID) devID := fmt.Sprintf("device_%s", volumeUUID)
err := q.ExecuteSCSIDeviceAdd(context.Background(), blockdevID, devID, err := q.ExecuteSCSIDeviceAdd(context.Background(), blockdevID, devID,
"scsi-hd", "scsi0.0", "", 1, 2, true) "scsi-hd", "scsi0.0", "", 1, 2, true, false)
if err != nil { if err != nil {
t.Fatalf("Unexpected error %v", err) t.Fatalf("Unexpected error %v", err)
} }
@ -1012,7 +1012,7 @@ func TestQMPPCIDeviceAdd(t *testing.T) {
blockdevID := fmt.Sprintf("drive_%s", volumeUUID) blockdevID := fmt.Sprintf("drive_%s", volumeUUID)
devID := fmt.Sprintf("device_%s", volumeUUID) devID := fmt.Sprintf("device_%s", volumeUUID)
err := q.ExecutePCIDeviceAdd(context.Background(), blockdevID, devID, err := q.ExecutePCIDeviceAdd(context.Background(), blockdevID, devID,
"virtio-blk-pci", "0x1", "", "", true) "virtio-blk-pci", "0x1", "", "", true, false)
if err != nil { if err != nil {
t.Fatalf("Unexpected error %v", err) t.Fatalf("Unexpected error %v", err)
} }