Skip to content

Commit

Permalink
qemu/qmp: preparation for s390x support
Browse files Browse the repository at this point in the history
This PR prepeares for the s390x support. It introduces:
 - a generalization of ccw and pci devices. The variable for the pci devices have
   been renamed by removing the Pci suffix. They have been moved to the
   qemu_arch_base.go
 - the mapping isVirtioPCI has been move to qemu_arch_base.go because in
   this way a different mapping can be added for other architecture (e.g
   s390x)
 - the functions QemuNetdevParam and QemuDeviceParam have been moved to
   qemu_arch_base.go. In this way, they could be reimplemented for other
   architecture for the case VHOSTUSER
 - a function disableModern has been introduced to check if the device is
   a pci device and then return the right parameters. In the case of ccw
   devices, they don't have the flag disable-modern
 - a function mqParameter has been introduced to return the right
   parameters for the mq case. The virtio-net-ccw doesn't have the
   vectors flag
 - in qemu_arch_base_test.go contains the test and strings that can be
   overwritten for other architectures (e.g s390). The devices names and
   the flags for the devices can be overwritten.
 - the string for the romfile has been replaced by a variable romfile
   that could be left empty if the devices doesn't support a romfile as
   for the ccw devices for s390.
 - clean-up: in the disable-moder=on/off have been changed to
   disable-moder=true/false. In the code there was a mixture of on/true
   off/false

Fixes: kata-containers#61

Co-authored-by: Yash D Jain <ydjainopensource@gmail.com>
Signed-off-by: Alice Frosi <afrosi@de.ibm.com>
  • Loading branch information
