mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-05 22:05:47 +00:00
qemu: new functions to calculate/set device pciConnectFlags
The lowest level function of this trio (qemuDomainDeviceCalculatePCIConnectFlags()) aims to be the single authority for the virDomainPCIConnectFlags to use for any given device using a particular arch/machinetype/qemu-binary. qemuDomainFillDevicePCIConnectFlags() sets info->pciConnectFlags in a single device (unless it has no virDomainDeviceInfo, in which case it's a NOP). qemuDomainFillAllPCIConnectFlags() sets info->pciConnectFlags in all devices that have a virDomainDeviceInfo The latter two functions aren't called anywhere yet. This commit is just making them available. Later patches will replace all the current hodge-podge of flag settings with calls to this single authority.
This commit is contained in:
parent
50adb8a660
commit
bd776c2b09
@ -142,6 +142,11 @@ typedef struct _virDomainDeviceInfo {
|
|||||||
/* bootIndex is only used for disk, network interface, hostdev
|
/* bootIndex is only used for disk, network interface, hostdev
|
||||||
* and redirdev devices */
|
* and redirdev devices */
|
||||||
unsigned int bootIndex;
|
unsigned int bootIndex;
|
||||||
|
|
||||||
|
/* pciConnectFlags is only used internally during address
|
||||||
|
* assignment, never saved and never reported.
|
||||||
|
*/
|
||||||
|
int pciConnectFlags; /* enum virDomainPCIConnectFlags */
|
||||||
} virDomainDeviceInfo, *virDomainDeviceInfoPtr;
|
} virDomainDeviceInfo, *virDomainDeviceInfoPtr;
|
||||||
|
|
||||||
|
|
||||||
|
@ -409,6 +409,372 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuDomainDeviceCalculatePCIConnectFlags:
|
||||||
|
*
|
||||||
|
* @dev: The device to be checked
|
||||||
|
* @pcieFlags: flags to use for a known PCI Express device
|
||||||
|
* @virtioFlags: flags to use for a virtio device (properly vetted
|
||||||
|
* for the current qemu binary and arch/machinetype)
|
||||||
|
*
|
||||||
|
* Lowest level function to determine PCI connectFlags for a
|
||||||
|
* device. This function relies on the next higher-level function
|
||||||
|
* determining the value for pcieFlags and virtioFlags in advance -
|
||||||
|
* this is to make it more efficient to call multiple times.
|
||||||
|
*
|
||||||
|
* Returns appropriate virDomainPCIConnectFlags for this device in
|
||||||
|
* this domain, or 0 if the device doesn't connect using PCI. There
|
||||||
|
* is no failure.
|
||||||
|
*/
|
||||||
|
static virDomainPCIConnectFlags
|
||||||
|
qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
|
||||||
|
virDomainPCIConnectFlags pcieFlags
|
||||||
|
ATTRIBUTE_UNUSED,
|
||||||
|
virDomainPCIConnectFlags virtioFlags
|
||||||
|
ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
virDomainPCIConnectFlags pciFlags = (VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
|
||||||
|
VIR_PCI_CONNECT_HOTPLUGGABLE);
|
||||||
|
|
||||||
|
switch ((virDomainDeviceType) dev->type) {
|
||||||
|
case VIR_DOMAIN_DEVICE_CONTROLLER: {
|
||||||
|
virDomainControllerDefPtr cont = dev->data.controller;
|
||||||
|
|
||||||
|
switch ((virDomainControllerType) cont->type) {
|
||||||
|
case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
|
||||||
|
return virDomainPCIControllerModelToConnectType(cont->model);
|
||||||
|
|
||||||
|
case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_CONTROLLER_TYPE_USB:
|
||||||
|
switch ((virDomainControllerModelUSB) cont->model) {
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB1: /* xen only */
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2: /* xen only */
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_MODEL_USB_LAST:
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
|
||||||
|
case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_FS:
|
||||||
|
/* the only type of filesystem so far is virtio-9p-pci */
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_NET: {
|
||||||
|
virDomainNetDefPtr net = dev->data.net;
|
||||||
|
|
||||||
|
/* NB: a type='hostdev' will use PCI, but its
|
||||||
|
* address is assigned when we're assigning the
|
||||||
|
* addresses for other hostdev devices.
|
||||||
|
*/
|
||||||
|
if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
|
||||||
|
STREQ(net->model, "usb-net")) {
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_SOUND:
|
||||||
|
switch ((virDomainSoundModel) dev->data.sound->model) {
|
||||||
|
case VIR_DOMAIN_SOUND_MODEL_ES1370:
|
||||||
|
case VIR_DOMAIN_SOUND_MODEL_AC97:
|
||||||
|
case VIR_DOMAIN_SOUND_MODEL_ICH6:
|
||||||
|
case VIR_DOMAIN_SOUND_MODEL_ICH9:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_SOUND_MODEL_SB16:
|
||||||
|
case VIR_DOMAIN_SOUND_MODEL_PCSPK:
|
||||||
|
case VIR_DOMAIN_SOUND_MODEL_USB:
|
||||||
|
case VIR_DOMAIN_SOUND_MODEL_LAST:
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_DISK:
|
||||||
|
switch ((virDomainDiskBus) dev->data.disk->bus) {
|
||||||
|
case VIR_DOMAIN_DISK_BUS_VIRTIO:
|
||||||
|
return pciFlags; /* only virtio disks use PCI */
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DISK_BUS_IDE:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_FDC:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_SCSI:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_XEN:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_USB:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_UML:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_SATA:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_SD:
|
||||||
|
case VIR_DOMAIN_DISK_BUS_LAST:
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_MEMBALLOON:
|
||||||
|
switch ((virDomainMemballoonModel) dev->data.memballoon->model) {
|
||||||
|
case VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_MEMBALLOON_MODEL_XEN:
|
||||||
|
case VIR_DOMAIN_MEMBALLOON_MODEL_NONE:
|
||||||
|
case VIR_DOMAIN_MEMBALLOON_MODEL_LAST:
|
||||||
|
/* should be 0 (not PCI) */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_RNG:
|
||||||
|
switch ((virDomainRNGModel) dev->data.rng->model) {
|
||||||
|
case VIR_DOMAIN_RNG_MODEL_VIRTIO:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_RNG_MODEL_LAST:
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_WATCHDOG:
|
||||||
|
/* only one model connects using PCI */
|
||||||
|
switch ((virDomainWatchdogModel) dev->data.watchdog->model) {
|
||||||
|
case VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_WATCHDOG_MODEL_IB700:
|
||||||
|
case VIR_DOMAIN_WATCHDOG_MODEL_DIAG288:
|
||||||
|
case VIR_DOMAIN_WATCHDOG_MODEL_LAST:
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_VIDEO:
|
||||||
|
switch ((virDomainVideoType) dev->data.video->type) {
|
||||||
|
case VIR_DOMAIN_VIDEO_TYPE_VIRTIO:
|
||||||
|
case VIR_DOMAIN_VIDEO_TYPE_VGA:
|
||||||
|
case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
|
||||||
|
case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
|
||||||
|
case VIR_DOMAIN_VIDEO_TYPE_XEN:
|
||||||
|
case VIR_DOMAIN_VIDEO_TYPE_VBOX:
|
||||||
|
case VIR_DOMAIN_VIDEO_TYPE_QXL:
|
||||||
|
case VIR_DOMAIN_VIDEO_TYPE_PARALLELS:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_VIDEO_TYPE_LAST:
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_SHMEM:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_INPUT:
|
||||||
|
switch ((virDomainInputBus) dev->data.input->bus) {
|
||||||
|
case VIR_DOMAIN_INPUT_BUS_VIRTIO:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_INPUT_BUS_PS2:
|
||||||
|
case VIR_DOMAIN_INPUT_BUS_USB:
|
||||||
|
case VIR_DOMAIN_INPUT_BUS_XEN:
|
||||||
|
case VIR_DOMAIN_INPUT_BUS_PARALLELS:
|
||||||
|
case VIR_DOMAIN_INPUT_BUS_LAST:
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_CHR:
|
||||||
|
switch ((virDomainChrSerialTargetType) dev->data.chr->targetType) {
|
||||||
|
case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI:
|
||||||
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA:
|
||||||
|
case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB:
|
||||||
|
case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST:
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* These devices don't ever connect with PCI */
|
||||||
|
case VIR_DOMAIN_DEVICE_NVRAM:
|
||||||
|
case VIR_DOMAIN_DEVICE_TPM:
|
||||||
|
case VIR_DOMAIN_DEVICE_PANIC:
|
||||||
|
case VIR_DOMAIN_DEVICE_MEMORY:
|
||||||
|
case VIR_DOMAIN_DEVICE_HUB:
|
||||||
|
case VIR_DOMAIN_DEVICE_REDIRDEV:
|
||||||
|
case VIR_DOMAIN_DEVICE_SMARTCARD:
|
||||||
|
/* These devices don't even have a DeviceInfo */
|
||||||
|
case VIR_DOMAIN_DEVICE_LEASE:
|
||||||
|
case VIR_DOMAIN_DEVICE_GRAPHICS:
|
||||||
|
case VIR_DOMAIN_DEVICE_IOMMU:
|
||||||
|
case VIR_DOMAIN_DEVICE_LAST:
|
||||||
|
case VIR_DOMAIN_DEVICE_NONE:
|
||||||
|
/* should be 0 */
|
||||||
|
return pciFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We can never get here, because all cases are covered in the
|
||||||
|
* switch, and they all return, but the compiler will still
|
||||||
|
* complain "control reaches end of non-void function" unless
|
||||||
|
* we add the following return.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
virDomainPCIConnectFlags virtioFlags;
|
||||||
|
virDomainPCIConnectFlags pcieFlags;
|
||||||
|
} qemuDomainFillDevicePCIConnectFlagsIterData;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuDomainFillDevicePCIConnectFlagsIterInit:
|
||||||
|
*
|
||||||
|
* Initialize the iterator data that is used when calling
|
||||||
|
* qemuDomainCalculateDevicePCIConnectFlags().
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
qemuDomainFillDevicePCIConnectFlagsIterInit(virDomainDefPtr def,
|
||||||
|
virQEMUCapsPtr qemuCaps,
|
||||||
|
qemuDomainFillDevicePCIConnectFlagsIterData *data)
|
||||||
|
{
|
||||||
|
if (qemuDomainMachineHasPCIeRoot(def)) {
|
||||||
|
data->pcieFlags = (VIR_PCI_CONNECT_TYPE_PCIE_DEVICE |
|
||||||
|
VIR_PCI_CONNECT_HOTPLUGGABLE);
|
||||||
|
} else {
|
||||||
|
data->pcieFlags = (VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
|
||||||
|
VIR_PCI_CONNECT_HOTPLUGGABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY)) {
|
||||||
|
data->virtioFlags = data->pcieFlags;
|
||||||
|
} else {
|
||||||
|
data->virtioFlags = (VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
|
||||||
|
VIR_PCI_CONNECT_HOTPLUGGABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuDomainFillDevicePCIConnectFlagsIter:
|
||||||
|
*
|
||||||
|
* @def: the entire DomainDef
|
||||||
|
* @dev: The device to be checked
|
||||||
|
* @info: virDomainDeviceInfo within the device
|
||||||
|
* @opaque: points to iterator data setup beforehand.
|
||||||
|
*
|
||||||
|
* Sets the pciConnectFlags for a single device's info. Has properly
|
||||||
|
* formatted arguments to be called by virDomainDeviceInfoIterate().
|
||||||
|
*
|
||||||
|
* Always returns 0 - there is no failure.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
qemuDomainFillDevicePCIConnectFlagsIter(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
||||||
|
virDomainDeviceDefPtr dev,
|
||||||
|
virDomainDeviceInfoPtr info,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
qemuDomainFillDevicePCIConnectFlagsIterData *data = opaque;
|
||||||
|
|
||||||
|
info->pciConnectFlags
|
||||||
|
= qemuDomainDeviceCalculatePCIConnectFlags(dev, data->pcieFlags,
|
||||||
|
data->virtioFlags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuDomainFillAllPCIConnectFlags:
|
||||||
|
*
|
||||||
|
* @def: the entire DomainDef
|
||||||
|
* @qemuCaps: as you'd expect
|
||||||
|
*
|
||||||
|
* Set the info->pciConnectFlags for all devices in the domain.
|
||||||
|
*
|
||||||
|
* Returns 0 on success or -1 on failure (the only possibility of
|
||||||
|
* failure would be some internal problem with
|
||||||
|
* virDomainDeviceInfoIterate())
|
||||||
|
*/
|
||||||
|
static int ATTRIBUTE_UNUSED
|
||||||
|
qemuDomainFillAllPCIConnectFlags(virDomainDefPtr def,
|
||||||
|
virQEMUCapsPtr qemuCaps)
|
||||||
|
{
|
||||||
|
qemuDomainFillDevicePCIConnectFlagsIterData data;
|
||||||
|
|
||||||
|
qemuDomainFillDevicePCIConnectFlagsIterInit(def, qemuCaps, &data);
|
||||||
|
|
||||||
|
return virDomainDeviceInfoIterate(def,
|
||||||
|
qemuDomainFillDevicePCIConnectFlagsIter,
|
||||||
|
&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuDomainFillDevicePCIConnectFlags:
|
||||||
|
*
|
||||||
|
* @def: the entire DomainDef
|
||||||
|
* @dev: The device to be checked
|
||||||
|
* @qemuCaps: as you'd expect
|
||||||
|
*
|
||||||
|
* Set the info->pciConnectFlags for a single device.
|
||||||
|
*
|
||||||
|
* No return value.
|
||||||
|
*/
|
||||||
|
static void ATTRIBUTE_UNUSED
|
||||||
|
qemuDomainFillDevicePCIConnectFlags(virDomainDefPtr def,
|
||||||
|
virDomainDeviceDefPtr dev,
|
||||||
|
virQEMUCapsPtr qemuCaps)
|
||||||
|
{
|
||||||
|
virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev);
|
||||||
|
|
||||||
|
if (info) {
|
||||||
|
/* qemuDomainDeviceCalculatePCIConnectFlags() is called with
|
||||||
|
* the data setup in the ...IterData by ...IterInit() rather
|
||||||
|
* than setting the values directly here. It may seem like
|
||||||
|
* pointless posturing, but it's done this way to eliminate
|
||||||
|
* duplicated setup code while allowing more efficient
|
||||||
|
* operation when it's being done repeatedly with the device
|
||||||
|
* iterator (since qemuDomainFillAllPCIConnectFlags() only
|
||||||
|
* calls ...IterInit() once for all devices).
|
||||||
|
*/
|
||||||
|
qemuDomainFillDevicePCIConnectFlagsIterData data;
|
||||||
|
|
||||||
|
qemuDomainFillDevicePCIConnectFlagsIterInit(def, qemuCaps, &data);
|
||||||
|
|
||||||
|
info->pciConnectFlags
|
||||||
|
= qemuDomainDeviceCalculatePCIConnectFlags(dev, data.pcieFlags,
|
||||||
|
data.virtioFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
|
qemuDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
|
||||||
virDomainDeviceInfoPtr dev,
|
virDomainDeviceInfoPtr dev,
|
||||||
|
Loading…
Reference in New Issue
Block a user