If a pcie-root-port or pcie-downstream-port has hotplug='off' in its
<target> subelement, and if the qemu binary supports the hotplug=false
option, then it will be added to the commandline for the pcie
controller. This controller will then not allow any hotplug/unplug of
devices while the guest is running (and the hotplug capability won't
be advertised to the guest OS, so the guest OS also won't present
unplugging of PCI devices as an option).
<controller type='pci' model='pcie-root-port'>
<target hotplug='off'/>
</controller>
For any PCI controllers other than pcie-downstream-port and
pcie-root-port, of for qemu binaries that don't support the hotplug
commandline option, an error will be logged during validation.
Signed-off-by: Laine Stump <laine(a)redhat.com>
---
src/qemu/qemu_command.c | 4 ++
src/qemu/qemu_validate.c | 31 +++++++++++++++
.../pcie-root-port-nohotplug.args | 39 +++++++++++++++++++
tests/qemuxml2argvtest.c | 7 ++++
4 files changed, 81 insertions(+)
create mode 100644 tests/qemuxml2argvdata/pcie-root-port-nohotplug.args
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index df90f5edf5..f619ef32be 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3016,6 +3016,10 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef,
virBufferAsprintf(&buf, "%s,port=0x%x,chassis=%d,id=%s",
modelName, pciopts->port,
pciopts->chassis, def->info.alias);
+ if (pciopts->hotplug != VIR_TRISTATE_SWITCH_ABSENT) {
+ virBufferAsprintf(&buf, ",hotplug=%s",
+ virTristateSwitchTypeToString(pciopts->hotplug));
+ }
break;
case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
virBufferAsprintf(&buf, "%s,index=%d,id=%s",
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 6f94361b52..49f9af69db 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -2637,6 +2637,37 @@ qemuValidateDomainDeviceDefControllerPCI(const
virDomainControllerDef *cont,
virReportEnumRangeError(virDomainControllerModelPCI, cont->model);
}
+ /* hotplug */
+ if (pciopts->hotplug != VIR_TRISTATE_SWITCH_ABSENT) {
+ switch ((virDomainControllerModelPCI) cont->model) {
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCIE_ROOT_PORT_HOTPLUG)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("setting the hotplug property on a '%s'
device is not supported by this QEMU binary"),
+ modelName);
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
+ case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE:
+ virReportControllerInvalidOption(cont, model, modelName,
"hotplug");
+ return -1;
+
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
+ default:
+ virReportEnumRangeError(virDomainControllerModelPCI, cont->model);
+ }
+ }
+
/* QEMU device availability */
if (cap < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
diff --git a/tests/qemuxml2argvdata/pcie-root-port-nohotplug.args
b/tests/qemuxml2argvdata/pcie-root-port-nohotplug.args
new file mode 100644
index 0000000000..3a4904c24f
--- /dev/null
+++ b/tests/qemuxml2argvdata/pcie-root-port-nohotplug.args
@@ -0,0 +1,39 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-guest \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-guest/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-guest/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-guest/.config \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name guest \
+-S \
+-machine q35,accel=tcg,usb=off,dump-guest-core=off \
+-m 2048 \
+-realtime mlock=off \
+-smp 2,sockets=2,cores=1,threads=1 \
+-uuid 11dbdcdd-4c3b-482b-8903-9bdb8c0a2774 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-device pcie-root-port,port=0x10,chassis=1,id=pci.1,bus=pcie.0,\
+multifunction=on,addr=0x2 \
+-device pcie-root-port,port=0x11,chassis=2,id=pci.2,hotplug=off,bus=pcie.0,\
+addr=0x2.0x1 \
+-device ioh3420,port=0x12,chassis=3,id=pci.3,hotplug=off,bus=pcie.0,\
+addr=0x2.0x2 \
+-device x3130-upstream,id=pci.4,bus=pci.1,addr=0x0 \
+-device xio3130-downstream,port=0x0,chassis=5,id=pci.5,hotplug=off,bus=pci.4,\
+addr=0x0 \
+-device xio3130-downstream,port=0x1,chassis=6,id=pci.6,hotplug=on,bus=pci.4,\
+addr=0x1 \
+-device xio3130-downstream,port=0x2,chassis=7,id=pci.7,bus=pci.4,addr=0x2 \
+-device xio3130-downstream,port=0x27,chassis=30,id=pci.8,bus=pci.4,addr=0x3
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index fdeb3c2e65..9a10528251 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2436,6 +2436,13 @@ mymain(void)
DO_TEST("pcie-root-port-model-ioh3420",
QEMU_CAPS_DEVICE_IOH3420);
+ DO_TEST("pcie-root-port-nohotplug",
+ QEMU_CAPS_DEVICE_PCIE_ROOT_PORT,
+ QEMU_CAPS_DEVICE_IOH3420,
+ QEMU_CAPS_DEVICE_X3130_UPSTREAM,
+ QEMU_CAPS_DEVICE_XIO3130_DOWNSTREAM,
+ QEMU_CAPS_PCIE_ROOT_PORT_HOTPLUG);
+
DO_TEST("autoindex",
QEMU_CAPS_DEVICE_PCI_BRIDGE,
QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
--
2.25.2