[libvirt] [PATCH 16/23] cputest: Use CPU models from QEMU when available

Jiri Denemark posted 23 patches 7 years, 7 months ago
There is a newer version of this series
[libvirt] [PATCH 16/23] cputest: Use CPU models from QEMU when available
Posted by Jiri Denemark 7 years, 7 months ago
When testing cpuDecode for computing guest CPU definition from CPUID
data (the CPU definition reported by domain capabilities), we need to
use CPU models (and their usability blockers) from QEMU if they are
available to cpuDecode in the same way it is actually used in the qemu
driver.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 tests/cputest.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 75 insertions(+), 6 deletions(-)

diff --git a/tests/cputest.c b/tests/cputest.c
index b72c17a168..18618ad309 100644
--- a/tests/cputest.c
+++ b/tests/cputest.c
@@ -515,6 +515,37 @@ cpuTestMakeQEMUCaps(const struct data *data)
     qemuCaps = NULL;
     goto cleanup;
 }
+
+
+static virDomainCapsCPUModelsPtr
+cpuTestGetCPUModels(const struct data *data)
+{
+    virDomainCapsCPUModelsPtr models = NULL;
+    virQEMUCapsPtr qemuCaps;
+
+    if (data->flags != JSON_MODELS)
+        return NULL;
+
+    if (!(qemuCaps = cpuTestMakeQEMUCaps(data)))
+        return NULL;
+
+    models = virQEMUCapsGetCPUDefinitions(qemuCaps, VIR_DOMAIN_VIRT_KVM);
+    if (models)
+        virObjectRef(models);
+
+    virObjectUnref(qemuCaps);
+
+    return models;
+}
+
+#else /* if WITH_QEMU && WITH_YAJL */
+
+static virDomainCapsCPUModelsPtr
+cpuTestGetCPUModels(const struct data *data ATTRIBUTE_UNUSED)
+{
+    return NULL;
+}
+
 #endif
 
 
@@ -528,6 +559,7 @@ cpuTestCPUID(bool guest, const void *arg)
     char *host = NULL;
     virCPUDefPtr cpu = NULL;
     char *result = NULL;
+    virDomainCapsCPUModelsPtr models = NULL;
 
     if (virAsprintf(&hostFile, "%s/cputestdata/%s-cpuid-%s.xml",
                     abs_srcdir, virArchToString(data->arch), data->host) < 0)
@@ -549,7 +581,10 @@ cpuTestCPUID(bool guest, const void *arg)
         cpu->type = VIR_CPU_TYPE_HOST;
     }
 
-    if (cpuDecode(cpu, hostData, NULL) < 0)
+    if (guest)
+        models = cpuTestGetCPUModels(data);
+
+    if (cpuDecode(cpu, hostData, models) < 0)
         goto cleanup;
 
     if (virAsprintf(&result, "cpuid-%s-%s",
@@ -565,6 +600,7 @@ cpuTestCPUID(bool guest, const void *arg)
     virCPUDataFree(hostData);
     virCPUDefFree(cpu);
     VIR_FREE(result);
+    virObjectUnref(models);
     return ret;
 }
 
@@ -686,6 +722,8 @@ cpuTestUpdateLive(const void *arg)
     virCPUDataPtr disabledData = NULL;
     char *expectedFile = NULL;
     virCPUDefPtr expected = NULL;
+    virDomainCapsCPUModelsPtr hvModels = NULL;
+    virDomainCapsCPUModelsPtr models = NULL;
     int ret = -1;
 
     if (virAsprintf(&cpuFile, "cpuid-%s-guest", data->host) < 0 ||
@@ -704,13 +742,42 @@ cpuTestUpdateLive(const void *arg)
         !(disabledData = virCPUDataParse(disabled)))
         goto cleanup;
 
-    if (virCPUUpdateLive(data->arch, cpu, enabledData, disabledData) < 0)
-        goto cleanup;
-
     if (virAsprintf(&expectedFile, "cpuid-%s-json", data->host) < 0 ||
         !(expected = cpuTestLoadXML(data->arch, expectedFile)))
         goto cleanup;
 
+    /* In case the host CPU signature does not exactly match any CPU model from
+     * cpu_map.xml, the CPU model we detect from CPUID may differ from the one
+     * we compute by asking QEMU. Since this test expands both CPU models and
+     * compares their features, we can try to translate the 'actual' CPU to
+     * use the CPU model from 'expected'.
+     */
+    if (STRNEQ(cpu->model, expected->model)) {
+        virDomainCapsCPUModelPtr hvModel;
+        char **blockers = NULL;
+        virDomainCapsCPUUsable usable = VIR_DOMCAPS_CPU_USABLE_UNKNOWN;
+
+        if (!(models = virDomainCapsCPUModelsNew(0)))
+            goto cleanup;
+
+        if ((hvModels = cpuTestGetCPUModels(data)) &&
+            virCPUModelIsAllowed(expected->model, hvModels, &hvModel)) {
+            blockers = hvModel->blockers;
+            usable = hvModel->usable;
+        }
+
+        if (virDomainCapsCPUModelsAdd(models, expected->model, -1,
+                                      usable, blockers) < 0)
+            goto cleanup;
+
+        cpu->fallback = VIR_CPU_FALLBACK_ALLOW;
+        ignore_value(virCPUTranslate(data->arch, cpu, models));
+        cpu->fallback = VIR_CPU_FALLBACK_FORBID;
+    }
+
+    if (virCPUUpdateLive(data->arch, cpu, enabledData, disabledData) < 0)
+        goto cleanup;
+
     ret = cpuTestUpdateLiveCompare(data->arch, cpu, expected);
 
  cleanup:
@@ -724,6 +791,8 @@ cpuTestUpdateLive(const void *arg)
     virCPUDataFree(disabledData);
     VIR_FREE(expectedFile);
     virCPUDefFree(expected);
+    virObjectUnref(hvModels);
+    virObjectUnref(models);
     return ret;
 }
 
