]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Report better host-model CPUs in domain caps
authorJiri Denemark <jdenemar@redhat.com>
Wed, 8 Mar 2017 12:32:46 +0000 (13:32 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Mon, 13 Mar 2017 22:49:57 +0000 (23:49 +0100)
One of the main reasons for introducing host-model CPU definition in a
domain capabilities XML was the inability to express disabled features
in a host capabilities XML. That is, when a host CPU is, e.g., Haswell
without x2apic support, host capabilities XML will have to report it as
Westmere + a bunch of additional features., but we really want to use
Haswell - x2apic when creating a host-model CPU.

Unfortunately, I somehow forgot to do the last step and the code would
just copy the CPU definition found in the host capabilities XML. This
changed recently for new QEMU versions which allow us to query host CPU,
but any slightly older QEMU will not benefit from any change I did. This
patch makes sure the right CPU model is filled in the domain
capabilities even with old QEMU.

The issue was reported in
https://bugzilla.redhat.com/show_bug.cgi?id=1426456

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
src/qemu/qemu_capabilities.c
src/qemu/qemu_capspriv.h
tests/Makefile.am
tests/domaincapstest.c
tests/qemucpumock.c [new file with mode: 0644]
tests/qemuxml2argvtest.c

index 08c66b0880f6f85763fe231d1541d74bfe81a3ca..70f9ed777aa707d9299501df8bee789304075156 100644 (file)
@@ -1074,6 +1074,26 @@ virQEMUCapsProbeHostCPU(virCapsPtr caps)
 }
 
 
+virCPUDefPtr
+virQEMUCapsProbeHostCPUForEmulator(virCapsPtr caps,
+                                   virQEMUCapsPtr qemuCaps,
+                                   virDomainVirtType type)
+{
+    size_t nmodels;
+    char **models;
+    virCPUDefPtr cpu;
+
+    if (virQEMUCapsGetCPUDefinitions(qemuCaps, type, &models, &nmodels) < 0)
+        return NULL;
+
+    cpu = virCPUGetHost(caps->host.arch, VIR_CPU_TYPE_GUEST, NULL,
+                        (const char **) models, nmodels);
+
+    virStringListFreeCount(models, nmodels);
+    return cpu;
+}
+
+
 static int
 virQEMUCapsInitPages(virCapsPtr caps)
 {
@@ -3207,6 +3227,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
                             virDomainVirtType type)
 {
     virCPUDefPtr cpu = NULL;
+    virCPUDefPtr hostCPU = NULL;
     int rc;
 
     if (!caps || !virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch))
