mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-01 09:25:18 +00:00
qemu: add dmi-to-pci-bridge controller
This PCI controller, named "dmi-to-pci-bridge" in the libvirt config, and implemented with qemu's "i82801b11-bridge" device, connects to a PCI Express slot (e.g. one of the slots provided by the pcie-root controller, aka "pcie.0" on the qemu commandline), and provides 31 *non-hot-pluggable* PCI (*not* PCIe) slots, numbered 1-31. Any time a machine is defined which has a pcie-root controller (i.e. any q35-based machinetype), libvirt will automatically add a dmi-to-pci-bridge controller if one doesn't exist, and also add a pci-bridge controller. The reasoning here is that any useful domain will have either an immediate (startup time) or eventual (subsequent hot-plug) need for a standard PCI slot; since the pcie-root controller only provides PCIe slots, we need to connect a dmi-to-pci-bridge controller to it in order to get a non-hot-plug PCI slot that we can then use to connect a pci-bridge - the slots provided by the pci-bridge will be both standard PCI and hot-pluggable. Since pci-bridge devices themselves can not be hot-plugged into a running system (although you can hot-plug other devices into a pci-bridge's slots), any new pci-bridge controller that is added can (and will) be plugged into the dmi-to-pci-bridge as long as it has empty slots available. This patch is also changing the qemuxml2xml-pcie test from a "DO_TEST" to a "DO_DIFFERENT_TEST". This is so that the "before" xml can omit the automatically added dmi-to-pci-bridge and pci-bridge devices, and the "after" xml can include it - this way we are testing if libvirt is properly adding these devices.
This commit is contained in:
parent
48a3f48ac5
commit
62ac6b4354
@ -2338,11 +2338,14 @@
|
||||
|
||||
<p>
|
||||
PCI controllers have an optional <code>model</code> attribute with
|
||||
possible values <code>pci-root</code>, <code>pcie-root</code>
|
||||
or <code>pci-bridge</code>.
|
||||
possible values <code>pci-root</code>, <code>pcie-root</code>,
|
||||
<code>pci-bridge</code>, or <code>dmi-to-pci-bridge</code>.
|
||||
For machine types which provide an implicit PCI bus, the pci-root
|
||||
controller with index=0 is auto-added and required to use PCI devices.
|
||||
pci-root has no address.
|
||||
PCI bridges are auto-added if there are too many devices to fit on
|
||||
the one bus provided by pci-root, or a PCI bus number greater than zero
|
||||
was specified.
|
||||
PCI bridges can also be specified manually, but their addresses should
|
||||
only refer to PCI buses provided by already specified PCI controllers.
|
||||
Leaving gaps in the PCI controller indexes might lead to an invalid
|
||||
@ -2365,12 +2368,29 @@
|
||||
the pcie-root controller with index=0 is auto-added to the
|
||||
domain's configuration. pcie-root has also no address, provides
|
||||
31 slots (numbered 1-31) and can only be used to attach PCIe
|
||||
devices. (<span class="since">since 1.1.2</span>).
|
||||
devices. In order to connect standard PCI devices on a system
|
||||
which has a pcie-root controller, a pci controller
|
||||
with <code>model='dmi-to-pci-bridge'</code> is automatically
|
||||
added. A dmi-to-pci-bridge controller plugs into a PCIe slot (as
|
||||
provided by pcie-root), and itself provides 31 standard PCI
|
||||
slots (which are not hot-pluggable). In order to have
|
||||
hot-pluggable PCI slots in the guest system, a pci-bridge
|
||||
controller will also be automatically created and connected to
|
||||
one of the slots of the auto-created dmi-to-pci-bridge
|
||||
controller; all guest devices with PCI addresses that are
|
||||
auto-determined by libvirt will be placed on this pci-bridge
|
||||
device. (<span class="since">since 1.1.2</span>).
|
||||
</p>
|
||||
<pre>
|
||||
...
|
||||
<devices>
|
||||
<controller type='pci' index='0' model='pcie-root'/>
|
||||
<controller type='pci' index='1' model='dmi-to-pci-bridge'>
|
||||
<address type='pci' domain='0' bus='0' slot='0xe' function='0'/>
|
||||
</controller>
|
||||
<controller type='pci' index='2' model='pci-bridge'>
|
||||
<address type='pci' domain='0' bus='1' slot='1' function='0'/>
|
||||
</controller>
|
||||
</devices>
|
||||
...</pre>
|
||||
|
||||
|
@ -1540,6 +1540,7 @@
|
||||
<value>pci-root</value>
|
||||
<value>pcie-root</value>
|
||||
<value>pci-bridge</value>
|
||||
<value>dmi-to-pci-bridge</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
</group>
|
||||
|
@ -311,7 +311,8 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
|
||||
VIR_ENUM_IMPL(virDomainControllerModelPCI, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST,
|
||||
"pci-root",
|
||||
"pcie-root",
|
||||
"pci-bridge")
|
||||
"pci-bridge",
|
||||
"dmi-to-pci-bridge")
|
||||
|
||||
VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
|
||||
"auto",
|
||||
|
@ -770,6 +770,7 @@ typedef enum {
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT,
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT,
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE,
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE,
|
||||
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST
|
||||
} virDomainControllerModelPCI;
|
||||
|
@ -234,6 +234,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
|
||||
|
||||
"vnc-share-policy", /* 150 */
|
||||
"device-del-event",
|
||||
"dmi-to-pci-bridge",
|
||||
);
|
||||
|
||||
struct _virQEMUCaps {
|
||||
@ -1381,6 +1382,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
|
||||
{ "pci-bridge", QEMU_CAPS_DEVICE_PCI_BRIDGE },
|
||||
{ "vfio-pci", QEMU_CAPS_DEVICE_VFIO_PCI },
|
||||
{ "scsi-generic", QEMU_CAPS_DEVICE_SCSI_GENERIC },
|
||||
{ "i82801b11-bridge", QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE },
|
||||
};
|
||||
|
||||
static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBlk[] = {
|
||||
|
@ -190,6 +190,7 @@ enum virQEMUCapsFlags {
|
||||
QEMU_CAPS_MLOCK = 149, /* -realtime mlock=on|off */
|
||||
QEMU_CAPS_VNC_SHARE_POLICY = 150, /* set display sharing policy */
|
||||
QEMU_CAPS_DEVICE_DEL_EVENT = 151, /* DEVICE_DELETED event */
|
||||
QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE = 152, /* -device i82801b11-bridge */
|
||||
|
||||
QEMU_CAPS_LAST, /* this must always be the last item */
|
||||
};
|
||||
|
@ -1561,6 +1561,13 @@ qemuDomainPCIAddressBusSetModel(qemuDomainPCIAddressBusPtr bus,
|
||||
bus->minSlot = 1;
|
||||
bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST;
|
||||
break;
|
||||
case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
|
||||
/* slots 1 - 31, standard PCI slots,
|
||||
* but *not* hot-pluggable */
|
||||
bus->flags = QEMU_PCI_CONNECT_TYPE_PCI;
|
||||
bus->minSlot = 1;
|
||||
bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST;
|
||||
break;
|
||||
default:
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Invalid PCI controller model %d"), model);
|
||||
@ -1669,6 +1676,12 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
||||
*/
|
||||
flags = QEMU_PCI_CONNECT_TYPE_PCI;
|
||||
break;
|
||||
case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
|
||||
/* pci-bridge needs a PCIe slot, but it isn't
|
||||
* hot-pluggable, so it doesn't need a hot-pluggable slot.
|
||||
*/
|
||||
flags = QEMU_PCI_CONNECT_TYPE_PCIE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2372,6 +2385,12 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
|
||||
*/
|
||||
flags = QEMU_PCI_CONNECT_TYPE_PCI;
|
||||
break;
|
||||
case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
|
||||
/* dmi-to-pci-bridge requires a non-hotplug PCIe
|
||||
* slot
|
||||
*/
|
||||
flags = QEMU_PCI_CONNECT_TYPE_PCIE;
|
||||
break;
|
||||
default:
|
||||
flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
|
||||
break;
|
||||
@ -4351,6 +4370,20 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
|
||||
virBufferAsprintf(&buf, "pci-bridge,chassis_nr=%d,id=pci.%d",
|
||||
def->idx, def->idx);
|
||||
break;
|
||||
case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
|
||||
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("The dmi-to-pci-bridge (i82801b11-bridge) "
|
||||
"controller is not supported in this QEMU binary"));
|
||||
goto error;
|
||||
}
|
||||
if (def->idx == 0) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("dmi-to-pci-bridge index should be > 0"));
|
||||
goto error;
|
||||
}
|
||||
virBufferAsprintf(&buf, "i82801b11-bridge,id=pci.%d", def->idx);
|
||||
break;
|
||||
case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
|
||||
case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
|
@ -760,12 +760,23 @@ qemuDomainDefPostParse(virDomainDefPtr def,
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
|
||||
return -1;
|
||||
|
||||
if (addPCIeRoot &&
|
||||
virDomainDefMaybeAddController(
|
||||
/* When a machine has a pcie-root, make sure that there is always
|
||||
* a dmi-to-pci-bridge controller added as bus 1, and a pci-bridge
|
||||
* as bus 2, so that standard PCI devices can be connected
|
||||
*/
|
||||
if (addPCIeRoot) {
|
||||
if (virDomainDefMaybeAddController(
|
||||
def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) < 0)
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) < 0 ||
|
||||
virDomainDefMaybeAddController(
|
||||
def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 1,
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE) < 0 ||
|
||||
virDomainDefMaybeAddController(
|
||||
def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 2,
|
||||
VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE) < 0) {
|
||||
return -1;
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/libexec/qemu-kvm \
|
||||
-S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
|
||||
-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
|
||||
-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.1,addr=0x1 -usb
|
||||
-device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x1 \
|
||||
-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 -usb
|
||||
|
7
tests/qemuxml2argvdata/qemuxml2argv-q35.args
Normal file
7
tests/qemuxml2argvdata/qemuxml2argv-q35.args
Normal file
@ -0,0 +1,7 @@
|
||||
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
|
||||
/usr/libexec/qemu-kvm -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
|
||||
-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
|
||||
-device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x1 \
|
||||
-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \
|
||||
-usb \
|
||||
-vga qxl -global qxl.ram_size=67108864 -global qxl.vram_size=18874368
|
25
tests/qemuxml2argvdata/qemuxml2argv-q35.xml
Normal file
25
tests/qemuxml2argvdata/qemuxml2argv-q35.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<domain type='qemu'>
|
||||
<name>q35-test</name>
|
||||
<uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid>
|
||||
<memory unit='KiB'>2097152</memory>
|
||||
<currentMemory unit='KiB'>2097152</currentMemory>
|
||||
<vcpu placement='static' cpuset='0-1'>2</vcpu>
|
||||
<os>
|
||||
<type arch='x86_64' machine='q35'>hvm</type>
|
||||
<boot dev='hd'/>
|
||||
</os>
|
||||
<clock offset='utc'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<emulator>/usr/libexec/qemu-kvm</emulator>
|
||||
<controller type='pci' index='0' model='pcie-root'/>
|
||||
<controller type='pci' index='1' model='dmi-to-pci-bridge'/>
|
||||
<controller type='pci' index='2' model='pci-bridge'/>
|
||||
<video>
|
||||
<model type='qxl' ram='65536' vram='18432' heads='1'/>
|
||||
</video>
|
||||
<memballoon model='none'/>
|
||||
</devices>
|
||||
</domain>
|
@ -995,7 +995,13 @@ mymain(void)
|
||||
DO_TEST("pci-bridge-many-disks",
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
|
||||
DO_TEST("pcie-root",
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE,
|
||||
QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE);
|
||||
DO_TEST("q35",
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE,
|
||||
QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
|
||||
QEMU_CAPS_VGA, QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
|
||||
QEMU_CAPS_VGA, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL);
|
||||
|
||||
DO_TEST("hostdev-scsi-lsi", QEMU_CAPS_DRIVE,
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
|
||||
|
23
tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml
Normal file
23
tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<domain type='qemu'>
|
||||
<name>q35-test</name>
|
||||
<uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid>
|
||||
<memory unit='KiB'>2097152</memory>
|
||||
<currentMemory unit='KiB'>2097152</currentMemory>
|
||||
<vcpu placement='static' cpuset='0-1'>2</vcpu>
|
||||
<os>
|
||||
<type arch='x86_64' machine='q35'>hvm</type>
|
||||
<boot dev='hd'/>
|
||||
</os>
|
||||
<clock offset='utc'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<emulator>/usr/libexec/qemu-kvm</emulator>
|
||||
<controller type='pci' index='0' model='pcie-root'/>
|
||||
<controller type='usb' index='0'/>
|
||||
<controller type='pci' index='1' model='dmi-to-pci-bridge'/>
|
||||
<controller type='pci' index='2' model='pci-bridge'/>
|
||||
<memballoon model='none'/>
|
||||
</devices>
|
||||
</domain>
|
@ -294,7 +294,8 @@ mymain(void)
|
||||
DO_TEST_DIFFERENT("pci-bridge-many-disks");
|
||||
DO_TEST_DIFFERENT("pci-autoadd-addr");
|
||||
DO_TEST_DIFFERENT("pci-autoadd-idx");
|
||||
DO_TEST("pcie-root");
|
||||
DO_TEST_DIFFERENT("pcie-root");
|
||||
DO_TEST("q35");
|
||||
|
||||
DO_TEST("hostdev-scsi-lsi");
|
||||
DO_TEST("hostdev-scsi-virtio-scsi");
|
||||
|
Loading…
x
Reference in New Issue
Block a user