Alice Frosi and Yash D Jain committed Nov 21, 2018
1 parent e82e849 commit 9f6e0ea
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 225 deletions.
180 changes: 58 additions & 122 deletions qemu/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,9 @@ const (
// NVDIMM is the Non Volatile DIMM device driver.
NVDIMM DeviceDriver = "nvdimm"

// Virtio9P is the 9pfs device driver.
Virtio9P DeviceDriver = "virtio-9p-pci"

// VirtioNet is the virt-io networking device driver.
VirtioNet DeviceDriver = "virtio-net"

// VirtioNetPCI is the virt-io pci networking device driver.
VirtioNetPCI DeviceDriver = "virtio-net-pci"

// VirtioSerial is the serial device driver.
VirtioSerial DeviceDriver = "virtio-serial-pci"

// VirtioBlock is the block device driver.
VirtioBlock DeviceDriver = "virtio-blk"

Expand All @@ -83,9 +74,6 @@ const (
// VirtioSerialPort is the serial port device driver.
VirtioSerialPort DeviceDriver = "virtserialport"

// VHostVSockPCI is the vhost vsock pci driver.
VHostVSockPCI DeviceDriver = "vhost-vsock-pci"

// VirtioRng is the paravirtualized RNG device driver.
VirtioRng DeviceDriver = "virtio-rng"

Expand All @@ -101,40 +89,26 @@ const (
//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,
// disableModern returns the parameters with the disable-modern option.
// In case the device driver is not a PCI device and it doesn't have the option
// an empty string is returned.
func (driver DeviceDriver) disableModern(disable bool) string {
if !isVirtioPCI[driver] {
return ""
}

if disable {
return "disable-modern=true"
}

return "disable-modern=false"
}

// ObjectType is a string representing a qemu object type.
Expand Down Expand Up @@ -284,8 +258,8 @@ func (fsdev FSDevice) QemuParams(config *Config) []string {
var qemuParams []string

deviceParams = append(deviceParams, fmt.Sprintf("%s", fsdev.Driver))
if fsdev.DisableModern {
deviceParams = append(deviceParams, ",disable-modern=true")
if s := fsdev.Driver.disableModern(fsdev.DisableModern); s != "" {
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
}
deviceParams = append(deviceParams, fmt.Sprintf(",fsdev=%s", fsdev.ID))
deviceParams = append(deviceParams, fmt.Sprintf(",mount_tag=%s", fsdev.MountTag))
Expand Down Expand Up @@ -370,8 +344,8 @@ func (cdev CharDevice) QemuParams(config *Config) []string {
var qemuParams []string

deviceParams = append(deviceParams, fmt.Sprintf("%s", cdev.Driver))
if cdev.DisableModern {
deviceParams = append(deviceParams, ",disable-modern=true")
if s := cdev.Driver.disableModern(cdev.DisableModern); s != "" {
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
}
if cdev.Bus != "" {
deviceParams = append(deviceParams, fmt.Sprintf(",bus=%s", cdev.Bus))
Expand Down Expand Up @@ -402,9 +376,6 @@ func (cdev CharDevice) QemuParams(config *Config) []string {
return qemuParams
}

// NetDeviceType is a qemu networking device type.
type NetDeviceType string

const (
// TAP is a TAP networking device type.
TAP NetDeviceType = "tap"
Expand All @@ -425,48 +396,6 @@ const (
VHOSTUSER NetDeviceType = "vhostuser"
)

// QemuNetdevParam converts to the QEMU -netdev parameter notation
func (n NetDeviceType) QemuNetdevParam() string {
switch n {
case TAP:
return "tap"
case MACVTAP:
return "tap"
case IPVTAP:
return "tap"
case VETHTAP:
return "tap" // -netdev type=tap -device virtio-net-pci
case VFIO:
return "" // -device vfio-pci (no netdev)
case VHOSTUSER:
return "vhost-user" // -netdev type=vhost-user (no device)
default:
return ""

}
}

// QemuDeviceParam converts to the QEMU -device parameter notation
func (n NetDeviceType) QemuDeviceParam() DeviceDriver {
switch n {
case TAP:
return "virtio-net-pci"
case MACVTAP:
return "virtio-net-pci"
case IPVTAP:
return "virtio-net-pci"
case VETHTAP:
return "virtio-net-pci" // -netdev type=tap -device virtio-net-pci
case VFIO:
return "vfio-pci" // -device vfio-pci (no netdev)
case VHOSTUSER:
return "" // -netdev type=vhost-user (no device)
default:
return ""

}
}

// NetDevice represents a guest networking device
type NetDevice struct {
// Type is the netdev type (e.g. tap).
Expand Down Expand Up @@ -527,6 +456,29 @@ func (netdev NetDevice) Valid() bool {
}
}

// mqParameter returns the parameters for multi-queue driver. If the driver is a PCI device then the
// vector flag is required. If the driver is a CCW type than the vector flag is not implemented and only
// multi-queue option mq needs to be activated. See comment in libvirt code at
// https://github.com/libvirt/libvirt/blob/6e7e965dcd3d885739129b1454ce19e819b54c25/src/qemu/qemu_command.c#L3633
func (netdev NetDevice) mqParameter() string {
var p []string
p = append(p, ",mq=on")
if isVirtioPCI[netdev.Driver] {
// https://www.linux-kvm.org/page/Multiqueue
// -netdev tap,vhost=on,queues=N
// enable mq and specify msix vectors in qemu cmdline
// (2N+2 vectors, N for tx queues, N for rx queues, 1 for config, and one for possible control vq)
// -device virtio-net-pci,mq=on,vectors=2N+2...
// enable mq in guest by 'ethtool -L eth0 combined $queue_num'
// Clearlinux automatically sets up the queues properly
// The agent implementation should do this to ensure that it is
// always set
vectors := len(netdev.FDs)*2 + 2
p = append(p, fmt.Sprintf(",vectors=%d", vectors))
}
return strings.Join(p, "")
}

// QemuDeviceParams returns the -device parameters for this network device
func (netdev NetDevice) QemuDeviceParams(config *Config) []string {
var deviceParams []string
Expand All @@ -549,26 +501,12 @@ func (netdev NetDevice) QemuDeviceParams(config *Config) []string {
deviceParams = append(deviceParams, fmt.Sprintf(",addr=%x", addr))
}
}

if netdev.DisableModern {
deviceParams = append(deviceParams, ",disable-modern=true")
if s := netdev.Driver.disableModern(netdev.DisableModern); s != "" {
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
}

if len(netdev.FDs) > 0 {
// https://www.linux-kvm.org/page/Multiqueue
// -netdev tap,vhost=on,queues=N
// enable mq and specify msix vectors in qemu cmdline
// (2N+2 vectors, N for tx queues, N for rx queues, 1 for config, and one for possible control vq)
// -device virtio-net-pci,mq=on,vectors=2N+2...
// enable mq in guest by 'ethtool -L eth0 combined $queue_num'
// Clearlinux automatically sets up the queues properly
// The agent implementation should do this to ensure that it is
// always set
vectors := len(netdev.FDs)*2 + 2

// Note: We are appending to the device params here
deviceParams = append(deviceParams, ",mq=on")
deviceParams = append(deviceParams, fmt.Sprintf(",vectors=%d", vectors))
deviceParams = append(deviceParams, netdev.mqParameter())
}

if isVirtioPCI[netdev.Driver] {
Expand Down Expand Up @@ -683,8 +621,8 @@ func (dev SerialDevice) QemuParams(config *Config) []string {
var qemuParams []string

deviceParams = append(deviceParams, fmt.Sprintf("%s", dev.Driver))
if dev.DisableModern {
deviceParams = append(deviceParams, ",disable-modern=true")
if s := dev.Driver.disableModern(dev.DisableModern); s != "" {
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
}
deviceParams = append(deviceParams, fmt.Sprintf(",id=%s", dev.ID))
if isVirtioPCI[dev.Driver] {
Expand Down Expand Up @@ -761,8 +699,8 @@ func (blkdev BlockDevice) QemuParams(config *Config) []string {
var qemuParams []string

deviceParams = append(deviceParams, fmt.Sprintf("%s", blkdev.Driver))
if blkdev.DisableModern {
deviceParams = append(deviceParams, ",disable-modern=true")
if s := blkdev.Driver.disableModern(blkdev.DisableModern); s != "" {
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
}
deviceParams = append(deviceParams, fmt.Sprintf(",drive=%s", blkdev.ID))
if blkdev.SCSI == false {
Expand Down Expand Up @@ -909,7 +847,7 @@ func (vfioDev VFIODevice) QemuParams(config *Config) []string {
var qemuParams []string
var deviceParams []string

driver := VfioPCI
driver := Vfio

deviceParams = append(deviceParams, fmt.Sprintf("%s,host=%s", driver, vfioDev.BDF))
if isVirtioPCI[driver] {
Expand Down Expand Up @@ -956,16 +894,16 @@ func (scsiCon SCSIController) QemuParams(config *Config) []string {
var qemuParams []string
var devParams []string

driver := VirtioScsiPCI
driver := VirtioScsi
devParams = append(devParams, fmt.Sprintf("%s,id=%s", driver, scsiCon.ID))
if scsiCon.Bus != "" {
devParams = append(devParams, fmt.Sprintf("bus=%s", scsiCon.Bus))
}
if scsiCon.Addr != "" {
devParams = append(devParams, fmt.Sprintf("addr=%s", scsiCon.Addr))
}
if scsiCon.DisableModern {
devParams = append(devParams, fmt.Sprintf("disable-modern=true"))
if s := driver.disableModern(scsiCon.DisableModern); s != "" {
devParams = append(devParams, fmt.Sprintf("%s", s))
}
if scsiCon.IOThread != "" {
devParams = append(devParams, fmt.Sprintf("iothread=%s", scsiCon.IOThread))
Expand Down Expand Up @@ -1087,7 +1025,9 @@ type VSOCKDevice struct {
const (
// MinimalGuestCID is the smallest valid context ID for a guest.
MinimalGuestCID uint32 = 3
)

const (
// VSOCKGuestCID is the VSOCK guest CID parameter.
VSOCKGuestCID = "guest-cid"
)
Expand All @@ -1106,10 +1046,10 @@ func (vsock VSOCKDevice) QemuParams(config *Config) []string {
var deviceParams []string
var qemuParams []string

driver := VHostVSockPCI
driver := VHostVSock
deviceParams = append(deviceParams, fmt.Sprintf("%s", driver))
if vsock.DisableModern {
deviceParams = append(deviceParams, ",disable-modern=true")
if s := driver.disableModern(vsock.DisableModern); s != "" {
deviceParams = append(deviceParams, fmt.Sprintf(",%s", s))
}
if vsock.VHostFD != nil {
qemuFDs := config.appendFDs([]*os.File{vsock.VHostFD})
Expand Down Expand Up @@ -1223,13 +1163,9 @@ func (b BalloonDevice) QemuParams(_ *Config) []string {
} else {
deviceParams = append(deviceParams, "deflate-on-oom=off")
}

if b.DisableModern {
deviceParams = append(deviceParams, "disable-modern=on")
} else {
deviceParams = append(deviceParams, "disable-modern=off")
if s := driver.disableModern(b.DisableModern); s != "" {
deviceParams = append(deviceParams, fmt.Sprintf("%s", s))
}

qemuParams = append(qemuParams, "-device")
qemuParams = append(qemuParams, strings.Join(deviceParams, ","))

Expand Down

0 comments on commit 9f6e0ea

Please sign in to comment.