|
|
6ae9ed |
From 5fde4ecb99989b91940f1b24a509adb47e3e0894 Mon Sep 17 00:00:00 2001
|
|
|
6ae9ed |
Message-Id: <5fde4ecb99989b91940f1b24a509adb47e3e0894@dist-git>
|
|
|
6ae9ed |
From: Peter Krempa <pkrempa@redhat.com>
|
|
|
6ae9ed |
Date: Wed, 24 Aug 2016 16:11:37 -0400
|
|
|
6ae9ed |
Subject: [PATCH] qemu: command: Add support for sparse vcpu topologies
|
|
|
6ae9ed |
|
|
|
6ae9ed |
https://bugzilla.redhat.com/show_bug.cgi?id=1097930
|
|
|
6ae9ed |
https://bugzilla.redhat.com/show_bug.cgi?id=1224341
|
|
|
6ae9ed |
|
|
|
6ae9ed |
Add support for using the new approach to hotplug vcpus using device_add
|
|
|
6ae9ed |
during startup of qemu to allow sparse vcpu topologies.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
There are a few limitations imposed by qemu on the supported
|
|
|
6ae9ed |
configuration:
|
|
|
6ae9ed |
- vcpu0 needs to be always present and not hotpluggable
|
|
|
6ae9ed |
- non-hotpluggable cpus need to be ordered at the beginning
|
|
|
6ae9ed |
- order of the vcpus needs to be unique for every single hotpluggable
|
|
|
6ae9ed |
entity
|
|
|
6ae9ed |
|
|
|
6ae9ed |
Qemu also doesn't really allow to query the information necessary to
|
|
|
6ae9ed |
start a VM with the vcpus directly on the commandline. Fortunately they
|
|
|
6ae9ed |
can be hotplugged during startup.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
The new hotplug code uses the following approach:
|
|
|
6ae9ed |
- non-hotpluggable vcpus are counted and put to the -smp option
|
|
|
6ae9ed |
- qemu is started
|
|
|
6ae9ed |
- qemu is queried for the necessary information
|
|
|
6ae9ed |
- the configuration is checked
|
|
|
6ae9ed |
- the hotpluggable vcpus are hotplugged
|
|
|
6ae9ed |
- vcpus are started
|
|
|
6ae9ed |
|
|
|
6ae9ed |
This patch adds a lot of checking code and enables the support to
|
|
|
6ae9ed |
specify the individual vcpu element with qemu.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
(cherry picked from commit 9eb9106ea51b43102ee51132f69780b2c86ccbca)
|
|
|
6ae9ed |
---
|
|
|
6ae9ed |
docs/formatdomain.html.in | 5 +
|
|
|
6ae9ed |
src/qemu/qemu_command.c | 20 ++-
|
|
|
6ae9ed |
src/qemu/qemu_domain.c | 76 ++++++++-
|
|
|
6ae9ed |
src/qemu/qemu_process.c | 178 +++++++++++++++++++++
|
|
|
6ae9ed |
.../qemuxml2argv-cpu-hotplug-startup.args | 20 +++
|
|
|
6ae9ed |
.../qemuxml2argv-cpu-hotplug-startup.xml | 29 ++++
|
|
|
6ae9ed |
tests/qemuxml2argvtest.c | 2 +
|
|
|
6ae9ed |
7 files changed, 325 insertions(+), 5 deletions(-)
|
|
|
6ae9ed |
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-hotplug-startup.args
|
|
|
6ae9ed |
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-hotplug-startup.xml
|
|
|
6ae9ed |
|
|
|
6ae9ed |
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
|
|
|
6ae9ed |
index 252f91c..a838bff 100644
|
|
|
6ae9ed |
--- a/docs/formatdomain.html.in
|
|
|
6ae9ed |
+++ b/docs/formatdomain.html.in
|
|
|
6ae9ed |
@@ -580,6 +580,11 @@
|
|
|
6ae9ed |
Note that providing state for individual cpus may be necessary to enable
|
|
|
6ae9ed |
support of addressable vCPU hotplug and this feature may not be
|
|
|
6ae9ed |
supported by all hypervisors.
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ For QEMU the following conditions are required. Vcpu 0 needs to be
|
|
|
6ae9ed |
+ enabled and non-hotpluggable. On PPC64 along with it vcpus that are in
|
|
|
6ae9ed |
+ the same core need to be enabled as well. All non-hotpluggable cpus
|
|
|
6ae9ed |
+ present at boot need to be grouped after vcpu 0.
|
|
|
6ae9ed |
Since 2.2.0 (QEMU only)
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
|
|
|
6ae9ed |
index 95055c4..e292f48 100644
|
|
|
6ae9ed |
--- a/src/qemu/qemu_command.c
|
|
|
6ae9ed |
+++ b/src/qemu/qemu_command.c
|
|
|
6ae9ed |
@@ -7109,17 +7109,29 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
|
|
|
6ae9ed |
|
|
|
6ae9ed |
static int
|
|
|
6ae9ed |
qemuBuildSmpCommandLine(virCommandPtr cmd,
|
|
|
6ae9ed |
- const virDomainDef *def)
|
|
|
6ae9ed |
+ virDomainDefPtr def)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
char *smp;
|
|
|
6ae9ed |
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
6ae9ed |
+ unsigned int maxvcpus = virDomainDefGetVcpusMax(def);
|
|
|
6ae9ed |
+ unsigned int nvcpus = 0;
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr vcpu;
|
|
|
6ae9ed |
+ size_t i;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* count non-hotpluggable enabled vcpus. Hotpluggable ones will be added
|
|
|
6ae9ed |
+ * in a different way */
|
|
|
6ae9ed |
+ for (i = 0; i < maxvcpus; i++) {
|
|
|
6ae9ed |
+ vcpu = virDomainDefGetVcpu(def, i);
|
|
|
6ae9ed |
+ if (vcpu->online && vcpu->hotpluggable == VIR_TRISTATE_BOOL_NO)
|
|
|
6ae9ed |
+ nvcpus++;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
|
|
|
6ae9ed |
virCommandAddArg(cmd, "-smp");
|
|
|
6ae9ed |
|
|
|
6ae9ed |
- virBufferAsprintf(&buf, "%u", virDomainDefGetVcpus(def));
|
|
|
6ae9ed |
+ virBufferAsprintf(&buf, "%u", nvcpus);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
- if (virDomainDefHasVcpusOffline(def))
|
|
|
6ae9ed |
- virBufferAsprintf(&buf, ",maxcpus=%u", virDomainDefGetVcpusMax(def));
|
|
|
6ae9ed |
+ if (nvcpus != maxvcpus)
|
|
|
6ae9ed |
+ virBufferAsprintf(&buf, ",maxcpus=%u", maxvcpus);
|
|
|
6ae9ed |
/* sockets, cores, and threads are either all zero
|
|
|
6ae9ed |
* or all non-zero, thus checking one of them is enough */
|
|
|
6ae9ed |
if (def->cpu && def->cpu->sockets) {
|
|
|
6ae9ed |
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
|
|
6ae9ed |
index 959b551..8eb6e51 100644
|
|
|
6ae9ed |
--- a/src/qemu/qemu_domain.c
|
|
|
6ae9ed |
+++ b/src/qemu/qemu_domain.c
|
|
|
6ae9ed |
@@ -2247,6 +2247,76 @@ qemuDomainRecheckInternalPaths(virDomainDefPtr def,
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
static int
|
|
|
6ae9ed |
+qemuDomainDefVcpusPostParse(virDomainDefPtr def)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ unsigned int maxvcpus = virDomainDefGetVcpusMax(def);
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr vcpu;
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr prevvcpu;
|
|
|
6ae9ed |
+ size_t i;
|
|
|
6ae9ed |
+ bool has_order = false;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* vcpu 0 needs to be present, first, and non-hotpluggable */
|
|
|
6ae9ed |
+ vcpu = virDomainDefGetVcpu(def, 0);
|
|
|
6ae9ed |
+ if (!vcpu->online) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
6ae9ed |
+ _("vcpu 0 can't be offline"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ if (vcpu->hotpluggable == VIR_TRISTATE_BOOL_YES) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
6ae9ed |
+ _("vcpu0 can't be hotpluggable"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ if (vcpu->order != 0 && vcpu->order != 1) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
6ae9ed |
+ _("vcpu0 must be enabled first"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (vcpu->order != 0)
|
|
|
6ae9ed |
+ has_order = true;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ prevvcpu = vcpu;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* all online vcpus or non online vcpu need to have order set */
|
|
|
6ae9ed |
+ for (i = 1; i < maxvcpus; i++) {
|
|
|
6ae9ed |
+ vcpu = virDomainDefGetVcpu(def, i);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (vcpu->online &&
|
|
|
6ae9ed |
+ (vcpu->order != 0) != has_order) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
6ae9ed |
+ _("all vcpus must have either set or unset order"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* few conditions for non-hotpluggable (thus online) vcpus */
|
|
|
6ae9ed |
+ if (vcpu->hotpluggable == VIR_TRISTATE_BOOL_NO) {
|
|
|
6ae9ed |
+ /* they can be ordered only at the beginning */
|
|
|
6ae9ed |
+ if (prevvcpu->hotpluggable == VIR_TRISTATE_BOOL_YES) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
6ae9ed |
+ _("online non-hotpluggable vcpus need to be "
|
|
|
6ae9ed |
+ "ordered prior to hotplugable vcpus"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* they need to be in order (qemu doesn't support any order yet).
|
|
|
6ae9ed |
+ * Also note that multiple vcpus may share order on some platforms */
|
|
|
6ae9ed |
+ if (prevvcpu->order > vcpu->order) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
6ae9ed |
+ _("online non-hotpluggable vcpus must be ordered "
|
|
|
6ae9ed |
+ "in ascending order"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ prevvcpu = vcpu;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return 0;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
qemuDomainDefPostParse(virDomainDefPtr def,
|
|
|
6ae9ed |
virCapsPtr caps,
|
|
|
6ae9ed |
unsigned int parseFlags,
|
|
|
6ae9ed |
@@ -2301,6 +2371,9 @@ qemuDomainDefPostParse(virDomainDefPtr def,
|
|
|
6ae9ed |
if (virSecurityManagerVerify(driver->securityManager, def) < 0)
|
|
|
6ae9ed |
goto cleanup;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+ if (qemuDomainDefVcpusPostParse(def) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
ret = 0;
|
|
|
6ae9ed |
cleanup:
|
|
|
6ae9ed |
virObjectUnref(qemuCaps);
|
|
|
6ae9ed |
@@ -2670,7 +2743,8 @@ virDomainDefParserConfig virQEMUDriverDomainDefParserConfig = {
|
|
|
6ae9ed |
.deviceValidateCallback = qemuDomainDeviceDefValidate,
|
|
|
6ae9ed |
|
|
|
6ae9ed |
.features = VIR_DOMAIN_DEF_FEATURE_MEMORY_HOTPLUG |
|
|
|
6ae9ed |
- VIR_DOMAIN_DEF_FEATURE_OFFLINE_VCPUPIN
|
|
|
6ae9ed |
+ VIR_DOMAIN_DEF_FEATURE_OFFLINE_VCPUPIN |
|
|
|
6ae9ed |
+ VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS,
|
|
|
6ae9ed |
};
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
|
|
6ae9ed |
index c94eed4..2eac422 100644
|
|
|
6ae9ed |
--- a/src/qemu/qemu_process.c
|
|
|
6ae9ed |
+++ b/src/qemu/qemu_process.c
|
|
|
6ae9ed |
@@ -4719,6 +4719,172 @@ qemuProcessSetupIOThreads(virDomainObjPtr vm)
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+qemuProcessValidateHotpluggableVcpus(virDomainDefPtr def)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr vcpu;
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr subvcpu;
|
|
|
6ae9ed |
+ qemuDomainVcpuPrivatePtr vcpupriv;
|
|
|
6ae9ed |
+ unsigned int maxvcpus = virDomainDefGetVcpusMax(def);
|
|
|
6ae9ed |
+ size_t i = 0;
|
|
|
6ae9ed |
+ size_t j;
|
|
|
6ae9ed |
+ virBitmapPtr ordermap = NULL;
|
|
|
6ae9ed |
+ int ret = -1;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!(ordermap = virBitmapNew(maxvcpus)))
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* validate:
|
|
|
6ae9ed |
+ * - all hotpluggable entities to be hotplugged have the correct data
|
|
|
6ae9ed |
+ * - vcpus belonging to a hotpluggable entity share configuration
|
|
|
6ae9ed |
+ * - order of the hotpluggable entities is unique
|
|
|
6ae9ed |
+ */
|
|
|
6ae9ed |
+ for (i = 0; i < maxvcpus; i++) {
|
|
|
6ae9ed |
+ vcpu = virDomainDefGetVcpu(def, i);
|
|
|
6ae9ed |
+ vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* skip over hotpluggable entities */
|
|
|
6ae9ed |
+ if (vcpupriv->vcpus == 0)
|
|
|
6ae9ed |
+ continue;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (vcpu->order != 0) {
|
|
|
6ae9ed |
+ if (virBitmapIsBitSet(ordermap, vcpu->order - 1)) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
6ae9ed |
+ _("duplicate vcpu order '%u'"), vcpu->order - 1);
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ ignore_value(virBitmapSetBit(ordermap, vcpu->order - 1));
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ for (j = i + 1; j < (i + vcpupriv->vcpus); j++) {
|
|
|
6ae9ed |
+ subvcpu = virDomainDefGetVcpu(def, j);
|
|
|
6ae9ed |
+ if (subvcpu->hotpluggable != vcpu->hotpluggable ||
|
|
|
6ae9ed |
+ subvcpu->online != vcpu->online ||
|
|
|
6ae9ed |
+ subvcpu->order != vcpu->order) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
6ae9ed |
+ _("vcpus '%zu' and '%zu' are in the same hotplug "
|
|
|
6ae9ed |
+ "group but differ in configuration"), i, j);
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (vcpu->online && vcpu->hotpluggable == VIR_TRISTATE_BOOL_YES) {
|
|
|
6ae9ed |
+ if ((vcpupriv->socket_id == -1 && vcpupriv->core_id == -1 &&
|
|
|
6ae9ed |
+ vcpupriv->thread_id == -1) ||
|
|
|
6ae9ed |
+ !vcpupriv->type) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
6ae9ed |
+ _("vcpu '%zu' is missing hotplug data"), i);
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ ret = 0;
|
|
|
6ae9ed |
+ cleanup:
|
|
|
6ae9ed |
+ virBitmapFree(ordermap);
|
|
|
6ae9ed |
+ return ret;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+qemuDomainHasHotpluggableStartupVcpus(virDomainDefPtr def)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ size_t maxvcpus = virDomainDefGetVcpusMax(def);
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr vcpu;
|
|
|
6ae9ed |
+ size_t i;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ for (i = 0; i < maxvcpus; i++) {
|
|
|
6ae9ed |
+ vcpu = virDomainDefGetVcpu(def, i);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (vcpu->online && vcpu->hotpluggable == VIR_TRISTATE_BOOL_YES)
|
|
|
6ae9ed |
+ return true;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return false;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+qemuProcessVcpusSortOrder(const void *a,
|
|
|
6ae9ed |
+ const void *b)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr vcpua = *((virDomainVcpuDefPtr *)a);
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr vcpub = *((virDomainVcpuDefPtr *)b);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return vcpua->order - vcpub->order;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+qemuProcessSetupHotpluggableVcpus(virQEMUDriverPtr driver,
|
|
|
6ae9ed |
+ virDomainObjPtr vm,
|
|
|
6ae9ed |
+ qemuDomainAsyncJob asyncJob)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ unsigned int maxvcpus = virDomainDefGetVcpusMax(vm->def);
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr vcpu;
|
|
|
6ae9ed |
+ qemuDomainVcpuPrivatePtr vcpupriv;
|
|
|
6ae9ed |
+ virJSONValuePtr vcpuprops = NULL;
|
|
|
6ae9ed |
+ size_t i;
|
|
|
6ae9ed |
+ int ret = -1;
|
|
|
6ae9ed |
+ int rc;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ virDomainVcpuDefPtr *bootHotplug = NULL;
|
|
|
6ae9ed |
+ size_t nbootHotplug = 0;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ for (i = 0; i < maxvcpus; i++) {
|
|
|
6ae9ed |
+ vcpu = virDomainDefGetVcpu(vm->def, i);
|
|
|
6ae9ed |
+ vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (vcpu->hotpluggable == VIR_TRISTATE_BOOL_YES && vcpu->online &&
|
|
|
6ae9ed |
+ vcpupriv->vcpus != 0) {
|
|
|
6ae9ed |
+ if (virAsprintf(&vcpupriv->alias, "vcpu%zu", i) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (VIR_APPEND_ELEMENT(bootHotplug, nbootHotplug, vcpu) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (nbootHotplug == 0) {
|
|
|
6ae9ed |
+ ret = 0;
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ qsort(bootHotplug, nbootHotplug, sizeof(*bootHotplug),
|
|
|
6ae9ed |
+ qemuProcessVcpusSortOrder);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ for (i = 0; i < nbootHotplug; i++) {
|
|
|
6ae9ed |
+ vcpu = bootHotplug[i];
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!(vcpuprops = qemuBuildHotpluggableCPUProps(vcpu)))
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ rc = qemuMonitorAddDeviceArgs(qemuDomainGetMonitor(vm), vcpuprops);
|
|
|
6ae9ed |
+ vcpuprops = NULL;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (rc < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ virJSONValueFree(vcpuprops);
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ ret = 0;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ cleanup:
|
|
|
6ae9ed |
+ VIR_FREE(bootHotplug);
|
|
|
6ae9ed |
+ virJSONValueFree(vcpuprops);
|
|
|
6ae9ed |
+ return ret;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
/**
|
|
|
6ae9ed |
* qemuProcessPrepareDomain
|
|
|
6ae9ed |
*
|
|
|
6ae9ed |
@@ -5195,6 +5361,18 @@ qemuProcessLaunch(virConnectPtr conn,
|
|
|
6ae9ed |
if (qemuSetupCpusetMems(vm) < 0)
|
|
|
6ae9ed |
goto cleanup;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+ VIR_DEBUG("setting up hotpluggable cpus");
|
|
|
6ae9ed |
+ if (qemuDomainHasHotpluggableStartupVcpus(vm->def)) {
|
|
|
6ae9ed |
+ if (qemuDomainRefreshVcpuInfo(driver, vm, asyncJob, false) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (qemuProcessValidateHotpluggableVcpus(vm->def) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (qemuProcessSetupHotpluggableVcpus(driver, vm, asyncJob) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
VIR_DEBUG("Refreshing VCPU info");
|
|
|
6ae9ed |
if (qemuDomainRefreshVcpuInfo(driver, vm, asyncJob, false) < 0)
|
|
|
6ae9ed |
goto cleanup;
|
|
|
6ae9ed |
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-hotplug-startup.args b/tests/qemuxml2argvdata/qemuxml2argv-cpu-hotplug-startup.args
|
|
|
6ae9ed |
new file mode 100644
|
|
|
6ae9ed |
index 0000000..035f250
|
|
|
6ae9ed |
--- /dev/null
|
|
|
6ae9ed |
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-hotplug-startup.args
|
|
|
6ae9ed |
@@ -0,0 +1,20 @@
|
|
|
6ae9ed |
+LC_ALL=C \
|
|
|
6ae9ed |
+PATH=/bin \
|
|
|
6ae9ed |
+HOME=/home/test \
|
|
|
6ae9ed |
+USER=test \
|
|
|
6ae9ed |
+LOGNAME=test \
|
|
|
6ae9ed |
+QEMU_AUDIO_DRV=none \
|
|
|
6ae9ed |
+/usr/bin/qemu \
|
|
|
6ae9ed |
+-name QEMUGuest1 \
|
|
|
6ae9ed |
+-S \
|
|
|
6ae9ed |
+-M pc \
|
|
|
6ae9ed |
+-m 214 \
|
|
|
6ae9ed |
+-smp 1,maxcpus=6,sockets=3,cores=2,threads=1 \
|
|
|
6ae9ed |
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
|
|
|
6ae9ed |
+-nographic \
|
|
|
6ae9ed |
+-nodefaults \
|
|
|
6ae9ed |
+-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \
|
|
|
6ae9ed |
+-no-acpi \
|
|
|
6ae9ed |
+-boot n \
|
|
|
6ae9ed |
+-usb \
|
|
|
6ae9ed |
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
|
|
|
6ae9ed |
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-hotplug-startup.xml b/tests/qemuxml2argvdata/qemuxml2argv-cpu-hotplug-startup.xml
|
|
|
6ae9ed |
new file mode 100644
|
|
|
6ae9ed |
index 0000000..58718aa
|
|
|
6ae9ed |
--- /dev/null
|
|
|
6ae9ed |
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-hotplug-startup.xml
|
|
|
6ae9ed |
@@ -0,0 +1,29 @@
|
|
|
6ae9ed |
+<domain type='qemu'>
|
|
|
6ae9ed |
+ <name>QEMUGuest1</name>
|
|
|
6ae9ed |
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
|
|
6ae9ed |
+ <memory unit='KiB'>219100</memory>
|
|
|
6ae9ed |
+ <currentMemory unit='KiB'>219100</currentMemory>
|
|
|
6ae9ed |
+ <vcpu placement='static' current='3'>6</vcpu>
|
|
|
6ae9ed |
+ <vcpus>
|
|
|
6ae9ed |
+ <vcpu id='0' enabled='yes' hotpluggable='no' order='1'/>
|
|
|
6ae9ed |
+ <vcpu id='1' enabled='no' hotpluggable='yes'/>
|
|
|
6ae9ed |
+ <vcpu id='2' enabled='no' hotpluggable='yes'/>
|
|
|
6ae9ed |
+ <vcpu id='3' enabled='no' hotpluggable='yes'/>
|
|
|
6ae9ed |
+ <vcpu id='4' enabled='yes' hotpluggable='yes' order='2'/>
|
|
|
6ae9ed |
+ <vcpu id='5' enabled='yes' hotpluggable='yes' order='3'/>
|
|
|
6ae9ed |
+ </vcpus>
|
|
|
6ae9ed |
+ <os>
|
|
|
6ae9ed |
+ <type arch='x86_64' machine='pc'>hvm</type>
|
|
|
6ae9ed |
+ <boot dev='network'/>
|
|
|
6ae9ed |
+ </os>
|
|
|
6ae9ed |
+ <cpu>
|
|
|
6ae9ed |
+ <topology sockets="3" cores="2" threads="1"/>
|
|
|
6ae9ed |
+ </cpu>
|
|
|
6ae9ed |
+ <clock offset='utc'/>
|
|
|
6ae9ed |
+ <on_poweroff>destroy</on_poweroff>
|
|
|
6ae9ed |
+ <on_reboot>restart</on_reboot>
|
|
|
6ae9ed |
+ <on_crash>destroy</on_crash>
|
|
|
6ae9ed |
+ <devices>
|
|
|
6ae9ed |
+ <emulator>/usr/bin/qemu</emulator>
|
|
|
6ae9ed |
+ </devices>
|
|
|
6ae9ed |
+</domain>
|
|
|
6ae9ed |
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
|
|
|
6ae9ed |
index a9a3e6b..9de2f94 100644
|
|
|
6ae9ed |
--- a/tests/qemuxml2argvtest.c
|
|
|
6ae9ed |
+++ b/tests/qemuxml2argvtest.c
|
|
|
6ae9ed |
@@ -2102,6 +2102,8 @@ mymain(void)
|
|
|
6ae9ed |
DO_TEST("intel-iommu", QEMU_CAPS_DEVICE_PCI_BRIDGE,
|
|
|
6ae9ed |
QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, QEMU_CAPS_DEVICE_INTEL_IOMMU);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+ DO_TEST("cpu-hotplug-startup", QEMU_CAPS_QUERY_HOTPLUGGABLE_CPUS);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
qemuTestDriverFree(&driver);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
|
6ae9ed |
--
|
|
|
6ae9ed |
2.10.0
|
|
|
6ae9ed |
|