[PATCH v6 0/4] introduce support for acpi-bridge-hotplug feature

changelog: v6: rebased to latest. capabilities have been renamed as per suggestions that were made here: https://listman.redhat.com/archives/libvir-list/2021-October/msg00061.html v5: rebased the patchset with the latest master. v4: split the original series into two - pci-root controller specific one (https://www.mail-archive.com/libvir-list@redhat.com/msg221645.html) and this one specific to pci bridges. The conf xml has been introduced as per suggestion by Berrange here: https://patchew.org/Libvirt/20210912032631.2853520-1-ani@anisinha.ca Changes has been introduced to parse and validate the xml accordingly as well as to add backend qemu commandline option. v3: reorganized the patches as per Laine's suggestion. Added more details in commit messages. Added conf description in formatdomain.rst. Added changelog for next release. v2: fixed bugs and added additional missing unit tests. v1: initial implementation. Had some bugs and missed some unit tests This change introduces a new libvirt sub-element <pci> under <features> that can be used to configure all pci related features. Currently the only sub-sub element supported by this sub-element is 'acpi-bridge-hotplug' as shown below: <features> <pci> <acpi-bridge-hotplug state='on|off'/> </pci> </features> The above option is only available for qemu driver and that too for x86 guests only. It is a global option. 'acpi-bridge-hotplug' option enables or disables ACPI hotplug support for cold-plugged pci bridges. Examples of bridges include PCI-PCI bridge (pci-bridge controller) or PCIe-PCI bridges for pc machines and pcie-root-port controller for q35 machines. Being global option, no other bridge specific option 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 following changes in qemu repo: 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 repo: (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). There are use cases where users would still want to use native hotplug (see notes). Therefore, this config option enables users to choose either ACPI based hotplug or native hotplug for bridges (for example for pcie root port controller in q35 machines). Notes: One concrete example of why one might still want to use native hotplug with pcie-root-port controller is the fact that we are still discovering issues with acpi hotplug on PCIE. One such issue is: https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg02146.html Another reason is that users have been using native hotplug on pcie root ports up until now. They have built and tested their systems based on native hotplug. They may not want to suddenly move to acpi based hotplug just because it is now the default in qemu. Supporting the option to chose one or the other through libvirt makes things simpler for end users. Ani Sinha (4): qemu: capablities: detect presence of acpi-pci-hotplug-with-bridge-support conf: introduce support for acpi-bridge-hotplug feature qemu: command: add support for acpi-bridge-hotplug feature NEWS: add new acpi pci hotplug config option in the release note for next release NEWS.rst | 7 ++ docs/formatdomain.rst | 11 +++ docs/schemas/domaincommon.rng | 15 ++++ src/conf/domain_conf.c | 89 ++++++++++++++++++- src/conf/domain_conf.h | 9 ++ src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 14 +++ src/qemu/qemu_validate.c | 46 ++++++++++ .../caps_2.11.0.x86_64.xml | 1 + .../caps_2.12.0.x86_64.xml | 1 + .../caps_3.0.0.x86_64.xml | 1 + .../caps_3.1.0.x86_64.xml | 1 + .../caps_4.0.0.x86_64.xml | 1 + .../caps_4.1.0.x86_64.xml | 1 + .../caps_4.2.0.x86_64.xml | 1 + .../caps_5.0.0.x86_64.xml | 1 + .../caps_5.1.0.x86_64.xml | 1 + .../caps_5.2.0.x86_64.xml | 1 + .../caps_6.0.0.x86_64.xml | 1 + .../caps_6.1.0.x86_64.xml | 2 + .../aarch64-acpi-hotplug-bridge-disable.err | 1 + .../aarch64-acpi-hotplug-bridge-disable.xml | 33 +++++++ ...pc-i440fx-acpi-hotplug-bridge-disable.args | 31 +++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.err | 1 + .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 33 +++++++ .../q35-acpi-hotplug-bridge-disable.args | 33 +++++++ .../q35-acpi-hotplug-bridge-disable.err | 1 + .../q35-acpi-hotplug-bridge-disable.xml | 47 ++++++++++ .../q35-acpi-hotplug-bridge-enable.xml | 47 ++++++++++ tests/qemuxml2argvtest.c | 16 ++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 1 + .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 1 + .../q35-acpi-hotplug-bridge-disable.xml | 1 + .../q35-acpi-hotplug-bridge-enable.xml | 1 + tests/qemuxml2xmltest.c | 14 +++ 37 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml -- 2.25.1