@@ -915,11 +984,11 @@ mymain(void)
         DO_TEST(arch, cpuTestHostCPUID, host, host,                     \
                 NULL, NULL, 0, 0);                                      \
         DO_TEST(arch, cpuTestGuestCPUID, host, host,                    \
-                NULL, NULL, 0, 0);                                      \
+                NULL, NULL, json, 0);                                   \
         DO_TEST_CPUID_JSON(arch, host, json);                           \
         if (json != JSON_NONE) {                                        \
             DO_TEST(arch, cpuTestUpdateLive, host, host,                \
-                    NULL, NULL, 0, 0);                                  \
+                    NULL, NULL, json, 0);                               \
         }                                                               \
     } while (0)
 
-- 
2.14.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 16/23] cputest: Use CPU models from QEMU when available
Posted by John Ferlan 7 years, 7 months ago

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
> When testing cpuDecode for computing guest CPU definition from CPUID
> data (the CPU definition reported by domain capabilities), we need to
> use CPU models (and their usability blockers) from QEMU if they are
> available to cpuDecode in the same way it is actually used in the qemu
> driver.
> 
> Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
> ---
>  tests/cputest.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 75 insertions(+), 6 deletions(-)
> 
> diff --git a/tests/cputest.c b/tests/cputest.c
> index b72c17a168..18618ad309 100644
> --- a/tests/cputest.c
> +++ b/tests/cputest.c
> @@ -515,6 +515,37 @@ cpuTestMakeQEMUCaps(const struct data *data)
>      qemuCaps = NULL;
>      goto cleanup;
>  }
> +
> +
> +static virDomainCapsCPUModelsPtr
> +cpuTestGetCPUModels(const struct data *data)
> +{
> +    virDomainCapsCPUModelsPtr models = NULL;
> +    virQEMUCapsPtr qemuCaps;
> +
> +    if (data->flags != JSON_MODELS)
> +        return NULL;
> +
> +    if (!(qemuCaps = cpuTestMakeQEMUCaps(data)))
> +        return NULL;
> +
> +    models = virQEMUCapsGetCPUDefinitions(qemuCaps, VIR_DOMAIN_VIRT_KVM);
> +    if (models)
> +        virObjectRef(models);

As I learned a while back virObjectRef() works on a NULL @models - so no
need for the if (models) (and the Unref already doesn't have one).

> +
> +    virObjectUnref(qemuCaps);
> +
> +    return models;
> +}
> +

Reviewed-by: John Ferlan <jferlan@redhat.com>

John

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 16/23] cputest: Use CPU models from QEMU when available
Posted by Jiri Denemark 7 years, 7 months ago
On Thu, Oct 12, 2017 at 17:21:53 -0400, John Ferlan wrote:
> 
> 
> On 10/04/2017 10:58 AM, Jiri Denemark wrote:
> > When testing cpuDecode for computing guest CPU definition from CPUID
> > data (the CPU definition reported by domain capabilities), we need to
> > use CPU models (and their usability blockers) from QEMU if they are
> > available to cpuDecode in the same way it is actually used in the qemu
> > driver.
> > 
> > Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
> > ---
> >  tests/cputest.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
> >  1 file changed, 75 insertions(+), 6 deletions(-)
> > 
> > diff --git a/tests/cputest.c b/tests/cputest.c
> > index b72c17a168..18618ad309 100644
> > --- a/tests/cputest.c
> > +++ b/tests/cputest.c
> > @@ -515,6 +515,37 @@ cpuTestMakeQEMUCaps(const struct data *data)
> >      qemuCaps = NULL;
> >      goto cleanup;
> >  }
> > +
> > +
> > +static virDomainCapsCPUModelsPtr
> > +cpuTestGetCPUModels(const struct data *data)
> > +{
> > +    virDomainCapsCPUModelsPtr models = NULL;
> > +    virQEMUCapsPtr qemuCaps;
> > +
> > +    if (data->flags != JSON_MODELS)
> > +        return NULL;
> > +
> > +    if (!(qemuCaps = cpuTestMakeQEMUCaps(data)))
> > +        return NULL;
> > +
> > +    models = virQEMUCapsGetCPUDefinitions(qemuCaps, VIR_DOMAIN_VIRT_KVM);
> > +    if (models)
> > +        virObjectRef(models);
> 
> As I learned a while back virObjectRef() works on a NULL @models - so no
> need for the if (models) (and the Unref already doesn't have one).

Oh right. Somehow when I was checking it, I looked at
VIR_OBJECT_NOTVALID macro and completely ignored its body and looked at
the body of VIR_OBJECT_USAGE_PRINT_WARNING macro instead which made me
think virObjectRef prints some nasty warnings when obj == NULL.

Jirka

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list