This change introduces libvirt xml support for the following two pm options: <pm> <acpi-hotplug-bridge enabled='no'/> <acpi-root-hotplug enabled='yes'/> </pm> The above two options are only available for qemu driver and that too for x86 guests only. Both of them are global options. 'acpi-hotplug-bridge' option enables or disables ACPI hotplug support for cold plugged bridges. Examples of cold plugged bridges include PCI-PCI bridge (pci-bridge controller) for pc machines and pcie-root-port controller for q35 machines. Being global options, no other bridge specific options for pci-bridge controller or pcie-root-port controllers are required. For pc machine type in x86, this option is available in qemu for a long time, from version 2.1. Please see the changes in qemu.git: 9e047b982452c6 ("piix4: add acpi pci hotplug support") 133a2da488062e ("pc: acpi: generate AML only for PCI0 devices if PCI bridge hotplug is disabled") For q35 machine type, this was introduced in qemu 6.1 with the following changes in qemu.git: (a) c0e427d6eb5fef ("hw/acpi/ich9: Enable ACPI PCI hot-plug") (b) 17858a16950860 ("hw/acpi/ich9: Set ACPI PCI hot-plug as default on Q35") The reasons for enabling ACPI based hotplug for PCIe (q35) based machines (as opposed to native hotplug) are outlined in (b). It is possible that some users might still want to use native hotplug on PCIe. Therefore, this config option enables users to choose either ACPI based hotplug or native hotplug for cold plugged bridges (for example for pcie root port controller in q35 machines). 'acpi-root-hotplug' option enables or disables ACPI based hotplug for PCI root bus (pci-root controller). This option is only available for pc machine type. This additional option enables users to disable hotplug for all devices in the system without adding an additional PCI-PCI bridge, putting the devices behind the bridge and using the existing "acpi-hotplug-bridge" option to disable hotplug on that bridge. This feature was introduced from qemu version 5.2 with the following change in qemu.git: 3d7e78aa7777f ("Introduce a new flag for i440fx to disable PCI hotplug on the root bus") The above qemu commit describes some compelling reasons why users might to disable hotplug on PCI root buses. This change also adds related unit tests to exercise the new conf options. Signed-off-by: Ani Sinha <ani@xxxxxxxxxxx> --- docs/formatdomain.rst | 36 ++++++++++++--- docs/schemas/domaincommon.rng | 17 +++++++ src/conf/domain_conf.c | 21 ++++++++- src/conf/domain_conf.h | 2 + .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 17 +++++++ .../pc-i440fx-acpi-root-hotplug-disable.xml | 17 +++++++ .../q35-acpi-hotplug-bridge-disable.xml | 17 +++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 31 +++++++++++++ .../pc-i440fx-acpi-root-hotplug-disable.xml | 31 +++++++++++++ .../q35-acpi-hotplug-bridge-disable.xml | 45 +++++++++++++++++++ tests/qemuxml2xmltest.c | 9 ++++ 11 files changed, 236 insertions(+), 7 deletions(-) create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-root-hotplug-disable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2xmloutdata/pc-i440fx-acpi-root-hotplug-disable.xml create mode 100644 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index ad3b4ea92c..c8b04c625c 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -1793,16 +1793,40 @@ advertisements to the guest OS. (NB: Only qemu driver support) <pm> <suspend-to-disk enabled='no'/> <suspend-to-mem enabled='yes'/> + <acpi-hotplug-bridge enabled='no'/> + <acpi-root-hotplug enabled='yes'/> </pm> ... ``pm`` - These elements enable ('yes') or disable ('no') BIOS support for S3 - (suspend-to-mem) and S4 (suspend-to-disk) ACPI sleep states. If nothing is - specified, then the hypervisor will be left with its default value. - Note: This setting cannot prevent the guest OS from performing a suspend as - the guest OS itself can choose to circumvent the unavailability of the sleep - states (e.g. S4 by turning off completely). + These elements enable ('yes') or disable ('no') certain BIOS advertisements. + If nothing is specified, then the hypervisor will be left with its default value. + The following BIOS options are available: + +``suspend-to-mem`` + support for S3 (suspend-to-mem) ACPI sleep states. +``suspend-to-disk`` + support for S4 (suspend-to-disk) ACPI sleep states. + + Note that for the above two options, the setting cannot prevent the guest OS + from performing a suspend as the guest OS itself can choose to circumvent the + unavailability of the sleep states (e.g. S4 by turning off completely). + +``acpi-hotplug-bridge`` + :since:`Since 7.8.0` This option enables or disables BIOS ACPI based hotplug support + for cold plugged bridges. It is available only for x86 guests, both for q35 and pc + machine types. For pc machines, the support is available from `QEMU 2.12`. For q35 + machines, the support is available from `QEMU 6.1`. Examples of cold plugged bridges + include PCI-PCI bridges for pc machine types (pci-bridge controller). For q35 machines, + it includes PCIE root ports (pcie-root-port controller). This is a global option that + affects all bridges. No other bridge specific option is required to be specified. + +``acpi-root-hotplug`` + :since:`Since 7.8.0 (QEMU 5.2)` This option enables or disables BIOS ACPI based + hotplug support for PCI root bus (pci-root controller). This is available only + for x86 guests, only for pc machine type. For q35 machines, PCIE root complex, + the pcie-root controller, does not support hotplug capability. This is also a global + option. :anchor:`<a id="elementsFeatures"/>` diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 11fa24f398..a51efb933d 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4333,6 +4333,16 @@ <ref name="suspendChoices"/> </element> </optional> + <optional> + <element name="acpi-hotplug-bridge"> + <ref name="acpiHotplugChoices"/> + </element> + </optional> + <optional> + <element name="acpi-root-hotplug"> + <ref name="acpiHotplugChoices"/> + </element> + </optional> </interleave> <empty/> </element> @@ -4344,6 +4354,13 @@ </attribute> </optional> </define> + <define name="acpiHotplugChoices"> + <optional> + <attribute name="enabled"> + <ref name="virYesNo"/> + </attribute> + </optional> + </define> <!-- Specific setup for a qemu emulated character device. Note: this definition doesn't fully specify the constraints on this node. diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index cb9e7218ff..e48661534f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -19339,6 +19339,16 @@ virDomainDefLifecycleParse(virDomainDef *def, &def->pm.s4) < 0) goto error; + if (virDomainPMStateParseXML(ctxt, + "string(./pm/acpi-hotplug-bridge/@enabled)", + &def->pm.acpi_hp_bridge) < 0) + goto error; + + if (virDomainPMStateParseXML(ctxt, + "string(./pm/acpi-root-hotplug/@enabled)", + &def->pm.acpi_root_hp) < 0) + goto error; + return 0; error: @@ -28151,7 +28161,8 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, virDomainLockFailureTypeToString) < 0) return -1; - if (def->pm.s3 || def->pm.s4) { + if (def->pm.s3 || def->pm.s4 || def->pm.acpi_hp_bridge || + def->pm.acpi_root_hp) { virBufferAddLit(buf, "<pm>\n"); virBufferAdjustIndent(buf, 2); if (def->pm.s3) { @@ -28162,6 +28173,14 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, virBufferAsprintf(buf, "<suspend-to-disk enabled='%s'/>\n", virTristateBoolTypeToString(def->pm.s4)); } + if (def->pm.acpi_hp_bridge) { + virBufferAsprintf(buf, "<acpi-hotplug-bridge enabled='%s'/>\n", + virTristateBoolTypeToString(def->pm.acpi_hp_bridge)); + } + if (def->pm.acpi_root_hp) { + virBufferAsprintf(buf, "<acpi-root-hotplug enabled='%s'/>\n", + virTristateBoolTypeToString(def->pm.acpi_root_hp)); + } virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</pm>\n"); } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index c7e6df7981..863bdf54f8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2644,6 +2644,8 @@ struct _virDomainPowerManagement { /* These options are of type enum virTristateBool */ int s3; int s4; + int acpi_hp_bridge; + int acpi_root_hp; }; struct _virDomainPerfDef { diff --git a/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..b96caa9b2d --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,17 @@ +<domain type='qemu'> + <name>i440fx</name> + <uuid>56f5055c-1b8d-490c-844a-ad646a1caaaa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type> + <boot dev='network'/> + </os> + <pm> + <acpi-hotplug-bridge enabled='no'/> + </pm> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/pc-i440fx-acpi-root-hotplug-disable.xml b/tests/qemuxml2argvdata/pc-i440fx-acpi-root-hotplug-disable.xml new file mode 100644 index 0000000000..ef563200bf --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-root-hotplug-disable.xml @@ -0,0 +1,17 @@ +<domain type='qemu'> + <name>i440fx</name> + <uuid>56f5055c-1b8d-490c-844a-ad646a1caaaa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type> + <boot dev='network'/> + </os> + <pm> + <acpi-root-hotplug enabled='no'/> + </pm> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..bb9e8d4ee2 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,17 @@ +<domain type='qemu'> + <name>q35</name> + <uuid>56f5055c-1b8d-490c-844a-ad646a1caaaa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-q35-2.5'>hvm</type> + <boot dev='network'/> + </os> + <pm> + <acpi-hotplug-bridge enabled='no'/> + </pm> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..2534dc7e35 --- /dev/null +++ b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,31 @@ +<domain type='qemu'> + <name>i440fx</name> + <uuid>56f5055c-1b8d-490c-844a-ad646a1caaaa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type> + <boot dev='network'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <pm> + <acpi-hotplug-bridge enabled='no'/> + </pm> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/pc-i440fx-acpi-root-hotplug-disable.xml b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-root-hotplug-disable.xml new file mode 100644 index 0000000000..0ee404ee46 --- /dev/null +++ b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-root-hotplug-disable.xml @@ -0,0 +1,31 @@ +<domain type='qemu'> + <name>i440fx</name> + <uuid>56f5055c-1b8d-490c-844a-ad646a1caaaa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type> + <boot dev='network'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <pm> + <acpi-root-hotplug enabled='no'/> + </pm> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..e8c6f82145 --- /dev/null +++ b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,45 @@ +<domain type='qemu'> + <name>q35</name> + <uuid>56f5055c-1b8d-490c-844a-ad646a1caaaa</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-q35-2.5'>hvm</type> + <boot dev='network'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <pm> + <acpi-hotplug-bridge enabled='no'/> + </pm> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='dmi-to-pci-bridge'> + <model name='i82801b11-bridge'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/> + </controller> + <controller type='pci' index='2' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='2'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </controller> + <controller type='pci' index='3' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='3' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 6d3526f91f..cbf2306e05 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -425,6 +425,15 @@ mymain(void) DO_TEST_NOCAPS("input-usbtablet"); DO_TEST_NOCAPS("misc-acpi"); DO_TEST("misc-disable-s3", QEMU_CAPS_PIIX_DISABLE_S3); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-disable", + QEMU_CAPS_PIIX_ACPI_HOTPLUG_BRIDGE); + DO_TEST("q35-acpi-hotplug-bridge-disable", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); + DO_TEST("pc-i440fx-acpi-root-hotplug-disable", + QEMU_CAPS_PIIX_ACPI_ROOT_PCI_HOTPLUG); DO_TEST("misc-disable-suspends", QEMU_CAPS_PIIX_DISABLE_S3, QEMU_CAPS_PIIX_DISABLE_S4); -- 2.25.1