Blob Blame History Raw
From 4d614a11dd3164c63a5e28fdeff8b5f196a7ee18 Mon Sep 17 00:00:00 2001
Message-Id: <4d614a11dd3164c63a5e28fdeff8b5f196a7ee18@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 24 Aug 2016 16:11:30 -0400
Subject: [PATCH] qemu: domain: Extract cpu-hotplug related data

https://bugzilla.redhat.com/show_bug.cgi?id=1097930
https://bugzilla.redhat.com/show_bug.cgi?id=1224341

Now that the monitor code gathers all the data we can extract it to
relevant places either in the definition or the private data of a vcpu.

As only thread id is broken for TCG guests we may extract the rest of
the data and just skip assigning of the thread id. In case where qemu
would allow cpu hotplug in TCG mode this will make it work eventually.

(cherry picked from commit 6b4a23ff6c78bfc901a3c1a33460423ff702461f)
---
 src/qemu/qemu_domain.c | 90 ++++++++++++++++++++++++++++++++------------------
 src/qemu/qemu_domain.h | 10 ++++++
 2 files changed, 67 insertions(+), 33 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ebd0d9e..259fd79 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -847,8 +847,12 @@ qemuDomainVcpuPrivateNew(void)
 
 
 static void
-qemuDomainVcpuPrivateDispose(void *obj ATTRIBUTE_UNUSED)
+qemuDomainVcpuPrivateDispose(void *obj)
 {
+    qemuDomainVcpuPrivatePtr priv = obj;
+
+    VIR_FREE(priv->type);
+    VIR_FREE(priv->alias);
     return;
 }
 
@@ -5696,6 +5700,15 @@ qemuDomainValidateVcpuInfo(virDomainObjPtr vm)
 }
 
 
+bool
+qemuDomainSupportsNewVcpuHotplug(virDomainObjPtr vm)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+
+    return virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_HOTPLUGGABLE_CPUS);
+}
+
+
 /**
  * qemuDomainRefreshVcpuInfo:
  * @driver: qemu driver data
@@ -5717,44 +5730,16 @@ qemuDomainRefreshVcpuInfo(virQEMUDriverPtr driver,
     qemuMonitorCPUInfoPtr info = NULL;
     size_t maxvcpus = virDomainDefGetVcpusMax(vm->def);
     size_t i;
+    bool hotplug;
     int rc;
     int ret = -1;
 
-    /*
-     * Current QEMU *can* report info about host threads mapped
-     * to vCPUs, but it is not in a manner we can correctly
-     * deal with. The TCG CPU emulation does have a separate vCPU
-     * thread, but it runs every vCPU in that same thread. So it
-     * is impossible to setup different affinity per thread.
-     *
-     * What's more the 'query-cpus' command returns bizarre
-     * data for the threads. It gives the TCG thread for the
-     * vCPU 0, but for vCPUs 1-> N, it actually replies with
-     * the main process thread ID.
-     *
-     * The result is that when we try to set affinity for
-     * vCPU 1, it will actually change the affinity of the
-     * emulator thread :-( When you try to set affinity for
-     * vCPUs 2, 3.... it will fail if the affinity was
-     * different from vCPU 1.
-     *
-     * We *could* allow vcpu pinning with TCG, if we made the
-     * restriction that all vCPUs had the same mask. This would
-     * at least let us separate emulator from vCPUs threads, as
-     * we do for KVM. It would need some changes to our cgroups
-     * CPU layout though, and error reporting for the config
-     * restrictions.
-     *
-     * Just disable CPU pinning with TCG until someone wants
-     * to try to do this hard work.
-     */
-    if (vm->def->virtType == VIR_DOMAIN_VIRT_QEMU)
-        return 0;
+    hotplug = qemuDomainSupportsNewVcpuHotplug(vm);
 
     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
         return -1;
 
-    rc = qemuMonitorGetCPUInfo(qemuDomainGetMonitor(vm), &info, maxvcpus, false);
+    rc = qemuMonitorGetCPUInfo(qemuDomainGetMonitor(vm), &info, maxvcpus, hotplug);
 
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
@@ -5766,7 +5751,46 @@ qemuDomainRefreshVcpuInfo(virQEMUDriverPtr driver,
         vcpu = virDomainDefGetVcpu(vm->def, i);
         vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
 
-        vcpupriv->tid = info[i].tid;
+        /*
+         * Current QEMU *can* report info about host threads mapped
+         * to vCPUs, but it is not in a manner we can correctly
+         * deal with. The TCG CPU emulation does have a separate vCPU
+         * thread, but it runs every vCPU in that same thread. So it
+         * is impossible to setup different affinity per thread.
+         *
+         * What's more the 'query-cpus' command returns bizarre
+         * data for the threads. It gives the TCG thread for the
+         * vCPU 0, but for vCPUs 1-> N, it actually replies with
+         * the main process thread ID.
+         *
+         * The result is that when we try to set affinity for
+         * vCPU 1, it will actually change the affinity of the
+         * emulator thread :-( When you try to set affinity for
+         * vCPUs 2, 3.... it will fail if the affinity was
+         * different from vCPU 1.
+         *
+         * We *could* allow vcpu pinning with TCG, if we made the
+         * restriction that all vCPUs had the same mask. This would
+         * at least let us separate emulator from vCPUs threads, as
+         * we do for KVM. It would need some changes to our cgroups
+         * CPU layout though, and error reporting for the config
+         * restrictions.
+         *
+         * Just disable CPU pinning with TCG until someone wants
+         * to try to do this hard work.
+         */
+        if (vm->def->virtType != VIR_DOMAIN_VIRT_QEMU)
+            vcpupriv->tid = info[i].tid;
+
+        vcpupriv->socket_id = info[i].socket_id;
+        vcpupriv->core_id = info[i].core_id;
+        vcpupriv->thread_id = info[i].thread_id;
+        vcpupriv->vcpus = info[i].vcpus;
+        VIR_FREE(vcpupriv->type);
+        VIR_STEAL_PTR(vcpupriv->type, info[i].type);
+        VIR_FREE(vcpupriv->alias);
+        VIR_STEAL_PTR(vcpupriv->alias, info[i].alias);
+        vcpupriv->enable_id = info[i].id;
     }
 
     ret = 0;
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index a7176c4..c3ae169 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -317,6 +317,15 @@ struct _qemuDomainVcpuPrivate {
     virObject parent;
 
     pid_t tid; /* vcpu thread id */
+    int enable_id; /* order in which the vcpus were enabled in qemu */
+    char *alias;
+
+    /* information for hotpluggable cpus */
+    char *type;
+    int socket_id;
+    int core_id;
+    int thread_id;
+    int vcpus;
 };
 
 # define QEMU_DOMAIN_VCPU_PRIVATE(vcpu)    \
@@ -647,6 +656,7 @@ int qemuDomainDefValidateMemoryHotplug(const virDomainDef *def,
                                        virQEMUCapsPtr qemuCaps,
                                        const virDomainMemoryDef *mem);
 
+bool qemuDomainSupportsNewVcpuHotplug(virDomainObjPtr vm);
 bool qemuDomainHasVcpuPids(virDomainObjPtr vm);
 pid_t qemuDomainGetVcpuPid(virDomainObjPtr vm, unsigned int vcpuid);
 int qemuDomainValidateVcpuInfo(virDomainObjPtr vm);
-- 
2.10.0