qemu added support for i440fx specific global boolean flag PIIX4_PM.acpi-pci-hotplug-with-bridge-support around version 2.1. This flag is enabled by default. When disabled, it turns off acpi pci hotplug for cold plugged pci bridges in i440fx machine types. Very recently, in qemu version 6.1, the same global option was also added for q35 machine types as well. ICH9-LPC.acpi-pci-hotplug-with-bridge-support This option turns on or off acpi based hotplug for cold plugged pcie bridges like pcie root ports. This flag is also enabled by default. Please refer to the following qemu changes: c0e427d6eb5fef ("hw/acpi/ich9: Enable ACPI PCI hot-plug") 17858a16950860 ("hw/acpi/ich9: Set ACPI PCI hot-plug as default on Q35") This patch adds the corresponding qemu capabilities in libvirt. For i440fx, the capability is detected as QEMU_CAPS_PIIX_ACPI_HOTPLUG_BRIDGE. For q35, the capability is detected as QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE. Please note that the test specific qemu capabilities .replies files has already been updated as a part of regular refreshing them when a new qemu version is released. Hence, no updates to those files are required. Signed-off-by: Ani Sinha <ani@anisinha.ca> Reviewed-by: Laine Stump <laine@redhat.com> --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 2 ++ tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_3.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_4.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_5.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml | 2 ++ 14 files changed, 19 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 82687dbf39..c4d0e1858c 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -644,6 +644,8 @@ VIR_ENUM_IMPL(virQEMUCaps, "virtio-mem-pci", /* QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI */ "memory-backend-file.reserve", /* QEMU_CAPS_MEMORY_BACKEND_RESERVE */ "piix4.acpi-root-pci-hotplug", /* QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG */ + "piix4.acpi-hotplug-bridge", /* QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE */ + "ich9.acpi-hotplug-bridge", /* QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE */ ); @@ -1472,6 +1474,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsPiix4PM[] = { { "disable_s3", QEMU_CAPS_PIIX_DISABLE_S3, NULL }, { "disable_s4", QEMU_CAPS_PIIX_DISABLE_S4, NULL }, { "acpi-root-pci-hotplug", QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG, NULL }, + { "acpi-pci-hotplug-with-bridge-support", QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsUSBRedir[] = { @@ -1524,6 +1527,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioGpu[] = { static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsICH9[] = { { "disable_s3", QEMU_CAPS_ICH9_DISABLE_S3, NULL }, { "disable_s4", QEMU_CAPS_ICH9_DISABLE_S4, NULL }, + { "acpi-pci-hotplug-with-bridge-support", QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsUSBNECXHCI[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 2bbfc15dc4..e9bd6c8885 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -624,6 +624,8 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI, /* -device virtio-mem-pci */ QEMU_CAPS_MEMORY_BACKEND_RESERVE, /* -object memory-backend-*.reserve= */ QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG, /* -M pc PIIX4_PM.acpi-root-pci-hotplug */ + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE, /* -M pc PIIX4_PM.acpi-pci-hotplug-with-bridge-support */ + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE, /* -M q35 ICH9-LPC.acpi-pci-hotplug-with-bridge-support */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml index d6549d6440..65bfe911dd 100644 --- a/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml @@ -172,6 +172,7 @@ <flag name='am53c974'/> <flag name='cpu-max'/> <flag name='input-linux'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>2011000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100288</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml index 354a95cebc..e4d936886b 100644 --- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml @@ -184,6 +184,7 @@ <flag name='cpu-max'/> <flag name='input-linux'/> <flag name='virtio-blk.queue-size'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>2011090</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100289</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml index cffe482bf6..b903fbe403 100644 --- a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml @@ -190,6 +190,7 @@ <flag name='cpu-max'/> <flag name='input-linux'/> <flag name='virtio-blk.queue-size'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>3000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100239</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_3.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_3.1.0.x86_64.xml index 514e5985ac..143edb4e52 100644 --- a/tests/qemucapabilitiesdata/caps_3.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_3.1.0.x86_64.xml @@ -194,6 +194,7 @@ <flag name='input-linux'/> <flag name='query-display-options'/> <flag name='virtio-blk.queue-size'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>3000092</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100240</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_4.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_4.0.0.x86_64.xml index 5e733fec13..936726939d 100644 --- a/tests/qemucapabilitiesdata/caps_4.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_4.0.0.x86_64.xml @@ -202,6 +202,7 @@ <flag name='input-linux'/> <flag name='query-display-options'/> <flag name='virtio-blk.queue-size'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>4000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100240</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml index ba9ee0dd96..742e71e4ae 100644 --- a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml @@ -209,6 +209,7 @@ <flag name='input-linux'/> <flag name='query-display-options'/> <flag name='virtio-blk.queue-size'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>4001000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100241</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml index 034a770b08..52d0acef3d 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml @@ -220,6 +220,7 @@ <flag name='input-linux'/> <flag name='query-display-options'/> <flag name='virtio-blk.queue-size'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>4002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml index aae5fe018f..ccd7e53ea8 100644 --- a/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml @@ -227,6 +227,7 @@ <flag name='input-linux'/> <flag name='query-display-options'/> <flag name='virtio-blk.queue-size'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>5000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100241</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.xml index e9ae3c5abb..267a3acd9d 100644 --- a/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.xml @@ -230,6 +230,7 @@ <flag name='query-display-options'/> <flag name='virtio-blk.queue-size'/> <flag name='virtio-mem-pci'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>5001000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml index 98b5f34f2b..2be17f0e45 100644 --- a/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml @@ -232,6 +232,7 @@ <flag name='virtio-blk.queue-size'/> <flag name='virtio-mem-pci'/> <flag name='piix4.acpi-root-pci-hotplug'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>5002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml index f13a909314..9070eb85aa 100644 --- a/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml @@ -240,6 +240,7 @@ <flag name='virtio-blk.queue-size'/> <flag name='virtio-mem-pci'/> <flag name='piix4.acpi-root-pci-hotplug'/> + <flag name='piix4.acpi-hotplug-bridge'/> <version>6000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml index 87b37a2b7c..01833aff4b 100644 --- a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml @@ -243,6 +243,8 @@ <flag name='virtio-mem-pci'/> <flag name='memory-backend-file.reserve'/> <flag name='piix4.acpi-root-pci-hotplug'/> + <flag name='piix4.acpi-hotplug-bridge'/> + <flag name='ich9.acpi-hotplug-bridge'/> <version>6001000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> -- 2.25.1

On 10/5/21 1:51 AM, Ani Sinha wrote:
qemu added support for i440fx specific global boolean flag
PIIX4_PM.acpi-pci-hotplug-with-bridge-support
around version 2.1. This flag is enabled by default. When disabled, it turns off acpi pci hotplug for cold plugged pci bridges in i440fx machine types.
Very recently, in qemu version 6.1, the same global option was also added for q35 machine types as well.
ICH9-LPC.acpi-pci-hotplug-with-bridge-support
This option turns on or off acpi based hotplug for cold plugged pcie bridges like pcie root ports. This flag is also enabled by default. Please refer to the following qemu changes:
c0e427d6eb5fef ("hw/acpi/ich9: Enable ACPI PCI hot-plug") 17858a16950860 ("hw/acpi/ich9: Set ACPI PCI hot-plug as default on Q35")
This patch adds the corresponding qemu capabilities in libvirt. For i440fx, the capability is detected as QEMU_CAPS_PIIX_ACPI_HOTPLUG_BRIDGE. For q35, the capability is detected as QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE.
Please note that the test specific qemu capabilities .replies files has already been updated as a part of regular refreshing them when a new qemu version is released. Hence, no updates to those files are required.
Signed-off-by: Ani Sinha <ani@anisinha.ca> Reviewed-by: Laine Stump <laine@redhat.com> --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 2 ++ tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_3.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_4.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_5.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml | 2 ++ 14 files changed, 19 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 82687dbf39..c4d0e1858c 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -644,6 +644,8 @@ VIR_ENUM_IMPL(virQEMUCaps, "virtio-mem-pci", /* QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI */ "memory-backend-file.reserve", /* QEMU_CAPS_MEMORY_BACKEND_RESERVE */ "piix4.acpi-root-pci-hotplug", /* QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG */ + "piix4.acpi-hotplug-bridge", /* QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE */ + "ich9.acpi-hotplug-bridge", /* QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE */
The mechanics of this are all fine, as long as everyone is happy with the names. Reviewed-by: Laine Stump <laine@redhat.com>

This change introduces a new libvirt sub-element <pci> under <features> that can be used to configure all pci related features. Currently the only sub-sub element supported by this sub-element is 'acpi-bridge-hotplug' as shown below: <features> <pci> <acpi-bridge-hotplug state='on|off'/> </pci> </features> The above option is only available for qemu driver and that too for x86 guests only. It is a global option. 'acpi-bridge-hotplug' option enables or disables ACPI hotplug support for cold-plugged pci bridges. Examples of bridges include PCI-PCI bridge (pci-bridge controller) or PCIe-PCI bridges for pc machines and pcie-root-port controller for q35 machines. Being global option, no other bridge specific option 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 following changes in qemu repo: 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 repo: (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). There are use cases where users would still want to use native hotplug. Therefore, this config option enables users to choose either ACPI based hotplug or native hotplug for bridges (for example for pcie root port controller in q35 machines). Qemu capability validation checks have also been added along with related unit tests to exercise the new conf option. Signed-off-by: Ani Sinha <ani@anisinha.ca> --- docs/formatdomain.rst | 11 +++ docs/schemas/domaincommon.rng | 15 ++++ src/conf/domain_conf.c | 89 ++++++++++++++++++- src/conf/domain_conf.h | 9 ++ src/qemu/qemu_validate.c | 46 ++++++++++ .../aarch64-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 33 +++++++ .../q35-acpi-hotplug-bridge-disable.xml | 47 ++++++++++ .../q35-acpi-hotplug-bridge-enable.xml | 47 ++++++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 1 + .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 1 + .../q35-acpi-hotplug-bridge-disable.xml | 1 + .../q35-acpi-hotplug-bridge-enable.xml | 1 + tests/qemuxml2xmltest.c | 14 +++ 15 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index a02802a954..8d916eefa6 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -1847,6 +1847,9 @@ Hypervisors may allow certain CPU / machine features to be toggled on/off. <e820_host state='on'/> <passthrough state='on' mode='share_pt'/> </xen> + <pci> + <acpi-bridge-hotplug state="on"/> + </pci> <pvspinlock state='on'/> <gic version='2'/> <ioapic driver='qemu'/> @@ -1942,6 +1945,14 @@ are: passthrough Enable IOMMU mappings allowing PCI passthrough on, off; mode - optional string sync_pt or share_pt :since:`6.3.0` =========== ============================================== =================================================== ============== +``pci`` + Various PCI bus related features of the hypervisor. + ==================== ======================================================================================== ======= ============================ + Feature Description Value Since + ==================== ======================================================================================== ======= ============================ + acpi-bridge-hotplug Enable ACPI based hotplug on the cold-plugged PCI bridges (pc) and pcie-root-ports (q35) on, off :since:`7.8.0 (QEMU 6.1.0)` + ==================== ======================================================================================== ======= ============================ + ``pmu`` Depending on the ``state`` attribute (values ``on``, ``off``, default ``on``) enable or disable the performance monitoring unit for the guest. diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index ec5bd91740..6f33d1e774 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -6169,6 +6169,9 @@ <optional> <ref name="ioapic"/> </optional> + <optional> + <ref name="pci"/> + </optional> <optional> <ref name="hpt"/> </optional> @@ -6400,6 +6403,18 @@ </element> </define> + <define name="pci"> + <element name="pci"> + <interleave> + <optional> + <element name="acpi-bridge-hotplug"> + <ref name="featurestate"/> + </element> + </optional> + </interleave> + </element> + </define> + <define name="ioapic"> <element name="ioapic"> <attribute name="driver"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b8370f6950..229b75fecc 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -172,6 +172,7 @@ VIR_ENUM_IMPL(virDomainFeature, "cfpc", "sbbc", "ibs", + "pci", ); VIR_ENUM_IMPL(virDomainCapabilitiesPolicy, @@ -212,6 +213,11 @@ VIR_ENUM_IMPL(virDomainXen, "passthrough", ); +VIR_ENUM_IMPL(virDomainPCI, + VIR_DOMAIN_PCI_LAST, + "acpi-bridge-hotplug", +); + VIR_ENUM_IMPL(virDomainXenPassthroughMode, VIR_DOMAIN_XEN_PASSTHROUGH_MODE_LAST, "default", @@ -17536,6 +17542,36 @@ virDomainFeaturesKVMDefParse(virDomainDef *def, return 0; } +static int +virDomainFeaturesPCIDefParse(virDomainDef *def, + xmlNodePtr node) +{ + def->features[VIR_DOMAIN_FEATURE_PCI] = VIR_TRISTATE_SWITCH_ON; + + node = xmlFirstElementChild(node); + while (node) { + int feature; + virTristateSwitch value; + + feature = virDomainPCITypeFromString((const char *)node->name); + if (feature < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported PCI feature: %s"), + node->name); + return -1; + } + + if (virXMLPropTristateSwitch(node, "state", VIR_XML_PROP_REQUIRED, + &value) < 0) + return -1; + + def->pci_features[feature] = value; + + node = xmlNextElementSibling(node); + } + + return 0; +} static int virDomainFeaturesXENDefParse(virDomainDef *def, @@ -17835,6 +17871,10 @@ virDomainFeaturesDefParse(virDomainDef *def, break; } + case VIR_DOMAIN_FEATURE_PCI: + if (virDomainFeaturesPCIDefParse(def, nodes[i]) < 0) + return -1; + case VIR_DOMAIN_FEATURE_LAST: break; } @@ -17843,7 +17883,6 @@ virDomainFeaturesDefParse(virDomainDef *def, return 0; } - static int virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDef *def) { @@ -21521,6 +21560,7 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, case VIR_DOMAIN_FEATURE_HTM: case VIR_DOMAIN_FEATURE_NESTED_HV: case VIR_DOMAIN_FEATURE_CCF_ASSIST: + case VIR_DOMAIN_FEATURE_PCI: if (src->features[i] != dst->features[i]) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("State of feature '%s' differs: " @@ -21777,6 +21817,29 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, } } + /* pci */ + if (src->features[VIR_DOMAIN_FEATURE_PCI] == VIR_TRISTATE_SWITCH_ON) { + for (i = 0; i < VIR_DOMAIN_PCI_LAST; i++) { + switch ((virDomainPCI) i) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (src->pci_features[i] != dst->pci_features[i]) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("State of PCI feature '%s' differs: " + "source: '%s', destination: '%s'"), + virDomainPCITypeToString(i), + virTristateSwitchTypeToString(src->pci_features[i]), + virTristateSwitchTypeToString(dst->pci_features[i])); + return false; + } + + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + } + /* smm */ if (src->features[VIR_DOMAIN_FEATURE_SMM] == VIR_TRISTATE_SWITCH_ON) { if (src->tseg_specified != dst->tseg_specified) { @@ -27932,6 +27995,30 @@ virDomainDefFormatFeatures(virBuffer *buf, virDomainIBSTypeToString(def->features[i])); break; + case VIR_DOMAIN_FEATURE_PCI: + if (def->features[i] != VIR_TRISTATE_SWITCH_ON) + break; + + virBufferAddLit(&childBuf, "<pci>\n"); + virBufferAdjustIndent(&childBuf, 2); + for (j = 0; j < VIR_DOMAIN_PCI_LAST; j++) { + switch ((virDomainPCI) j) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (def->pci_features[j]) + virBufferAsprintf(&childBuf, "<%s state='%s'/>\n", + virDomainPCITypeToString(j), + virTristateSwitchTypeToString( + def->pci_features[j])); + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + virBufferAdjustIndent(&childBuf, -2); + virBufferAddLit(&childBuf, "</pci>\n"); + break; + case VIR_DOMAIN_FEATURE_LAST: break; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e054c1508e..e9902a473d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2043,6 +2043,7 @@ typedef enum { VIR_DOMAIN_FEATURE_CFPC, VIR_DOMAIN_FEATURE_SBBC, VIR_DOMAIN_FEATURE_IBS, + VIR_DOMAIN_FEATURE_PCI, VIR_DOMAIN_FEATURE_LAST } virDomainFeature; @@ -2068,6 +2069,12 @@ typedef enum { VIR_DOMAIN_HYPERV_LAST } virDomainHyperv; +typedef enum { + VIR_DOMAIN_PCI_ACPI_BRIDGE_HP = 0, + + VIR_DOMAIN_PCI_LAST +} virDomainPCI; + typedef enum { VIR_DOMAIN_KVM_HIDDEN = 0, VIR_DOMAIN_KVM_DEDICATED, @@ -2800,6 +2807,7 @@ struct _virDomainDef { int features[VIR_DOMAIN_FEATURE_LAST]; int caps_features[VIR_DOMAIN_PROCES_CAPS_FEATURE_LAST]; int hyperv_features[VIR_DOMAIN_HYPERV_LAST]; + int pci_features[VIR_DOMAIN_PCI_LAST]; int kvm_features[VIR_DOMAIN_KVM_LAST]; int msrs_features[VIR_DOMAIN_MSRS_LAST]; int xen_features[VIR_DOMAIN_XEN_LAST]; @@ -3923,6 +3931,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode); VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode); VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy); VIR_ENUM_DECL(virDomainHyperv); +VIR_ENUM_DECL(virDomainPCI); VIR_ENUM_DECL(virDomainKVM); VIR_ENUM_DECL(virDomainXen); VIR_ENUM_DECL(virDomainXenPassthroughMode); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index c84508cb64..e0e3ca0b10 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -173,6 +173,48 @@ qemuValidateDomainDefPSeriesFeature(const virDomainDef *def, return 0; } +static int +qemuValidateDomainDefPCIFeature(const virDomainDef *def, + virQEMUCaps *qemuCaps, + int feature) +{ + size_t i; + bool q35Dom = qemuDomainIsQ35(def); + bool q35cap = q35Dom && virQEMUCapsGet(qemuCaps, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); + + if (def->features[feature] == VIR_TRISTATE_SWITCH_ABSENT) + return 0; + + for (i = 0; i < VIR_DOMAIN_PCI_LAST; i++) { + if (def->pci_features[i] == VIR_TRISTATE_SWITCH_ABSENT) + continue; + + switch ((virDomainPCI) i) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (!ARCH_IS_X86(def->os.arch)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("acpi-bridge-hotplug is not available " + "for architecture '%s'"), + virArchToString(def->os.arch)); + return -1; + } + if (!q35cap && + !virQEMUCapsGet(qemuCaps, + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("acpi-bridge-hotplug is not available " + "with this QEMU binary")); + return -1; + } + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + return 0; +} static int qemuValidateDomainDefFeatures(const virDomainDef *def, @@ -294,6 +336,10 @@ qemuValidateDomainDefFeatures(const virDomainDef *def, } break; + case VIR_DOMAIN_FEATURE_PCI: + if (qemuValidateDomainDefPCIFeature(def, qemuCaps, i) < 0) + return -1; + break; case VIR_DOMAIN_FEATURE_SMM: case VIR_DOMAIN_FEATURE_KVM: case VIR_DOMAIN_FEATURE_XEN: diff --git a/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..0d5f945bd7 --- /dev/null +++ b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,33 @@ +<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='aarch64' machine='virt'>hvm</type> + <boot dev='network'/> + </os> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</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/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..4482825858 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,33 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml new file mode 100644 index 0000000000..8215ee0d50 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml @@ -0,0 +1,33 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='on'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..2ef3a7231f --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,47 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml new file mode 100644 index 0000000000..2e1b31b0f8 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml @@ -0,0 +1,47 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='on'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml new file mode 120000 index 0000000000..8154897401 --- /dev/null +++ b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml new file mode 120000 index 0000000000..6b9e5492f8 --- /dev/null +++ b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml new file mode 120000 index 0000000000..77719b1325 --- /dev/null +++ b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml new file mode 120000 index 0000000000..3cd8ee569e --- /dev/null +++ b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 69363ef85c..2e622c002f 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -428,6 +428,20 @@ mymain(void) QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); DO_TEST("pc-i440fx-acpi-root-hotplug-enable", QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-disable", + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-enable", + QEMU_CAPS_PIIX4_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("q35-acpi-hotplug-bridge-enable", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); DO_TEST("misc-disable-suspends", QEMU_CAPS_PIIX_DISABLE_S3, QEMU_CAPS_PIIX_DISABLE_S4); -- 2.25.1

On 10/5/21 1:51 AM, Ani Sinha wrote:
This change introduces a new libvirt sub-element <pci> under <features> that can be used to configure all pci related features. Currently the only sub-sub element supported by this sub-element is 'acpi-bridge-hotplug' as shown below:
<features> <pci> <acpi-bridge-hotplug state='on|off'/> </pci> </features>
I guess this is as good a place as any other. Any other opinions?
The above option is only available for qemu driver and that too for x86 guests only. It is a global option.
'acpi-bridge-hotplug' option enables or disables ACPI hotplug support for cold-plugged pci bridges. Examples of bridges include PCI-PCI bridge (pci-bridge controller) or PCIe-PCI bridges for pc machines and pcie-root-port controller for q35 machines. Being global option, no other bridge specific option 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 following changes in qemu repo:
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 repo:
(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). There are use cases where users would still want to use native hotplug. Therefore, this config option enables users to choose either ACPI based hotplug or native hotplug for bridges (for example for pcie root port controller in q35 machines).
Qemu capability validation checks have also been added along with related unit tests to exercise the new conf option.
Signed-off-by: Ani Sinha <ani@anisinha.ca> --- docs/formatdomain.rst | 11 +++ docs/schemas/domaincommon.rng | 15 ++++ src/conf/domain_conf.c | 89 ++++++++++++++++++- src/conf/domain_conf.h | 9 ++ src/qemu/qemu_validate.c | 46 ++++++++++ .../aarch64-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 33 +++++++ .../q35-acpi-hotplug-bridge-disable.xml | 47 ++++++++++ .../q35-acpi-hotplug-bridge-enable.xml | 47 ++++++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 1 + .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 1 + .../q35-acpi-hotplug-bridge-disable.xml | 1 + .../q35-acpi-hotplug-bridge-enable.xml | 1 + tests/qemuxml2xmltest.c | 14 +++ 15 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index a02802a954..8d916eefa6 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -1847,6 +1847,9 @@ Hypervisors may allow certain CPU / machine features to be toggled on/off. <e820_host state='on'/> <passthrough state='on' mode='share_pt'/> </xen> + <pci> + <acpi-bridge-hotplug state="on"/> + </pci> <pvspinlock state='on'/> <gic version='2'/> <ioapic driver='qemu'/> @@ -1942,6 +1945,14 @@ are: passthrough Enable IOMMU mappings allowing PCI passthrough on, off; mode - optional string sync_pt or share_pt :since:`6.3.0` =========== ============================================== =================================================== ==============
+``pci`` + Various PCI bus related features of the hypervisor. + ==================== ======================================================================================== ======= ============================ + Feature Description Value Since + ==================== ======================================================================================== ======= ============================ + acpi-bridge-hotplug Enable ACPI based hotplug on the cold-plugged PCI bridges (pc) and pcie-root-ports (q35) on, off :since:`7.8.0 (QEMU 6.1.0)` + ==================== ======================================================================================== ======= ============================ + ``pmu`` Depending on the ``state`` attribute (values ``on``, ``off``, default ``on``) enable or disable the performance monitoring unit for the guest. diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index ec5bd91740..6f33d1e774 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -6169,6 +6169,9 @@ <optional> <ref name="ioapic"/> </optional> + <optional> + <ref name="pci"/> + </optional> <optional> <ref name="hpt"/> </optional> @@ -6400,6 +6403,18 @@ </element> </define>
+ <define name="pci"> + <element name="pci"> + <interleave> + <optional> + <element name="acpi-bridge-hotplug"> + <ref name="featurestate"/> + </element> + </optional> + </interleave> + </element> + </define> + <define name="ioapic"> <element name="ioapic"> <attribute name="driver"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b8370f6950..229b75fecc 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -172,6 +172,7 @@ VIR_ENUM_IMPL(virDomainFeature, "cfpc", "sbbc", "ibs", + "pci", );
VIR_ENUM_IMPL(virDomainCapabilitiesPolicy, @@ -212,6 +213,11 @@ VIR_ENUM_IMPL(virDomainXen, "passthrough", );
+VIR_ENUM_IMPL(virDomainPCI, + VIR_DOMAIN_PCI_LAST, + "acpi-bridge-hotplug", +); + VIR_ENUM_IMPL(virDomainXenPassthroughMode, VIR_DOMAIN_XEN_PASSTHROUGH_MODE_LAST, "default", @@ -17536,6 +17542,36 @@ virDomainFeaturesKVMDefParse(virDomainDef *def, return 0; }
+static int +virDomainFeaturesPCIDefParse(virDomainDef *def, + xmlNodePtr node) +{ + def->features[VIR_DOMAIN_FEATURE_PCI] = VIR_TRISTATE_SWITCH_ON; + + node = xmlFirstElementChild(node); + while (node) { + int feature; + virTristateSwitch value; + + feature = virDomainPCITypeFromString((const char *)node->name); + if (feature < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported PCI feature: %s"), + node->name); + return -1; + } + + if (virXMLPropTristateSwitch(node, "state", VIR_XML_PROP_REQUIRED, + &value) < 0) + return -1; + + def->pci_features[feature] = value; + + node = xmlNextElementSibling(node); + } + + return 0; +}
Hmm. On one hand, this is adding a new case of manually iterating through the nodes of an XML document, which I thought we were trying to get rid of. On the other hand, it was obviously based on the existing code for the other subelements of the <features> element (which are the only other remaining uses of xmlFirstElementChild()) so either that code was purposefully left that way (and not reworked to use all of Tim's nice helper functions) in order to detect unknown subelements at parse time (which we usually don't do (and which has always kind of bothered me)), or there was some issue that required more thought so it was left as an exercise for later, in which case this new function could be redone at the same time as the others. So unless someone else has a problem with it, I'm okay with putting it in. Reviewed-by: Laine Stump <laine@redhat.com> (as long as there are no objections to the name of the element in the XML, and adding a new function that uses the "old" parsing method).
static int virDomainFeaturesXENDefParse(virDomainDef *def, @@ -17835,6 +17871,10 @@ virDomainFeaturesDefParse(virDomainDef *def, break; }
+ case VIR_DOMAIN_FEATURE_PCI: + if (virDomainFeaturesPCIDefParse(def, nodes[i]) < 0) + return -1; + case VIR_DOMAIN_FEATURE_LAST: break; } @@ -17843,7 +17883,6 @@ virDomainFeaturesDefParse(virDomainDef *def, return 0; }
- static int virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDef *def) { @@ -21521,6 +21560,7 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, case VIR_DOMAIN_FEATURE_HTM: case VIR_DOMAIN_FEATURE_NESTED_HV: case VIR_DOMAIN_FEATURE_CCF_ASSIST: + case VIR_DOMAIN_FEATURE_PCI: if (src->features[i] != dst->features[i]) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("State of feature '%s' differs: " @@ -21777,6 +21817,29 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, } }
+ /* pci */ + if (src->features[VIR_DOMAIN_FEATURE_PCI] == VIR_TRISTATE_SWITCH_ON) { + for (i = 0; i < VIR_DOMAIN_PCI_LAST; i++) { + switch ((virDomainPCI) i) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (src->pci_features[i] != dst->pci_features[i]) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("State of PCI feature '%s' differs: " + "source: '%s', destination: '%s'"), + virDomainPCITypeToString(i), + virTristateSwitchTypeToString(src->pci_features[i]), + virTristateSwitchTypeToString(dst->pci_features[i])); + return false; + } + + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + } + /* smm */ if (src->features[VIR_DOMAIN_FEATURE_SMM] == VIR_TRISTATE_SWITCH_ON) { if (src->tseg_specified != dst->tseg_specified) { @@ -27932,6 +27995,30 @@ virDomainDefFormatFeatures(virBuffer *buf, virDomainIBSTypeToString(def->features[i])); break;
+ case VIR_DOMAIN_FEATURE_PCI: + if (def->features[i] != VIR_TRISTATE_SWITCH_ON) + break; + + virBufferAddLit(&childBuf, "<pci>\n"); + virBufferAdjustIndent(&childBuf, 2); + for (j = 0; j < VIR_DOMAIN_PCI_LAST; j++) { + switch ((virDomainPCI) j) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (def->pci_features[j]) + virBufferAsprintf(&childBuf, "<%s state='%s'/>\n", + virDomainPCITypeToString(j), + virTristateSwitchTypeToString( + def->pci_features[j])); + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + virBufferAdjustIndent(&childBuf, -2); + virBufferAddLit(&childBuf, "</pci>\n"); + break; + case VIR_DOMAIN_FEATURE_LAST: break; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e054c1508e..e9902a473d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2043,6 +2043,7 @@ typedef enum { VIR_DOMAIN_FEATURE_CFPC, VIR_DOMAIN_FEATURE_SBBC, VIR_DOMAIN_FEATURE_IBS, + VIR_DOMAIN_FEATURE_PCI,
VIR_DOMAIN_FEATURE_LAST } virDomainFeature; @@ -2068,6 +2069,12 @@ typedef enum { VIR_DOMAIN_HYPERV_LAST } virDomainHyperv;
+typedef enum { + VIR_DOMAIN_PCI_ACPI_BRIDGE_HP = 0,
With so many other identifiers being so long and verbose, I think we can go ahead and call this one VIR_DOMAIN_PCI_ACPI_BRIDGE_HOTPLUG. Assuming no other problems, I can change this before pushing.
+ + VIR_DOMAIN_PCI_LAST +} virDomainPCI; + typedef enum { VIR_DOMAIN_KVM_HIDDEN = 0, VIR_DOMAIN_KVM_DEDICATED, @@ -2800,6 +2807,7 @@ struct _virDomainDef { int features[VIR_DOMAIN_FEATURE_LAST]; int caps_features[VIR_DOMAIN_PROCES_CAPS_FEATURE_LAST]; int hyperv_features[VIR_DOMAIN_HYPERV_LAST]; + int pci_features[VIR_DOMAIN_PCI_LAST]; int kvm_features[VIR_DOMAIN_KVM_LAST]; int msrs_features[VIR_DOMAIN_MSRS_LAST]; int xen_features[VIR_DOMAIN_XEN_LAST]; @@ -3923,6 +3931,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode); VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode); VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy); VIR_ENUM_DECL(virDomainHyperv); +VIR_ENUM_DECL(virDomainPCI); VIR_ENUM_DECL(virDomainKVM); VIR_ENUM_DECL(virDomainXen); VIR_ENUM_DECL(virDomainXenPassthroughMode); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index c84508cb64..e0e3ca0b10 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -173,6 +173,48 @@ qemuValidateDomainDefPSeriesFeature(const virDomainDef *def, return 0; }
+static int +qemuValidateDomainDefPCIFeature(const virDomainDef *def, + virQEMUCaps *qemuCaps, + int feature) +{ + size_t i; + bool q35Dom = qemuDomainIsQ35(def); + bool q35cap = q35Dom && virQEMUCapsGet(qemuCaps, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); + + if (def->features[feature] == VIR_TRISTATE_SWITCH_ABSENT) + return 0; + + for (i = 0; i < VIR_DOMAIN_PCI_LAST; i++) { + if (def->pci_features[i] == VIR_TRISTATE_SWITCH_ABSENT) + continue; + + switch ((virDomainPCI) i) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (!ARCH_IS_X86(def->os.arch)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("acpi-bridge-hotplug is not available " + "for architecture '%s'"), + virArchToString(def->os.arch)); + return -1; + } + if (!q35cap && + !virQEMUCapsGet(qemuCaps, + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("acpi-bridge-hotplug is not available " + "with this QEMU binary")); + return -1; + } + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + return 0; +}
static int qemuValidateDomainDefFeatures(const virDomainDef *def, @@ -294,6 +336,10 @@ qemuValidateDomainDefFeatures(const virDomainDef *def, } break;
+ case VIR_DOMAIN_FEATURE_PCI: + if (qemuValidateDomainDefPCIFeature(def, qemuCaps, i) < 0) + return -1; + break; case VIR_DOMAIN_FEATURE_SMM: case VIR_DOMAIN_FEATURE_KVM: case VIR_DOMAIN_FEATURE_XEN: diff --git a/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..0d5f945bd7 --- /dev/null +++ b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,33 @@ +<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='aarch64' machine='virt'>hvm</type> + <boot dev='network'/> + </os> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</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/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..4482825858 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,33 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml new file mode 100644 index 0000000000..8215ee0d50 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml @@ -0,0 +1,33 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='on'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..2ef3a7231f --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,47 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml new file mode 100644 index 0000000000..2e1b31b0f8 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml @@ -0,0 +1,47 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='on'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml new file mode 120000 index 0000000000..8154897401 --- /dev/null +++ b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml new file mode 120000 index 0000000000..6b9e5492f8 --- /dev/null +++ b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml new file mode 120000 index 0000000000..77719b1325 --- /dev/null +++ b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml new file mode 120000 index 0000000000..3cd8ee569e --- /dev/null +++ b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 69363ef85c..2e622c002f 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -428,6 +428,20 @@ mymain(void) QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); DO_TEST("pc-i440fx-acpi-root-hotplug-enable", QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-disable", + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-enable", + QEMU_CAPS_PIIX4_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("q35-acpi-hotplug-bridge-enable", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); DO_TEST("misc-disable-suspends", QEMU_CAPS_PIIX_DISABLE_S3, QEMU_CAPS_PIIX_DISABLE_S4);

On 10/7/21 11:12 PM, Laine Stump wrote:
@@ -27932,6 +27995,30 @@ virDomainDefFormatFeatures(virBuffer *buf,
virDomainIBSTypeToString(def->features[i])); break; + case VIR_DOMAIN_FEATURE_PCI: + if (def->features[i] != VIR_TRISTATE_SWITCH_ON) + break; + + virBufferAddLit(&childBuf, "<pci>\n"); + virBufferAdjustIndent(&childBuf, 2); + for (j = 0; j < VIR_DOMAIN_PCI_LAST; j++) { + switch ((virDomainPCI) j) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (def->pci_features[j])
Oops, I missed this the first time I went through - this should compare to VIR_TRISTATE_SWITCH_ABSENT rather than just checking for non-0. It ends up being the same thing, but you never know - some day someone may decide to change the values of the VIR_TRISTATE_* enums just for fun...
+ virBufferAsprintf(&childBuf, "<%s state='%s'/>\n", + virDomainPCITypeToString(j), + virTristateSwitchTypeToString( + def->pci_features[j])); + break;

On 10/5/21 1:51 AM, Ani Sinha wrote:
This change introduces a new libvirt sub-element <pci> under <features> that can be used to configure all pci related features. Currently the only sub-sub element supported by this sub-element is 'acpi-bridge-hotplug' as shown below:
<features> <pci> <acpi-bridge-hotplug state='on|off'/> </pci> </features>
The above option is only available for qemu driver and that too for x86 guests only. It is a global option.
'acpi-bridge-hotplug' option enables or disables ACPI hotplug support for cold-plugged pci bridges. Examples of bridges include PCI-PCI bridge (pci-bridge controller) or PCIe-PCI bridges for pc machines and pcie-root-port controller for q35 machines. Being global option, no other bridge specific option 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 following changes in qemu repo:
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 repo:
(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). There are use cases where users would still want to use native hotplug. Therefore, this config option enables users to choose either ACPI based hotplug or native hotplug for bridges (for example for pcie root port controller in q35 machines).
Qemu capability validation checks have also been added along with related unit tests to exercise the new conf option.
Signed-off-by: Ani Sinha <ani@anisinha.ca> --- docs/formatdomain.rst | 11 +++ docs/schemas/domaincommon.rng | 15 ++++ src/conf/domain_conf.c | 89 ++++++++++++++++++- src/conf/domain_conf.h | 9 ++ src/qemu/qemu_validate.c | 46 ++++++++++ .../aarch64-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 33 +++++++ .../q35-acpi-hotplug-bridge-disable.xml | 47 ++++++++++ .../q35-acpi-hotplug-bridge-enable.xml | 47 ++++++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 1 + .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 1 + .../q35-acpi-hotplug-bridge-disable.xml | 1 + .../q35-acpi-hotplug-bridge-enable.xml | 1 + tests/qemuxml2xmltest.c | 14 +++ 15 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index a02802a954..8d916eefa6 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -1847,6 +1847,9 @@ Hypervisors may allow certain CPU / machine features to be toggled on/off. <e820_host state='on'/> <passthrough state='on' mode='share_pt'/> </xen> + <pci> + <acpi-bridge-hotplug state="on"/> + </pci> <pvspinlock state='on'/> <gic version='2'/> <ioapic driver='qemu'/> @@ -1942,6 +1945,14 @@ are: passthrough Enable IOMMU mappings allowing PCI passthrough on, off; mode - optional string sync_pt or share_pt :since:`6.3.0` =========== ============================================== =================================================== ==============
+``pci`` + Various PCI bus related features of the hypervisor. + ==================== ======================================================================================== ======= ============================ + Feature Description Value Since + ==================== ======================================================================================== ======= ============================ + acpi-bridge-hotplug Enable ACPI based hotplug on the cold-plugged PCI bridges (pc) and pcie-root-ports (q35) on, off :since:`7.8.0 (QEMU 6.1.0)`
Weren't the qemu properties there in a much earlier version of QEMU? (Oh, and also it needs to say 7.9.0 instead of 7.8.0) Somewhere we need to put the extra info that on 440fx machinetypes ACPI is on by default, and disabling it means that only SHPC hotplug is available, while on q35 machinetypes, it is off by default until QEMU 6.1.0, and enabling it has the side-effect of disabling native PCIe hotplug, while disabling (on qemu 6.1.0+) also has the side-effect of enabling native PCIe hotplug.
+ ==================== ======================================================================================== ======= ============================ + ``pmu`` Depending on the ``state`` attribute (values ``on``, ``off``, default ``on``) enable or disable the performance monitoring unit for the guest. diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index ec5bd91740..6f33d1e774 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -6169,6 +6169,9 @@ <optional> <ref name="ioapic"/> </optional> + <optional> + <ref name="pci"/> + </optional> <optional> <ref name="hpt"/> </optional> @@ -6400,6 +6403,18 @@ </element> </define>
+ <define name="pci"> + <element name="pci"> + <interleave> + <optional> + <element name="acpi-bridge-hotplug"> + <ref name="featurestate"/> + </element> + </optional> + </interleave> + </element> + </define> + <define name="ioapic"> <element name="ioapic"> <attribute name="driver"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b8370f6950..229b75fecc 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -172,6 +172,7 @@ VIR_ENUM_IMPL(virDomainFeature, "cfpc", "sbbc", "ibs", + "pci", );
VIR_ENUM_IMPL(virDomainCapabilitiesPolicy, @@ -212,6 +213,11 @@ VIR_ENUM_IMPL(virDomainXen, "passthrough", );
+VIR_ENUM_IMPL(virDomainPCI, + VIR_DOMAIN_PCI_LAST, + "acpi-bridge-hotplug", +); + VIR_ENUM_IMPL(virDomainXenPassthroughMode, VIR_DOMAIN_XEN_PASSTHROUGH_MODE_LAST, "default", @@ -17536,6 +17542,36 @@ virDomainFeaturesKVMDefParse(virDomainDef *def, return 0; }
+static int +virDomainFeaturesPCIDefParse(virDomainDef *def, + xmlNodePtr node) +{ + def->features[VIR_DOMAIN_FEATURE_PCI] = VIR_TRISTATE_SWITCH_ON; + + node = xmlFirstElementChild(node); + while (node) { + int feature; + virTristateSwitch value; + + feature = virDomainPCITypeFromString((const char *)node->name); + if (feature < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported PCI feature: %s"), + node->name); + return -1; + } + + if (virXMLPropTristateSwitch(node, "state", VIR_XML_PROP_REQUIRED, + &value) < 0) + return -1; + + def->pci_features[feature] = value; + + node = xmlNextElementSibling(node); + } + + return 0; +}
static int virDomainFeaturesXENDefParse(virDomainDef *def, @@ -17835,6 +17871,10 @@ virDomainFeaturesDefParse(virDomainDef *def, break; }
+ case VIR_DOMAIN_FEATURE_PCI: + if (virDomainFeaturesPCIDefParse(def, nodes[i]) < 0) + return -1; + case VIR_DOMAIN_FEATURE_LAST: break; } @@ -17843,7 +17883,6 @@ virDomainFeaturesDefParse(virDomainDef *def, return 0; }
- static int virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDef *def) { @@ -21521,6 +21560,7 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, case VIR_DOMAIN_FEATURE_HTM: case VIR_DOMAIN_FEATURE_NESTED_HV: case VIR_DOMAIN_FEATURE_CCF_ASSIST: + case VIR_DOMAIN_FEATURE_PCI: if (src->features[i] != dst->features[i]) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("State of feature '%s' differs: " @@ -21777,6 +21817,29 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, } }
+ /* pci */ + if (src->features[VIR_DOMAIN_FEATURE_PCI] == VIR_TRISTATE_SWITCH_ON) { + for (i = 0; i < VIR_DOMAIN_PCI_LAST; i++) { + switch ((virDomainPCI) i) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (src->pci_features[i] != dst->pci_features[i]) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("State of PCI feature '%s' differs: " + "source: '%s', destination: '%s'"), + virDomainPCITypeToString(i), + virTristateSwitchTypeToString(src->pci_features[i]), + virTristateSwitchTypeToString(dst->pci_features[i])); + return false; + } + + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + } + /* smm */ if (src->features[VIR_DOMAIN_FEATURE_SMM] == VIR_TRISTATE_SWITCH_ON) { if (src->tseg_specified != dst->tseg_specified) { @@ -27932,6 +27995,30 @@ virDomainDefFormatFeatures(virBuffer *buf, virDomainIBSTypeToString(def->features[i])); break;
+ case VIR_DOMAIN_FEATURE_PCI: + if (def->features[i] != VIR_TRISTATE_SWITCH_ON) + break; + + virBufferAddLit(&childBuf, "<pci>\n"); + virBufferAdjustIndent(&childBuf, 2); + for (j = 0; j < VIR_DOMAIN_PCI_LAST; j++) { + switch ((virDomainPCI) j) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (def->pci_features[j]) + virBufferAsprintf(&childBuf, "<%s state='%s'/>\n", + virDomainPCITypeToString(j), + virTristateSwitchTypeToString( + def->pci_features[j])); + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + virBufferAdjustIndent(&childBuf, -2); + virBufferAddLit(&childBuf, "</pci>\n"); + break; + case VIR_DOMAIN_FEATURE_LAST: break; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e054c1508e..e9902a473d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2043,6 +2043,7 @@ typedef enum { VIR_DOMAIN_FEATURE_CFPC, VIR_DOMAIN_FEATURE_SBBC, VIR_DOMAIN_FEATURE_IBS, + VIR_DOMAIN_FEATURE_PCI,
VIR_DOMAIN_FEATURE_LAST } virDomainFeature; @@ -2068,6 +2069,12 @@ typedef enum { VIR_DOMAIN_HYPERV_LAST } virDomainHyperv;
+typedef enum { + VIR_DOMAIN_PCI_ACPI_BRIDGE_HP = 0, + + VIR_DOMAIN_PCI_LAST +} virDomainPCI; + typedef enum { VIR_DOMAIN_KVM_HIDDEN = 0, VIR_DOMAIN_KVM_DEDICATED, @@ -2800,6 +2807,7 @@ struct _virDomainDef { int features[VIR_DOMAIN_FEATURE_LAST]; int caps_features[VIR_DOMAIN_PROCES_CAPS_FEATURE_LAST]; int hyperv_features[VIR_DOMAIN_HYPERV_LAST]; + int pci_features[VIR_DOMAIN_PCI_LAST]; int kvm_features[VIR_DOMAIN_KVM_LAST]; int msrs_features[VIR_DOMAIN_MSRS_LAST]; int xen_features[VIR_DOMAIN_XEN_LAST]; @@ -3923,6 +3931,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode); VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode); VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy); VIR_ENUM_DECL(virDomainHyperv); +VIR_ENUM_DECL(virDomainPCI); VIR_ENUM_DECL(virDomainKVM); VIR_ENUM_DECL(virDomainXen); VIR_ENUM_DECL(virDomainXenPassthroughMode); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index c84508cb64..e0e3ca0b10 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -173,6 +173,48 @@ qemuValidateDomainDefPSeriesFeature(const virDomainDef *def, return 0; }
+static int +qemuValidateDomainDefPCIFeature(const virDomainDef *def, + virQEMUCaps *qemuCaps, + int feature) +{ + size_t i; + bool q35Dom = qemuDomainIsQ35(def); + bool q35cap = q35Dom && virQEMUCapsGet(qemuCaps, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); + + if (def->features[feature] == VIR_TRISTATE_SWITCH_ABSENT) + return 0; + + for (i = 0; i < VIR_DOMAIN_PCI_LAST; i++) { + if (def->pci_features[i] == VIR_TRISTATE_SWITCH_ABSENT) + continue; + + switch ((virDomainPCI) i) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (!ARCH_IS_X86(def->os.arch)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("acpi-bridge-hotplug is not available " + "for architecture '%s'"), + virArchToString(def->os.arch)); + return -1; + } + if (!q35cap && + !virQEMUCapsGet(qemuCaps, + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("acpi-bridge-hotplug is not available " + "with this QEMU binary")); + return -1; + } + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + return 0; +}
static int qemuValidateDomainDefFeatures(const virDomainDef *def, @@ -294,6 +336,10 @@ qemuValidateDomainDefFeatures(const virDomainDef *def, } break;
+ case VIR_DOMAIN_FEATURE_PCI: + if (qemuValidateDomainDefPCIFeature(def, qemuCaps, i) < 0) + return -1; + break; case VIR_DOMAIN_FEATURE_SMM: case VIR_DOMAIN_FEATURE_KVM: case VIR_DOMAIN_FEATURE_XEN: diff --git a/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..0d5f945bd7 --- /dev/null +++ b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,33 @@ +<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='aarch64' machine='virt'>hvm</type> + <boot dev='network'/> + </os> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</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/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..4482825858 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,33 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml new file mode 100644 index 0000000000..8215ee0d50 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml @@ -0,0 +1,33 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='on'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..2ef3a7231f --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,47 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml new file mode 100644 index 0000000000..2e1b31b0f8 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml @@ -0,0 +1,47 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='on'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml new file mode 120000 index 0000000000..8154897401 --- /dev/null +++ b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml new file mode 120000 index 0000000000..6b9e5492f8 --- /dev/null +++ b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml new file mode 120000 index 0000000000..77719b1325 --- /dev/null +++ b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml new file mode 120000 index 0000000000..3cd8ee569e --- /dev/null +++ b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 69363ef85c..2e622c002f 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -428,6 +428,20 @@ mymain(void) QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); DO_TEST("pc-i440fx-acpi-root-hotplug-enable", QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-disable", + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-enable", + QEMU_CAPS_PIIX4_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("q35-acpi-hotplug-bridge-enable", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); DO_TEST("misc-disable-suspends", QEMU_CAPS_PIIX_DISABLE_S3, QEMU_CAPS_PIIX_DISABLE_S4);

On Fri, 8 Oct 2021, Laine Stump wrote:
On 10/5/21 1:51 AM, Ani Sinha wrote:
This change introduces a new libvirt sub-element <pci> under <features> that can be used to configure all pci related features. Currently the only sub-sub element supported by this sub-element is 'acpi-bridge-hotplug' as shown below:
<features> <pci> <acpi-bridge-hotplug state='on|off'/> </pci> </features>
The above option is only available for qemu driver and that too for x86 guests only. It is a global option.
'acpi-bridge-hotplug' option enables or disables ACPI hotplug support for cold-plugged pci bridges. Examples of bridges include PCI-PCI bridge (pci-bridge controller) or PCIe-PCI bridges for pc machines and pcie-root-port controller for q35 machines. Being global option, no other bridge specific option 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 following changes in qemu repo:
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 repo:
(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). There are use cases where users would still want to use native hotplug. Therefore, this config option enables users to choose either ACPI based hotplug or native hotplug for bridges (for example for pcie root port controller in q35 machines).
Qemu capability validation checks have also been added along with related unit tests to exercise the new conf option.
Signed-off-by: Ani Sinha <ani@anisinha.ca> --- docs/formatdomain.rst | 11 +++ docs/schemas/domaincommon.rng | 15 ++++ src/conf/domain_conf.c | 89 ++++++++++++++++++- src/conf/domain_conf.h | 9 ++ src/qemu/qemu_validate.c | 46 ++++++++++ .../aarch64-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 33 +++++++ .../q35-acpi-hotplug-bridge-disable.xml | 47 ++++++++++ .../q35-acpi-hotplug-bridge-enable.xml | 47 ++++++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 1 + .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 1 + .../q35-acpi-hotplug-bridge-disable.xml | 1 + .../q35-acpi-hotplug-bridge-enable.xml | 1 + tests/qemuxml2xmltest.c | 14 +++ 15 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index a02802a954..8d916eefa6 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -1847,6 +1847,9 @@ Hypervisors may allow certain CPU / machine features to be toggled on/off. <e820_host state='on'/> <passthrough state='on' mode='share_pt'/> </xen> + <pci> + <acpi-bridge-hotplug state="on"/> + </pci> <pvspinlock state='on'/> <gic version='2'/> <ioapic driver='qemu'/> @@ -1942,6 +1945,14 @@ are: passthrough Enable IOMMU mappings allowing PCI passthrough on, off; mode - optional string sync_pt or share_pt :since:`6.3.0` =========== ============================================== =================================================== ============== +``pci`` + Various PCI bus related features of the hypervisor. + ==================== ======================================================================================== ======= ============================ + Feature Description Value Since + ==================== ======================================================================================== ======= ============================ + acpi-bridge-hotplug Enable ACPI based hotplug on the cold-plugged PCI bridges (pc) and pcie-root-ports (q35) on, off :since:`7.8.0 (QEMU 6.1.0)`
Weren't the qemu properties there in a much earlier version of QEMU? (Oh, and also it needs to say 7.9.0 instead of 7.8.0)
That was for i440fx. I took the higher version.
Somewhere we need to put the extra info that on 440fx machinetypes ACPI is on by default, and disabling it means that only SHPC hotplug is available, while on q35 machinetypes, it is off by default until QEMU 6.1.0, and enabling it has the side-effect of disabling native PCIe hotplug, while disabling (on qemu 6.1.0+) also has the side-effect of enabling native PCIe hotplug.
I have added a note in v7.
+ ==================== ======================================================================================== ======= ============================ + ``pmu`` Depending on the ``state`` attribute (values ``on``, ``off``, default ``on``) enable or disable the performance monitoring unit for the guest. diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index ec5bd91740..6f33d1e774 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -6169,6 +6169,9 @@ <optional> <ref name="ioapic"/> </optional> + <optional> + <ref name="pci"/> + </optional> <optional> <ref name="hpt"/> </optional> @@ -6400,6 +6403,18 @@ </element> </define> + <define name="pci"> + <element name="pci"> + <interleave> + <optional> + <element name="acpi-bridge-hotplug"> + <ref name="featurestate"/> + </element> + </optional> + </interleave> + </element> + </define> + <define name="ioapic"> <element name="ioapic"> <attribute name="driver"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b8370f6950..229b75fecc 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -172,6 +172,7 @@ VIR_ENUM_IMPL(virDomainFeature, "cfpc", "sbbc", "ibs", + "pci", ); VIR_ENUM_IMPL(virDomainCapabilitiesPolicy, @@ -212,6 +213,11 @@ VIR_ENUM_IMPL(virDomainXen, "passthrough", ); +VIR_ENUM_IMPL(virDomainPCI, + VIR_DOMAIN_PCI_LAST, + "acpi-bridge-hotplug", +); + VIR_ENUM_IMPL(virDomainXenPassthroughMode, VIR_DOMAIN_XEN_PASSTHROUGH_MODE_LAST, "default", @@ -17536,6 +17542,36 @@ virDomainFeaturesKVMDefParse(virDomainDef *def, return 0; } +static int +virDomainFeaturesPCIDefParse(virDomainDef *def, + xmlNodePtr node) +{ + def->features[VIR_DOMAIN_FEATURE_PCI] = VIR_TRISTATE_SWITCH_ON; + + node = xmlFirstElementChild(node); + while (node) { + int feature; + virTristateSwitch value; + + feature = virDomainPCITypeFromString((const char *)node->name); + if (feature < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported PCI feature: %s"), + node->name); + return -1; + } + + if (virXMLPropTristateSwitch(node, "state", VIR_XML_PROP_REQUIRED, + &value) < 0) + return -1; + + def->pci_features[feature] = value; + + node = xmlNextElementSibling(node); + } + + return 0; +} static int virDomainFeaturesXENDefParse(virDomainDef *def, @@ -17835,6 +17871,10 @@ virDomainFeaturesDefParse(virDomainDef *def, break; } + case VIR_DOMAIN_FEATURE_PCI: + if (virDomainFeaturesPCIDefParse(def, nodes[i]) < 0) + return -1; + case VIR_DOMAIN_FEATURE_LAST: break; } @@ -17843,7 +17883,6 @@ virDomainFeaturesDefParse(virDomainDef *def, return 0; } - static int virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDef *def) { @@ -21521,6 +21560,7 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, case VIR_DOMAIN_FEATURE_HTM: case VIR_DOMAIN_FEATURE_NESTED_HV: case VIR_DOMAIN_FEATURE_CCF_ASSIST: + case VIR_DOMAIN_FEATURE_PCI: if (src->features[i] != dst->features[i]) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("State of feature '%s' differs: " @@ -21777,6 +21817,29 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, } } + /* pci */ + if (src->features[VIR_DOMAIN_FEATURE_PCI] == VIR_TRISTATE_SWITCH_ON) { + for (i = 0; i < VIR_DOMAIN_PCI_LAST; i++) { + switch ((virDomainPCI) i) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (src->pci_features[i] != dst->pci_features[i]) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("State of PCI feature '%s' differs: " + "source: '%s', destination: '%s'"), + virDomainPCITypeToString(i), + virTristateSwitchTypeToString(src->pci_features[i]), + virTristateSwitchTypeToString(dst->pci_features[i])); + return false; + } + + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + } + /* smm */ if (src->features[VIR_DOMAIN_FEATURE_SMM] == VIR_TRISTATE_SWITCH_ON) { if (src->tseg_specified != dst->tseg_specified) { @@ -27932,6 +27995,30 @@ virDomainDefFormatFeatures(virBuffer *buf, virDomainIBSTypeToString(def->features[i])); break; + case VIR_DOMAIN_FEATURE_PCI: + if (def->features[i] != VIR_TRISTATE_SWITCH_ON) + break; + + virBufferAddLit(&childBuf, "<pci>\n"); + virBufferAdjustIndent(&childBuf, 2); + for (j = 0; j < VIR_DOMAIN_PCI_LAST; j++) { + switch ((virDomainPCI) j) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (def->pci_features[j]) + virBufferAsprintf(&childBuf, "<%s state='%s'/>\n", + virDomainPCITypeToString(j), + virTristateSwitchTypeToString( + def->pci_features[j])); + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + virBufferAdjustIndent(&childBuf, -2); + virBufferAddLit(&childBuf, "</pci>\n"); + break; + case VIR_DOMAIN_FEATURE_LAST: break; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e054c1508e..e9902a473d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2043,6 +2043,7 @@ typedef enum { VIR_DOMAIN_FEATURE_CFPC, VIR_DOMAIN_FEATURE_SBBC, VIR_DOMAIN_FEATURE_IBS, + VIR_DOMAIN_FEATURE_PCI, VIR_DOMAIN_FEATURE_LAST } virDomainFeature; @@ -2068,6 +2069,12 @@ typedef enum { VIR_DOMAIN_HYPERV_LAST } virDomainHyperv; +typedef enum { + VIR_DOMAIN_PCI_ACPI_BRIDGE_HP = 0, + + VIR_DOMAIN_PCI_LAST +} virDomainPCI; + typedef enum { VIR_DOMAIN_KVM_HIDDEN = 0, VIR_DOMAIN_KVM_DEDICATED, @@ -2800,6 +2807,7 @@ struct _virDomainDef { int features[VIR_DOMAIN_FEATURE_LAST]; int caps_features[VIR_DOMAIN_PROCES_CAPS_FEATURE_LAST]; int hyperv_features[VIR_DOMAIN_HYPERV_LAST]; + int pci_features[VIR_DOMAIN_PCI_LAST]; int kvm_features[VIR_DOMAIN_KVM_LAST]; int msrs_features[VIR_DOMAIN_MSRS_LAST]; int xen_features[VIR_DOMAIN_XEN_LAST]; @@ -3923,6 +3931,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode); VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode); VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy); VIR_ENUM_DECL(virDomainHyperv); +VIR_ENUM_DECL(virDomainPCI); VIR_ENUM_DECL(virDomainKVM); VIR_ENUM_DECL(virDomainXen); VIR_ENUM_DECL(virDomainXenPassthroughMode); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index c84508cb64..e0e3ca0b10 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -173,6 +173,48 @@ qemuValidateDomainDefPSeriesFeature(const virDomainDef *def, return 0; } +static int +qemuValidateDomainDefPCIFeature(const virDomainDef *def, + virQEMUCaps *qemuCaps, + int feature) +{ + size_t i; + bool q35Dom = qemuDomainIsQ35(def); + bool q35cap = q35Dom && virQEMUCapsGet(qemuCaps, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); + + if (def->features[feature] == VIR_TRISTATE_SWITCH_ABSENT) + return 0; + + for (i = 0; i < VIR_DOMAIN_PCI_LAST; i++) { + if (def->pci_features[i] == VIR_TRISTATE_SWITCH_ABSENT) + continue; + + switch ((virDomainPCI) i) { + case VIR_DOMAIN_PCI_ACPI_BRIDGE_HP: + if (!ARCH_IS_X86(def->os.arch)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("acpi-bridge-hotplug is not available " + "for architecture '%s'"), + virArchToString(def->os.arch)); + return -1; + } + if (!q35cap && + !virQEMUCapsGet(qemuCaps, + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("acpi-bridge-hotplug is not available " + "with this QEMU binary")); + return -1; + } + break; + + case VIR_DOMAIN_PCI_LAST: + break; + } + } + return 0; +} static int qemuValidateDomainDefFeatures(const virDomainDef *def, @@ -294,6 +336,10 @@ qemuValidateDomainDefFeatures(const virDomainDef *def, } break; + case VIR_DOMAIN_FEATURE_PCI: + if (qemuValidateDomainDefPCIFeature(def, qemuCaps, i) < 0) + return -1; + break; case VIR_DOMAIN_FEATURE_SMM: case VIR_DOMAIN_FEATURE_KVM: case VIR_DOMAIN_FEATURE_XEN: diff --git a/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..0d5f945bd7 --- /dev/null +++ b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,33 @@ +<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='aarch64' machine='virt'>hvm</type> + <boot dev='network'/> + </os> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</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/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..4482825858 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,33 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml new file mode 100644 index 0000000000..8215ee0d50 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml @@ -0,0 +1,33 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='on'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml new file mode 100644 index 0000000000..2ef3a7231f --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml @@ -0,0 +1,47 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='off'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml new file mode 100644 index 0000000000..2e1b31b0f8 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml @@ -0,0 +1,47 @@ +<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> + <features> + <pci> + <acpi-bridge-hotplug state='on'/> + </pci> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <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/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml new file mode 120000 index 0000000000..8154897401 --- /dev/null +++ b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml new file mode 120000 index 0000000000..6b9e5492f8 --- /dev/null +++ b/tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml new file mode 120000 index 0000000000..77719b1325 --- /dev/null +++ b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml new file mode 120000 index 0000000000..3cd8ee569e --- /dev/null +++ b/tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 69363ef85c..2e622c002f 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -428,6 +428,20 @@ mymain(void) QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); DO_TEST("pc-i440fx-acpi-root-hotplug-enable", QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-disable", + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-enable", + QEMU_CAPS_PIIX4_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("q35-acpi-hotplug-bridge-enable", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); DO_TEST("misc-disable-suspends", QEMU_CAPS_PIIX_DISABLE_S3, QEMU_CAPS_PIIX_DISABLE_S4);

This change adds backend qemu command line support for new libvirt global feature 'acpi-bridge-hotplug'. This option can be used as following: <feature> <pci> <acpi-bridge-hotplug state='off|on'/> </pci> </feature> The '<pci>' sub-element under '<feature>' is also newly introduced. 'acpi-bridge-hotplug' turns on the following command line option to qemu for x86 guests: (pc machines): -global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=<off|on> (q35 machines): -global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=<off|on> This change also adds the required qemuxml2argv unit tests in order to test correct qemu arguments. Unit tests have also been added to test qemu capability validation checks as well as checks for using this option with the right architecture. Signed-off-by: Ani Sinha <ani@anisinha.ca> --- src/qemu/qemu_command.c | 14 ++++++++ .../aarch64-acpi-hotplug-bridge-disable.err | 1 + ...pc-i440fx-acpi-hotplug-bridge-disable.args | 31 +++++++++++++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.err | 1 + .../q35-acpi-hotplug-bridge-disable.args | 33 +++++++++++++++++++ .../q35-acpi-hotplug-bridge-disable.err | 1 + tests/qemuxml2argvtest.c | 16 +++++++++ 7 files changed, 97 insertions(+) create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 08f6d735f8..6c8c99e595 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6069,6 +6069,7 @@ qemuBuildPMCommandLine(virCommand *cmd, qemuDomainObjPrivate *priv) { virQEMUCaps *qemuCaps = priv->qemuCaps; + int acpihp_br = def->pci_features[(virDomainPCI)VIR_DOMAIN_PCI_ACPI_BRIDGE_HP]; if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SET_ACTION)) { /* with new qemu we always want '-no-shutdown' on startup and we set @@ -6114,6 +6115,19 @@ qemuBuildPMCommandLine(virCommand *cmd, pm_object, def->pm.s4 == VIR_TRISTATE_BOOL_NO); } + if (acpihp_br) { + const char *pm_object = "PIIX4_PM"; + + if (qemuDomainIsQ35(def) && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE)) + pm_object = "ICH9-LPC"; + + virCommandAddArg(cmd, "-global"); + virCommandAddArgFormat(cmd, "%s.acpi-pci-hotplug-with-bridge-support=%s", + pm_object, + virTristateSwitchTypeToString(acpihp_br)); + } + return 0; } diff --git a/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err new file mode 100644 index 0000000000..9f0a88b826 --- /dev/null +++ b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err @@ -0,0 +1 @@ +unsupported configuration: acpi-bridge-hotplug is not available for architecture 'aarch64' diff --git a/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args new file mode 100644 index 0000000000..a1e5dc85c7 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args @@ -0,0 +1,31 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-i440fx \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-i440fx/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-i440fx/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-i440fx/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=i440fx,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-i440fx/master-key.aes \ +-machine pc-i440fx-2.5,accel=tcg,usb=off,dump-guest-core=off \ +-m 1024 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 56f5055c-1b8d-490c-844a-ad646a1caaaa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-i440fx/monitor.sock,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=off \ +-boot strict=on \ +-usb \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err new file mode 100644 index 0000000000..8c09a3cd76 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err @@ -0,0 +1 @@ +unsupported configuration: acpi-bridge-hotplug is not available with this QEMU binary diff --git a/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args new file mode 100644 index 0000000000..007c22c646 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args @@ -0,0 +1,33 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-q35 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-q35/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-q35/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-q35/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=q35,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-q35/master-key.aes \ +-machine pc-q35-2.5,accel=tcg,usb=off,dump-guest-core=off \ +-m 1024 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 56f5055c-1b8d-490c-844a-ad646a1caaaa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-q35/monitor.sock,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off \ +-boot strict=on \ +-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ +-device ioh3420,port=0x8,chassis=3,id=pci.3,bus=pcie.0,addr=0x1 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x1 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err new file mode 100644 index 0000000000..8c09a3cd76 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err @@ -0,0 +1 @@ +unsupported configuration: acpi-bridge-hotplug is not available with this QEMU binary diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 94aaa2f53e..507aa32009 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2574,6 +2574,22 @@ mymain(void) DO_TEST("pc-i440fx-acpi-root-hotplug-disable", QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); DO_TEST_PARSE_ERROR_NOCAPS("pc-i440fx-acpi-root-hotplug-disable"); + 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_AHCI, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-disable", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE); + DO_TEST_PARSE_ERROR_NOCAPS("q35-acpi-hotplug-bridge-disable"); + DO_TEST_PARSE_ERROR_NOCAPS("pc-i440fx-acpi-hotplug-bridge-disable"); + /* verify that we fail when acpi-bridge-hotplug option is specified for + * archs other than x86 + */ + DO_TEST_PARSE_ERROR_NOCAPS("aarch64-acpi-hotplug-bridge-disable"); DO_TEST("q35-usb2", QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, -- 2.25.1

On 10/5/21 1:51 AM, Ani Sinha wrote:
This change adds backend qemu command line support for new libvirt global feature 'acpi-bridge-hotplug'. This option can be used as following:
<feature> <pci> <acpi-bridge-hotplug state='off|on'/> </pci> </feature>
The '<pci>' sub-element under '<feature>' is also newly introduced.
'acpi-bridge-hotplug' turns on the following command line option to qemu for x86 guests:
(pc machines): -global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=<off|on> (q35 machines): -global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=<off|on>
This change also adds the required qemuxml2argv unit tests in order to test correct qemu arguments. Unit tests have also been added to test qemu capability validation checks as well as checks for using this option with the right architecture.
Signed-off-by: Ani Sinha <ani@anisinha.ca> --- src/qemu/qemu_command.c | 14 ++++++++ .../aarch64-acpi-hotplug-bridge-disable.err | 1 + ...pc-i440fx-acpi-hotplug-bridge-disable.args | 31 +++++++++++++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.err | 1 + .../q35-acpi-hotplug-bridge-disable.args | 33 +++++++++++++++++++ .../q35-acpi-hotplug-bridge-disable.err | 1 + tests/qemuxml2argvtest.c | 16 +++++++++ 7 files changed, 97 insertions(+) create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 08f6d735f8..6c8c99e595 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6069,6 +6069,7 @@ qemuBuildPMCommandLine(virCommand *cmd, qemuDomainObjPrivate *priv) { virQEMUCaps *qemuCaps = priv->qemuCaps; + int acpihp_br = def->pci_features[(virDomainPCI)VIR_DOMAIN_PCI_ACPI_BRIDGE_HP];
I'm not sure why you put the typecast on the array subscript, but it's unnecessary. I removed it.
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SET_ACTION)) { /* with new qemu we always want '-no-shutdown' on startup and we set @@ -6114,6 +6115,19 @@ qemuBuildPMCommandLine(virCommand *cmd, pm_object, def->pm.s4 == VIR_TRISTATE_BOOL_NO); }
+ if (acpihp_br) { + const char *pm_object = "PIIX4_PM"; + + if (qemuDomainIsQ35(def) && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE)) + pm_object = "ICH9-LPC";
So on Q35 systems that don't support setting "ICH9-LPC.acpi-pci-hotplug....." it will also work to set "PIIX4_PM.acpi-pci-...."? (apparently this is the case with the s3 and s4 acpi suspend options, which have a similar hack a few lines below this one). Assuming that is the case, then this patch also seems fine to me Reviewed-by: Laine Stump <laine@redhat.com> I may want to make the documentation in formatdomain.rst a bit more clear, but I can do that as a separate patch after these (since I know you're leaving on a vacation so won't be around to do it). As long as nobody complains about the naming of the feature, I think I can push this tomorrow evening (U.S. time) (that will give time for any discussion about naming in the morning, then I'll have to be afk for a few hours in the afternoon. Thanks for your contribution, and for your perseverance in the face of my procrastination, and enjoy your vacation!!
+ + virCommandAddArg(cmd, "-global"); + virCommandAddArgFormat(cmd, "%s.acpi-pci-hotplug-with-bridge-support=%s", + pm_object, + virTristateSwitchTypeToString(acpihp_br)); + } + return 0; }
diff --git a/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err new file mode 100644 index 0000000000..9f0a88b826 --- /dev/null +++ b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err @@ -0,0 +1 @@ +unsupported configuration: acpi-bridge-hotplug is not available for architecture 'aarch64' diff --git a/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args new file mode 100644 index 0000000000..a1e5dc85c7 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args @@ -0,0 +1,31 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-i440fx \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-i440fx/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-i440fx/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-i440fx/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=i440fx,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-i440fx/master-key.aes \ +-machine pc-i440fx-2.5,accel=tcg,usb=off,dump-guest-core=off \ +-m 1024 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 56f5055c-1b8d-490c-844a-ad646a1caaaa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-i440fx/monitor.sock,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=off \ +-boot strict=on \ +-usb \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err new file mode 100644 index 0000000000..8c09a3cd76 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err @@ -0,0 +1 @@ +unsupported configuration: acpi-bridge-hotplug is not available with this QEMU binary diff --git a/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args new file mode 100644 index 0000000000..007c22c646 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args @@ -0,0 +1,33 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-q35 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-q35/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-q35/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-q35/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=q35,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-q35/master-key.aes \ +-machine pc-q35-2.5,accel=tcg,usb=off,dump-guest-core=off \ +-m 1024 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 56f5055c-1b8d-490c-844a-ad646a1caaaa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-q35/monitor.sock,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off \ +-boot strict=on \ +-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ +-device ioh3420,port=0x8,chassis=3,id=pci.3,bus=pcie.0,addr=0x1 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x1 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err new file mode 100644 index 0000000000..8c09a3cd76 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err @@ -0,0 +1 @@ +unsupported configuration: acpi-bridge-hotplug is not available with this QEMU binary diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 94aaa2f53e..507aa32009 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2574,6 +2574,22 @@ mymain(void) DO_TEST("pc-i440fx-acpi-root-hotplug-disable", QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); DO_TEST_PARSE_ERROR_NOCAPS("pc-i440fx-acpi-root-hotplug-disable"); + 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_AHCI, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-disable", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE); + DO_TEST_PARSE_ERROR_NOCAPS("q35-acpi-hotplug-bridge-disable"); + DO_TEST_PARSE_ERROR_NOCAPS("pc-i440fx-acpi-hotplug-bridge-disable"); + /* verify that we fail when acpi-bridge-hotplug option is specified for + * archs other than x86 + */ + DO_TEST_PARSE_ERROR_NOCAPS("aarch64-acpi-hotplug-bridge-disable"); DO_TEST("q35-usb2", QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,

On Fri, 8 Oct 2021, Laine Stump wrote:
On 10/5/21 1:51 AM, Ani Sinha wrote:
This change adds backend qemu command line support for new libvirt global feature 'acpi-bridge-hotplug'. This option can be used as following:
<feature> <pci> <acpi-bridge-hotplug state='off|on'/> </pci> </feature>
The '<pci>' sub-element under '<feature>' is also newly introduced.
'acpi-bridge-hotplug' turns on the following command line option to qemu for x86 guests:
(pc machines): -global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=<off|on> (q35 machines): -global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=<off|on>
This change also adds the required qemuxml2argv unit tests in order to test correct qemu arguments. Unit tests have also been added to test qemu capability validation checks as well as checks for using this option with the right architecture.
Signed-off-by: Ani Sinha <ani@anisinha.ca> --- src/qemu/qemu_command.c | 14 ++++++++ .../aarch64-acpi-hotplug-bridge-disable.err | 1 + ...pc-i440fx-acpi-hotplug-bridge-disable.args | 31 +++++++++++++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.err | 1 + .../q35-acpi-hotplug-bridge-disable.args | 33 +++++++++++++++++++ .../q35-acpi-hotplug-bridge-disable.err | 1 + tests/qemuxml2argvtest.c | 16 +++++++++ 7 files changed, 97 insertions(+) create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 08f6d735f8..6c8c99e595 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6069,6 +6069,7 @@ qemuBuildPMCommandLine(virCommand *cmd, qemuDomainObjPrivate *priv) { virQEMUCaps *qemuCaps = priv->qemuCaps; + int acpihp_br = def->pci_features[(virDomainPCI)VIR_DOMAIN_PCI_ACPI_BRIDGE_HP];
I'm not sure why you put the typecast on the array subscript, but it's unnecessary. I removed it.
Fixed in v7.
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SET_ACTION)) { /* with new qemu we always want '-no-shutdown' on startup and we set @@ -6114,6 +6115,19 @@ qemuBuildPMCommandLine(virCommand *cmd, pm_object, def->pm.s4 == VIR_TRISTATE_BOOL_NO); } + if (acpihp_br) { + const char *pm_object = "PIIX4_PM"; + + if (qemuDomainIsQ35(def) && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE)) + pm_object = "ICH9-LPC";
So on Q35 systems that don't support setting "ICH9-LPC.acpi-pci-hotplug....." it will also work to set "PIIX4_PM.acpi-pci-...."? (apparently this is the case with the s3 and s4 acpi suspend options, which have a similar hack a few lines below this one).
Assuming that is the case, then this patch also seems fine to me
No, that is not right. I have fixed it in v7. Thanks for catching it.
Reviewed-by: Laine Stump <laine@redhat.com>
I may want to make the documentation in formatdomain.rst a bit more clear, but I can do that as a separate patch after these (since I know you're leaving on a vacation so won't be around to do it).
Yeah I could not handle it well. I tried my best but left the rest to the experts here :-)
As long as nobody complains about the naming of the feature,
If by naming if you mean the domain xml config options, that is approved by danpb (offline IRC chat with him). I think I can
push this tomorrow evening (U.S. time) (that will give time for any discussion about naming in the morning, then I'll have to be afk for a few hours in the afternoon.
Thanks for your contribution, and for your perseverance in the face of my procrastination, and enjoy your vacation!!
Thanks Laine for so much help. Very much appretiate your suggestions and guidance here.
+ + virCommandAddArg(cmd, "-global"); + virCommandAddArgFormat(cmd, "%s.acpi-pci-hotplug-with-bridge-support=%s", + pm_object, + virTristateSwitchTypeToString(acpihp_br)); + } + return 0; } diff --git a/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err new file mode 100644 index 0000000000..9f0a88b826 --- /dev/null +++ b/tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err @@ -0,0 +1 @@ +unsupported configuration: acpi-bridge-hotplug is not available for architecture 'aarch64' diff --git a/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args new file mode 100644 index 0000000000..a1e5dc85c7 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args @@ -0,0 +1,31 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-i440fx \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-i440fx/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-i440fx/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-i440fx/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=i440fx,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-i440fx/master-key.aes \ +-machine pc-i440fx-2.5,accel=tcg,usb=off,dump-guest-core=off \ +-m 1024 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 56f5055c-1b8d-490c-844a-ad646a1caaaa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-i440fx/monitor.sock,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=off \ +-boot strict=on \ +-usb \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err new file mode 100644 index 0000000000..8c09a3cd76 --- /dev/null +++ b/tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err @@ -0,0 +1 @@ +unsupported configuration: acpi-bridge-hotplug is not available with this QEMU binary diff --git a/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args new file mode 100644 index 0000000000..007c22c646 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args @@ -0,0 +1,33 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-q35 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-q35/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-q35/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-q35/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=q35,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-q35/master-key.aes \ +-machine pc-q35-2.5,accel=tcg,usb=off,dump-guest-core=off \ +-m 1024 \ +-realtime mlock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 56f5055c-1b8d-490c-844a-ad646a1caaaa \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-q35/monitor.sock,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off \ +-boot strict=on \ +-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ +-device ioh3420,port=0x8,chassis=3,id=pci.3,bus=pcie.0,addr=0x1 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x1 \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err new file mode 100644 index 0000000000..8c09a3cd76 --- /dev/null +++ b/tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err @@ -0,0 +1 @@ +unsupported configuration: acpi-bridge-hotplug is not available with this QEMU binary diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 94aaa2f53e..507aa32009 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2574,6 +2574,22 @@ mymain(void) DO_TEST("pc-i440fx-acpi-root-hotplug-disable", QEMU_CAPS_PIIX4_ACPI_ROOT_PCI_HOTPLUG); DO_TEST_PARSE_ERROR_NOCAPS("pc-i440fx-acpi-root-hotplug-disable"); + 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_AHCI, + QEMU_CAPS_ICH9_ACPI_HOTPLUG_BRIDGE); + DO_TEST("pc-i440fx-acpi-hotplug-bridge-disable", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_PIIX4_ACPI_HOTPLUG_BRIDGE); + DO_TEST_PARSE_ERROR_NOCAPS("q35-acpi-hotplug-bridge-disable"); + DO_TEST_PARSE_ERROR_NOCAPS("pc-i440fx-acpi-hotplug-bridge-disable"); + /* verify that we fail when acpi-bridge-hotplug option is specified for + * archs other than x86 + */ + DO_TEST_PARSE_ERROR_NOCAPS("aarch64-acpi-hotplug-bridge-disable"); DO_TEST("q35-usb2", QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,

Added the following new libvirt conf option to the release note to indicate their availability with the next release: <feature> <pci> <acpi-bridge-hotplug state='off|on'/> </pci> </feature> Signed-off-by: Ani Sinha <ani@anisinha.ca> --- NEWS.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index caa61f0646..25de621c91 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -32,6 +32,13 @@ v7.9.0 (unreleased) controller. The default behavior is unchanged (hotplug is allowed). + * Add a new global feature for controlling ACPI PCI hotplug on bridges + + A new ``<feature>`` config option ``<acpi-bridge-hotplug>`` under ``<pci>`` + sub-element have been added to allow users control BIOS ACPI based PCI + hotplug for cold plugged bridges. It is only applicable for x86 guests + using qemu driver. + * **Improvements** * **Bug fixes** -- 2.25.1

On 10/5/21 1:51 AM, Ani Sinha wrote:
Added the following new libvirt conf option to the release note to indicate their availability with the next release:
<feature> <pci> <acpi-bridge-hotplug state='off|on'/> </pci> </feature>
Signed-off-by: Ani Sinha <ani@anisinha.ca> --- NEWS.rst | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/NEWS.rst b/NEWS.rst index caa61f0646..25de621c91 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -32,6 +32,13 @@ v7.9.0 (unreleased) controller. The default behavior is unchanged (hotplug is allowed).
+ * Add a new global feature for controlling ACPI PCI hotplug on bridges + + A new ``<feature>`` config option ``<acpi-bridge-hotplug>`` under ``<pci>`` + sub-element have been added to allow users control BIOS ACPI based PCI + hotplug for cold plugged bridges. It is only applicable for x86 guests + using qemu driver.
How about: A new ``<feature>`` config option ``<acpi-bridge-hotplug>``under ``<pci>`` sub-element has been added to allow users to enable/disable ACPI based PCI hotplug for cold plugged bridges. It is only applicable for x86 guests using qemu driver. Reviewed-by: Laine Stump <laine@redhat.com>
+ * **Improvements**
* **Bug fixes**

Other than laine doesn't anyone have any feedback on this patch set? Timely reviews help contributions. It's difficult to sit on a patch set and keep rebasing for ever. On Tue, Oct 5, 2021 at 11:21 AM Ani Sinha <ani@anisinha.ca> wrote:
changelog:
v6: rebased to latest. capabilities have been renamed as per suggestions that were made here:
https://listman.redhat.com/archives/libvir-list/2021-October/msg00061.html v5: rebased the patchset with the latest master. v4: split the original series into two - pci-root controller specific one (https://www.mail-archive.com/libvir-list@redhat.com/msg221645.html) and this one specific to pci bridges. The conf xml has been introduced as per suggestion by Berrange here: https://patchew.org/Libvirt/20210912032631.2853520-1-ani@anisinha.ca Changes has been introduced to parse and validate the xml accordingly as well as to add backend qemu commandline option. v3: reorganized the patches as per Laine's suggestion. Added more details in commit messages. Added conf description in formatdomain.rst. Added changelog for next release. v2: fixed bugs and added additional missing unit tests. v1: initial implementation. Had some bugs and missed some unit tests
This change introduces a new libvirt sub-element <pci> under <features> that can be used to configure all pci related features. Currently the only sub-sub element supported by this sub-element is 'acpi-bridge-hotplug' as shown below:
<features> <pci> <acpi-bridge-hotplug state='on|off'/> </pci> </features>
The above option is only available for qemu driver and that too for x86 guests only. It is a global option.
'acpi-bridge-hotplug' option enables or disables ACPI hotplug support for cold-plugged pci bridges. Examples of bridges include PCI-PCI bridge (pci-bridge controller) or PCIe-PCI bridges for pc machines and pcie-root-port controller for q35 machines. Being global option, no other bridge specific option 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 following changes in qemu repo:
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 repo:
(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). There are use cases where users would still want to use native hotplug (see notes). Therefore, this config option enables users to choose either ACPI based hotplug or native hotplug for bridges (for example for pcie root port controller in q35 machines).
Notes: One concrete example of why one might still want to use native hotplug with pcie-root-port controller is the fact that we are still discovering issues with acpi hotplug on PCIE. One such issue is: https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg02146.html Another reason is that users have been using native hotplug on pcie root ports up until now. They have built and tested their systems based on native hotplug. They may not want to suddenly move to acpi based hotplug just because it is now the default in qemu. Supporting the option to chose one or the other through libvirt makes things simpler for end users.
Ani Sinha (4): qemu: capablities: detect presence of acpi-pci-hotplug-with-bridge-support conf: introduce support for acpi-bridge-hotplug feature qemu: command: add support for acpi-bridge-hotplug feature NEWS: add new acpi pci hotplug config option in the release note for next release
NEWS.rst | 7 ++ docs/formatdomain.rst | 11 +++ docs/schemas/domaincommon.rng | 15 ++++ src/conf/domain_conf.c | 89 ++++++++++++++++++- src/conf/domain_conf.h | 9 ++ src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 14 +++ src/qemu/qemu_validate.c | 46 ++++++++++ .../caps_2.11.0.x86_64.xml | 1 + .../caps_2.12.0.x86_64.xml | 1 + .../caps_3.0.0.x86_64.xml | 1 + .../caps_3.1.0.x86_64.xml | 1 + .../caps_4.0.0.x86_64.xml | 1 + .../caps_4.1.0.x86_64.xml | 1 + .../caps_4.2.0.x86_64.xml | 1 + .../caps_5.0.0.x86_64.xml | 1 + .../caps_5.1.0.x86_64.xml | 1 + .../caps_5.2.0.x86_64.xml | 1 + .../caps_6.0.0.x86_64.xml | 1 + .../caps_6.1.0.x86_64.xml | 2 + .../aarch64-acpi-hotplug-bridge-disable.err | 1 + .../aarch64-acpi-hotplug-bridge-disable.xml | 33 +++++++ ...pc-i440fx-acpi-hotplug-bridge-disable.args | 31 +++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.err | 1 + .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 33 +++++++ .../q35-acpi-hotplug-bridge-disable.args | 33 +++++++ .../q35-acpi-hotplug-bridge-disable.err | 1 + .../q35-acpi-hotplug-bridge-disable.xml | 47 ++++++++++ .../q35-acpi-hotplug-bridge-enable.xml | 47 ++++++++++ tests/qemuxml2argvtest.c | 16 ++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 1 + .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 1 + .../q35-acpi-hotplug-bridge-disable.xml | 1 + .../q35-acpi-hotplug-bridge-enable.xml | 1 + tests/qemuxml2xmltest.c | 14 +++ 37 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml
-- 2.25.1

Also just for the statistics , it's been almost 2 months now since the effort on the two patches started. On Fri, Oct 8, 2021 at 4:46 AM Ani Sinha <ani@anisinha.ca> wrote:
Other than laine doesn't anyone have any feedback on this patch set? Timely reviews help contributions. It's difficult to sit on a patch set and keep rebasing for ever.
On Tue, Oct 5, 2021 at 11:21 AM Ani Sinha <ani@anisinha.ca> wrote:
changelog:
v6: rebased to latest. capabilities have been renamed as per suggestions that were made here:
https://listman.redhat.com/archives/libvir-list/2021-October/msg00061.html v5: rebased the patchset with the latest master. v4: split the original series into two - pci-root controller specific one (https://www.mail-archive.com/libvir-list@redhat.com/msg221645.html) and this one specific to pci bridges. The conf xml has been introduced as per suggestion by Berrange here: https://patchew.org/Libvirt/20210912032631.2853520-1-ani@anisinha.ca Changes has been introduced to parse and validate the xml accordingly as well as to add backend qemu commandline option. v3: reorganized the patches as per Laine's suggestion. Added more details in commit messages. Added conf description in formatdomain.rst. Added changelog for next release. v2: fixed bugs and added additional missing unit tests. v1: initial implementation. Had some bugs and missed some unit tests
This change introduces a new libvirt sub-element <pci> under <features> that can be used to configure all pci related features. Currently the only sub-sub element supported by this sub-element is 'acpi-bridge-hotplug' as shown below:
<features> <pci> <acpi-bridge-hotplug state='on|off'/> </pci> </features>
The above option is only available for qemu driver and that too for x86 guests only. It is a global option.
'acpi-bridge-hotplug' option enables or disables ACPI hotplug support for cold-plugged pci bridges. Examples of bridges include PCI-PCI bridge (pci-bridge controller) or PCIe-PCI bridges for pc machines and pcie-root-port controller for q35 machines. Being global option, no other bridge specific option 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 following changes in qemu repo:
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 repo:
(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). There are use cases where users would still want to use native hotplug (see notes). Therefore, this config option enables users to choose either ACPI based hotplug or native hotplug for bridges (for example for pcie root port controller in q35 machines).
Notes: One concrete example of why one might still want to use native hotplug with pcie-root-port controller is the fact that we are still discovering issues with acpi hotplug on PCIE. One such issue is: https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg02146.html Another reason is that users have been using native hotplug on pcie root ports up until now. They have built and tested their systems based on native hotplug. They may not want to suddenly move to acpi based hotplug just because it is now the default in qemu. Supporting the option to chose one or the other through libvirt makes things simpler for end users.
Ani Sinha (4): qemu: capablities: detect presence of acpi-pci-hotplug-with-bridge-support conf: introduce support for acpi-bridge-hotplug feature qemu: command: add support for acpi-bridge-hotplug feature NEWS: add new acpi pci hotplug config option in the release note for next release
NEWS.rst | 7 ++ docs/formatdomain.rst | 11 +++ docs/schemas/domaincommon.rng | 15 ++++ src/conf/domain_conf.c | 89 ++++++++++++++++++- src/conf/domain_conf.h | 9 ++ src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 14 +++ src/qemu/qemu_validate.c | 46 ++++++++++ .../caps_2.11.0.x86_64.xml | 1 + .../caps_2.12.0.x86_64.xml | 1 + .../caps_3.0.0.x86_64.xml | 1 + .../caps_3.1.0.x86_64.xml | 1 + .../caps_4.0.0.x86_64.xml | 1 + .../caps_4.1.0.x86_64.xml | 1 + .../caps_4.2.0.x86_64.xml | 1 + .../caps_5.0.0.x86_64.xml | 1 + .../caps_5.1.0.x86_64.xml | 1 + .../caps_5.2.0.x86_64.xml | 1 + .../caps_6.0.0.x86_64.xml | 1 + .../caps_6.1.0.x86_64.xml | 2 + .../aarch64-acpi-hotplug-bridge-disable.err | 1 + .../aarch64-acpi-hotplug-bridge-disable.xml | 33 +++++++ ...pc-i440fx-acpi-hotplug-bridge-disable.args | 31 +++++++ .../pc-i440fx-acpi-hotplug-bridge-disable.err | 1 + .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 33 +++++++ .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 33 +++++++ .../q35-acpi-hotplug-bridge-disable.args | 33 +++++++ .../q35-acpi-hotplug-bridge-disable.err | 1 + .../q35-acpi-hotplug-bridge-disable.xml | 47 ++++++++++ .../q35-acpi-hotplug-bridge-enable.xml | 47 ++++++++++ tests/qemuxml2argvtest.c | 16 ++++ .../pc-i440fx-acpi-hotplug-bridge-disable.xml | 1 + .../pc-i440fx-acpi-hotplug-bridge-enable.xml | 1 + .../q35-acpi-hotplug-bridge-disable.xml | 1 + .../q35-acpi-hotplug-bridge-enable.xml | 1 + tests/qemuxml2xmltest.c | 14 +++ 37 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/aarch64-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.args create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.err create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-disable.xml create mode 100644 tests/qemuxml2argvdata/q35-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/pc-i440fx-acpi-hotplug-bridge-enable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-disable.xml create mode 120000 tests/qemuxml2xmloutdata/q35-acpi-hotplug-bridge-enable.xml
-- 2.25.1
participants (3)
-
Ani Sinha
-
Laine Stump
-
Laine Stump