[libvirt] [PATCH 38/41] cpu: Rework cpuHasFeature

Jiri Denemark jdenemar at redhat.com
Fri Aug 12 13:33:32 UTC 2016


The function is renamed to virCPUDataCheckFeature and another function
(virCPUCheckFeature) which works on CPU definition rather than raw CPU
data is introduced.

Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
---
 src/cpu/cpu.c                 | 55 ++++++++++++++++++++++++++++++++++++-------
 src/cpu/cpu.h                 | 23 ++++++++++++++----
 src/cpu/cpu_arm.c             |  1 -
 src/cpu/cpu_ppc64.c           |  1 -
 src/cpu/cpu_s390.c            |  1 -
 src/cpu/cpu_x86.c             | 30 ++++++++++++++++++++---
 src/libvirt_private.syms      |  3 ++-
 src/qemu/qemu_command.c       |  2 +-
 src/qemu/qemu_domain.c        |  7 ++++--
 src/qemu/qemu_parse_command.c |  2 +-
 src/qemu/qemu_process.c       | 10 ++++----
 src/vmware/vmware_conf.c      |  6 ++---
 tests/cputest.c               |  6 ++++-
 13 files changed, 113 insertions(+), 34 deletions(-)

diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index e215304..d6b0372 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -648,9 +648,45 @@ virCPUUpdate(virArch arch,
 
 
 /**
- * cpuHasFeature:
+ * virCPUCheckFeature:
  *
- * @data: internal CPU representation
+ * @arch: CPU architecture
+ * @cpu: CPU definition
+ * @feature: feature to be checked for
+ *
+ * Checks whether @feature is supported by the CPU described by @cpu.
+ *
+ * Returns 1 if the feature is supported, 0 if it's not supported, or
+ * -1 on error.
+ */
+int
+virCPUCheckFeature(virArch arch,
+                   const virCPUDef *cpu,
+                   const char *feature)
+{
+    struct cpuArchDriver *driver;
+
+    VIR_DEBUG("arch=%s, cpu=%p, feature=%s",
+              virArchToString(arch), cpu, feature);
+
+    if (!(driver = cpuGetSubDriver(arch)))
+        return -1;
+
+    if (!driver->checkFeature) {
+        virReportError(VIR_ERR_NO_SUPPORT,
+                       _("cannot check guest CPU feature for %s architecture"),
+                       virArchToString(arch));
+        return -1;
+    }
+
+    return driver->checkFeature(cpu, feature);
+}
+
+
+/**
+ * virCPUDataCheckFeature:
+ *
+ * @data: CPU data
  * @feature: feature to be checked for
  *
  * Checks whether @feature is supported by the CPU described by @data.
@@ -659,24 +695,25 @@ virCPUUpdate(virArch arch,
  * -1 on error.
  */
 int
-cpuHasFeature(const virCPUData *data,
-              const char *feature)
+virCPUDataCheckFeature(const virCPUData *data,
+                       const char *feature)
 {
     struct cpuArchDriver *driver;
 
-    VIR_DEBUG("data=%p, feature=%s", data, feature);
+    VIR_DEBUG("arch=%s, data=%p, feature=%s",
+              virArchToString(data->arch), data, feature);
 
-    if ((driver = cpuGetSubDriver(data->arch)) == NULL)
+    if (!(driver = cpuGetSubDriver(data->arch)))
         return -1;
 
-    if (driver->hasFeature == NULL) {
+    if (!driver->dataCheckFeature) {
         virReportError(VIR_ERR_NO_SUPPORT,
-                       _("cannot check guest CPU data for %s architecture"),
+                       _("cannot check guest CPU feature for %s architecture"),
                        virArchToString(data->arch));
         return -1;
     }
 
-    return driver->hasFeature(data, feature);
+    return driver->dataCheckFeature(data, feature);
 }
 
 
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index b8036b2..77ccb38 100644
--- a/src/cpu/cpu.h
+++ b/src/cpu/cpu.h
@@ -91,8 +91,12 @@ typedef int
                     const virCPUDef *host);
 
 typedef int
-(*cpuArchHasFeature) (const virCPUData *data,
-                      const char *feature);
+(*virCPUArchCheckFeature)(const virCPUDef *cpu,
+                          const char *feature);
+
+typedef int
+(*virCPUArchDataCheckFeature)(const virCPUData *data,
+                              const char *feature);
 
 typedef char *
 (*cpuArchDataFormat)(const virCPUData *data);
@@ -120,7 +124,8 @@ struct cpuArchDriver {
     cpuArchGuestData    guestData;
     cpuArchBaseline     baseline;
     virCPUArchUpdate    update;
-    cpuArchHasFeature    hasFeature;
+    virCPUArchCheckFeature checkFeature;
+    virCPUArchDataCheckFeature dataCheckFeature;
     cpuArchDataFormat   dataFormat;
     cpuArchDataParse    dataParse;
     cpuArchGetModels    getModels;
@@ -193,9 +198,17 @@ virCPUUpdate(virArch arch,
              const virCPUDef *host)
     ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
 
+
 int
-cpuHasFeature(const virCPUData *data,
-              const char *feature)
+virCPUCheckFeature(virArch arch,
+                   const virCPUDef *cpu,
+                   const char *feature)
+    ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
+
+int
+virCPUDataCheckFeature(const virCPUData *data,
+                       const char *feature)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
 
diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c
index 49da36e..3b68d83 100644
--- a/src/cpu/cpu_arm.c
+++ b/src/cpu/cpu_arm.c
@@ -131,5 +131,4 @@ struct cpuArchDriver cpuDriverArm = {
     .guestData = armGuestData,
     .baseline = armBaseline,
     .update = virCPUarmUpdate,
-    .hasFeature = NULL,
 };
diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c
index 00faa22..6f005e5 100644
--- a/src/cpu/cpu_ppc64.c
+++ b/src/cpu/cpu_ppc64.c
@@ -910,6 +910,5 @@ struct cpuArchDriver cpuDriverPPC64 = {
     .guestData  = ppc64DriverGuestData,
     .baseline   = ppc64DriverBaseline,
     .update     = virCPUppc64Update,
-    .hasFeature = NULL,
     .getModels  = ppc64DriverGetModels,
 };
diff --git a/src/cpu/cpu_s390.c b/src/cpu/cpu_s390.c
index 23a7f9d..fb352a0 100644
--- a/src/cpu/cpu_s390.c
+++ b/src/cpu/cpu_s390.c
@@ -83,5 +83,4 @@ struct cpuArchDriver cpuDriverS390 = {
     .guestData  = NULL,
     .baseline   = NULL,
     .update     = NULL,
-    .hasFeature = NULL,
 };
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index 69b081d..782c917 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -2601,8 +2601,30 @@ virCPUx86Update(virCPUDefPtr guest,
 
 
 static int
-x86HasFeature(const virCPUData *data,
-              const char *name)
+virCPUx86CheckFeature(const virCPUDef *cpu,
+                      const char *name)
+{
+    int ret = -1;
+    virCPUx86MapPtr map;
+    virCPUx86ModelPtr model = NULL;
+
+    if (!(map = virCPUx86GetMap()))
+        return -1;
+
+    if (!(model = x86ModelFromCPU(cpu, map, -1)))
+        goto cleanup;
+
+    ret = x86FeatureInData(name, &model->data, map);
+
+ cleanup:
+    x86ModelFree(model);
+    return ret;
+}
+
+
+static int
+virCPUx86DataCheckFeature(const virCPUData *data,
+                          const char *name)
 {
     virCPUx86MapPtr map;
 
@@ -2612,6 +2634,7 @@ x86HasFeature(const virCPUData *data,
     return x86FeatureInData(name, &data->data.x86, map);
 }
 
+
 static int
 x86GetModels(char ***models)
 {
@@ -2708,7 +2731,8 @@ struct cpuArchDriver cpuDriverX86 = {
     .guestData  = x86GuestData,
     .baseline   = x86Baseline,
     .update     = virCPUx86Update,
-    .hasFeature = x86HasFeature,
+    .checkFeature = virCPUx86CheckFeature,
+    .dataCheckFeature = virCPUx86DataCheckFeature,
     .dataFormat = x86CPUDataFormat,
     .dataParse  = x86CPUDataParse,
     .getModels  = x86GetModels,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1f50499..15aac81 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -969,8 +969,9 @@ cpuDecode;
 cpuEncode;
 cpuGetModels;
 cpuGuestData;
-cpuHasFeature;
 cpuNodeData;
+virCPUCheckFeature;
+virCPUDataCheckFeature;
 virCPUTranslate;
 virCPUUpdate;
 
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index ce04c76..985b628 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6473,7 +6473,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
      */
     if ((def->os.arch == VIR_ARCH_X86_64 || def->os.arch == VIR_ARCH_I686) &&
          compareAgainstHost) {
-        int hasSVM = cpuHasFeature(data, "svm");
+        int hasSVM = virCPUDataCheckFeature(data, "svm");
         if (hasSVM < 0)
             goto cleanup;
         *hasHwVirt = hasSVM > 0 ? true : false;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index d8c589e..decbdd0 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -3402,10 +3402,13 @@ char *qemuDomainFormatXML(virQEMUDriverPtr driver,
 {
     virDomainDefPtr def;
 
-    if ((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef)
+    if ((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef) {
         def = vm->newDef;
-    else
+    } else {
         def = vm->def;
+        if (virDomainObjIsActive(vm))
+            flags &= ~VIR_DOMAIN_XML_UPDATE_CPU;
+    }
 
     return qemuDomainDefFormatXML(driver, def, flags);
 }
diff --git a/src/qemu/qemu_parse_command.c b/src/qemu/qemu_parse_command.c
index 82d1621..e3a6a34 100644
--- a/src/qemu/qemu_parse_command.c
+++ b/src/qemu/qemu_parse_command.c
@@ -1605,7 +1605,7 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
                           NULL, NULL, NULL, NULL) < 0)
                 goto cleanup;
 
-            is_32bit = (cpuHasFeature(cpuData, "lm") != 1);
+            is_32bit = (virCPUDataCheckFeature(cpuData, "lm") != 1);
             cpuDataFree(cpuData);
         } else if (model) {
             is_32bit = STREQ(model, "qemu32");
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 662a46a..d4269db 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3694,7 +3694,7 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver,
         }
 
         if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK] == VIR_TRISTATE_SWITCH_ON) {
-            if (!cpuHasFeature(guestcpu, VIR_CPU_x86_KVM_PV_UNHALT)) {
+            if (!virCPUDataCheckFeature(guestcpu, VIR_CPU_x86_KVM_PV_UNHALT)) {
                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                _("host doesn't support paravirtual spinlocks"));
                 goto cleanup;
@@ -3707,7 +3707,7 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver,
                 if (virAsprintf(&cpuFeature, "__kvm_hv_%s",
                                 virDomainHypervTypeToString(i)) < 0)
                     goto cleanup;
-                if (!cpuHasFeature(guestcpu, cpuFeature)) {
+                if (!virCPUDataCheckFeature(guestcpu, cpuFeature)) {
                     switch ((virDomainHyperv) i) {
                     case VIR_DOMAIN_HYPERV_RELAXED:
                     case VIR_DOMAIN_HYPERV_VAPIC:
@@ -3743,7 +3743,7 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver,
                     continue;
 
                 if (STREQ(feature->name, "invtsc") &&
-                    !cpuHasFeature(guestcpu, feature->name)) {
+                    !virCPUDataCheckFeature(guestcpu, feature->name)) {
                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                    _("host doesn't support invariant TSC"));
                     goto cleanup;
@@ -4448,8 +4448,8 @@ qemuProcessStartValidateGuestCPU(virDomainObjPtr vm,
     case VIR_CPU_COMPARE_INCOMPATIBLE:
         if (cpuEncode(host->arch, host, NULL, &hostData,
                       NULL, NULL, NULL, NULL) == 0 &&
-            (!cpuHasFeature(hostData, "hle") ||
-             !cpuHasFeature(hostData, "rtm")) &&
+            (!virCPUDataCheckFeature(hostData, "hle") ||
+             !virCPUDataCheckFeature(hostData, "rtm")) &&
             (STREQ_NULLABLE(cpu->model, "Haswell") ||
              STREQ_NULLABLE(cpu->model, "Broadwell")))
             noTSX = true;
diff --git a/src/vmware/vmware_conf.c b/src/vmware/vmware_conf.c
index 8736976..4222f4e 100644
--- a/src/vmware/vmware_conf.c
+++ b/src/vmware/vmware_conf.c
@@ -100,9 +100,9 @@ vmwareCapsInit(void)
      *  - Host CPU is x86_64 with virtualization extensions
      */
     if (caps->host.arch == VIR_ARCH_X86_64 ||
-        (cpuHasFeature(data, "lm") &&
-         (cpuHasFeature(data, "vmx") ||
-          cpuHasFeature(data, "svm")))) {
+        (virCPUDataCheckFeature(data, "lm") &&
+         (virCPUDataCheckFeature(data, "vmx") ||
+          virCPUDataCheckFeature(data, "svm")))) {
 
         if ((guest = virCapabilitiesAddGuest(caps,
                                              VIR_DOMAIN_OSTYPE_HVM,
diff --git a/tests/cputest.c b/tests/cputest.c
index e6696e9..72f00b6 100644
--- a/tests/cputest.c
+++ b/tests/cputest.c
@@ -430,7 +430,11 @@ cpuTestHasFeature(const void *arg)
                   NULL, NULL, NULL, NULL) < 0)
         goto cleanup;
 
-    result = cpuHasFeature(hostData, data->name);
+    result = virCPUCheckFeature(host->arch, host, data->name);
+
+    if (data->result == result)
+        result = virCPUDataCheckFeature(hostData, data->name);
+
     if (data->result == -1)
         virResetLastError();
 
-- 
2.9.2




More information about the libvir-list mailing list