@@ -3223,11 +3244,11 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
     if ((rc = virQEMUCapsInitCPUModel(qemuCaps, type, cpu)) < 0) {
         goto error;
     } else if (rc == 1) {
-        VIR_DEBUG("No host CPU model info from QEMU; using host capabilities");
-        if (!caps->host.cpu || !caps->host.cpu->model)
-            goto error;
+        VIR_DEBUG("No host CPU model info from QEMU; probing host CPU directly");
 
-        if (virCPUDefCopyModelFilter(cpu, caps->host.cpu, true,
+        hostCPU = virQEMUCapsProbeHostCPUForEmulator(caps, qemuCaps, type);
+        if (!hostCPU ||
+            virCPUDefCopyModelFilter(cpu, hostCPU, true,
                                      virQEMUCapsCPUFilterFeatures,
                                      qemuCaps) < 0)
             goto error;
@@ -3238,11 +3259,14 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
     else
         qemuCaps->tcgCPUModel = cpu;
 
+ cleanup:
+    virCPUDefFree(hostCPU);
     return;
 
  error:
     virCPUDefFree(cpu);
     virResetLastError();
+    goto cleanup;
 }
 
 
index e0544f273b2ef37e296f227bfb1f35b81fa9e931..ee29b8bba71e5539f4783288b7f0523b92b7bf01 100644 (file)
@@ -87,4 +87,9 @@ void
 virQEMUCapsSetCPUModelInfo(virQEMUCapsPtr qemuCaps,
                            virDomainVirtType type,
                            qemuMonitorCPUModelInfoPtr modelInfo);
+
+virCPUDefPtr
+virQEMUCapsProbeHostCPUForEmulator(virCapsPtr caps,
+                                   virQEMUCapsPtr qemuCaps,
+                                   virDomainVirtType type);
 #endif
index 35e82abf5f53fa55f7fa4a993b849e8ee1991014..af69a3a843a531b5567aa057631bd05dd73698e8 100644 (file)
@@ -284,6 +284,7 @@ test_libraries += libqemumonitortestutils.la \
                qemuxml2xmlmock.la \
                qemucaps2xmlmock.la \
                qemucapsprobemock.la \
+               qemucpumock.la \
                $(NULL)
 endif WITH_QEMU
 
@@ -549,10 +550,16 @@ libqemutestdriver_la_SOURCES =
 libqemutestdriver_la_LDFLAGS = $(QEMULIB_LDFLAGS)
 libqemutestdriver_la_LIBADD = $(qemu_LDADDS)
 
+qemucpumock_la_SOURCES = \
+       qemucpumock.c
+qemucpumock_la_CFLAGS = $(AM_CFLAGS)
+qemucpumock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
+qemucpumock_la_LIBADD = $(MOCKLIBS_LIBS)
+
 qemuxml2argvtest_SOURCES = \
        qemuxml2argvtest.c testutilsqemu.c testutilsqemu.h \
        testutils.c testutils.h
-qemuxml2argvtest_LDADD = $(qemu_LDADDS) $(LDADDS) $(LIBXML_LIBS)
+qemuxml2argvtest_LDADD = libqemutestdriver.la $(LDADDS) $(LIBXML_LIBS)
 
 qemuxml2argvmock_la_SOURCES = \
        qemuxml2argvmock.c
@@ -949,7 +956,7 @@ domaincapstest_LDADD = $(LDADDS)
 
 if WITH_QEMU
 domaincapstest_SOURCES += testutilsqemu.c testutilsqemu.h
-domaincapstest_LDADD += $(qemu_LDADDS) $(GNULIB_LIBS)
+domaincapstest_LDADD += libqemutestdriver.la $(GNULIB_LIBS)
 endif WITH_QEMU
 
 if WITH_LIBXL
index 9b64f2c18a46ffa51d0b8f098620d5d8c0f7bdf9..a4bc8d6d0d719df7fdb9fecbde43d73d116ac789 100644 (file)
@@ -491,4 +491,10 @@ mymain(void)
     return ret;
 }
 
+#if WITH_QEMU
+VIRT_TEST_MAIN_PRELOAD(mymain,
+                       abs_builddir "/.libs/domaincapsmock.so",
+                       abs_builddir "/.libs/qemucpumock.so")
+#else
 VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/domaincapsmock.so")
+#endif
diff --git a/tests/qemucpumock.c b/tests/qemucpumock.c
new file mode 100644 (file)
index 0000000..2c1d24d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "internal.h"
+#include "qemu/qemu_capabilities.h"
+#define __QEMU_CAPSRIV_H_ALLOW__
+#include "qemu/qemu_capspriv.h"
+#undef __QEMU_CAPSRIV_H_ALLOW__
+
+
+virCPUDefPtr
+virQEMUCapsProbeHostCPUForEmulator(virCapsPtr caps,
+                                   virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED,
+                                   virDomainVirtType type ATTRIBUTE_UNUSED)
+{
+    if (!caps || !caps->host.cpu || !caps->host.cpu->model)
+        return NULL;
+
+    return virCPUDefCopy(caps->host.cpu);
+}
index 00b0e25cdab1c5f6758197b2338a72e098145fe7..6bd74659926673d824b17b241b75e164e58df71b 100644 (file)
@@ -2473,8 +2473,10 @@ mymain(void)
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
-VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/qemuxml2argvmock.so",
-                       abs_builddir "/.libs/virrandommock.so")
+VIRT_TEST_MAIN_PRELOAD(mymain,
+                       abs_builddir "/.libs/qemuxml2argvmock.so",
+                       abs_builddir "/.libs/virrandommock.so",
+                       abs_builddir "/.libs/qemucpumock.so")
 
 #else