[libvirt] [PATCH 2/7] cpu: Replace cpuNodeData with virCPUGetHost

Jiri Denemark jdenemar at redhat.com
Wed Mar 8 13:46:23 UTC 2017


cpuNodeData has always been followed by cpuDecode as no hypervisor
driver is really interested in raw CPUID data for a host CPU. Let's
create a new CPU driver API which returns virCPUDefPtr directly.

Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
---
 src/bhyve/bhyve_capabilities.c | 34 ++++---------------------
 src/cpu/cpu.c                  | 58 ++++++++++++++++++++++++++++++++++--------
 src/cpu/cpu.h                  | 11 ++++----
 src/cpu/cpu_arm.c              |  1 -
 src/cpu/cpu_ppc64.c            | 28 ++++++++++----------
 src/cpu/cpu_s390.c             |  1 -
 src/cpu/cpu_x86.c              | 27 +++++++++-----------
 src/libvirt_private.syms       |  2 +-
 src/qemu/qemu_capabilities.c   | 32 +++--------------------
 src/vmware/vmware_conf.c       | 19 +++-----------
 src/vz/vz_driver.c             | 21 ++-------------
 11 files changed, 95 insertions(+), 139 deletions(-)

diff --git a/src/bhyve/bhyve_capabilities.c b/src/bhyve/bhyve_capabilities.c
index 52d6ca782..c2c9303d7 100644
--- a/src/bhyve/bhyve_capabilities.c
+++ b/src/bhyve/bhyve_capabilities.c
@@ -40,41 +40,17 @@ VIR_LOG_INIT("bhyve.bhyve_capabilities");
 
 static int
 virBhyveCapsInitCPU(virCapsPtr caps,
-                  virArch arch)
+                    virArch arch)
 {
-    virCPUDefPtr cpu = NULL;
-    virCPUDataPtr data = NULL;
     virNodeInfo nodeinfo;
-    int ret = -1;
-
-    if (VIR_ALLOC(cpu) < 0)
-        goto error;
-
-    cpu->arch = arch;
 
     if (nodeGetInfo(&nodeinfo))
-        goto error;
+        return -1;
 
-    cpu->type = VIR_CPU_TYPE_HOST;
-    cpu->sockets = nodeinfo.sockets;
-    cpu->cores = nodeinfo.cores;
-    cpu->threads = nodeinfo.threads;
-    caps->host.cpu = cpu;
+    if (!(caps->host.cpu = virCPUGetHost(arch, &nodeinfo)))
+        return -1;
 
-    if (!(data = cpuNodeData(arch)) ||
-        cpuDecode(cpu, data, NULL, 0, NULL) < 0)
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    virCPUDataFree(data);
-
-    return ret;
-
- error:
-    virCPUDefFree(cpu);
-    goto cleanup;
+    return 0;
 }
 
 virCapsPtr
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index 051a58040..c1666ed3b 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -357,30 +357,66 @@ virCPUDataFree(virCPUDataPtr data)
 
 
 /**
- * cpuNodeData:
+ * virCPUGetHost:
  *
  * @arch: CPU architecture
+ * @nodeInfo: simplified CPU topology (optional)
  *
- * Returns CPU data for host CPU or NULL on error.
+ * Create CPU definition describing the host's CPU. If @nodeInfo is not NULL,
+ * the CPU definition will have topology (sockets, cores, threads) filled in
+ * according to the content of @nodeInfo. The function fails only if @nodeInfo
+ * was not passed in and the assigned CPU driver was not able to detect the
+ * host CPU model. In other words, a CPU definition containing just the
+ * topology is a successful result even if detecting the host CPU model fails.
+ *
+ * Returns host CPU definition or NULL on error.
  */
-virCPUDataPtr
-cpuNodeData(virArch arch)
+virCPUDefPtr
+virCPUGetHost(virArch arch,
+              virNodeInfoPtr nodeInfo)
 {
     struct cpuArchDriver *driver;
+    virCPUDefPtr cpu = NULL;
 
-    VIR_DEBUG("arch=%s", virArchToString(arch));
+    VIR_DEBUG("arch=%s, nodeInfo=%p",
+              virArchToString(arch), nodeInfo);
 
-    if ((driver = cpuGetSubDriver(arch)) == NULL)
+    if (!(driver = cpuGetSubDriver(arch)))
         return NULL;
 
-    if (driver->nodeData == NULL) {
-        virReportError(VIR_ERR_NO_SUPPORT,
-                       _("cannot get node CPU data for %s architecture"),
-                       virArchToString(arch));
+    if (VIR_ALLOC(cpu) < 0)
         return NULL;
+
+    cpu->arch = arch;
+    cpu->type = VIR_CPU_TYPE_HOST;
+
+    if (nodeInfo) {
+        cpu->sockets = nodeInfo->sockets;
+        cpu->cores = nodeInfo->cores;
+        cpu->threads = nodeInfo->threads;
     }
 
-    return driver->nodeData(arch);
+    /* Try to get the host CPU model, but don't really fail if nodeInfo is
+     * filled in.
+     */
+    if (driver->getHost) {
+        if (driver->getHost(cpu) < 0 && !nodeInfo)
+            goto error;
+    } else if (nodeInfo) {
+        VIR_DEBUG("cannot detect host CPU model for %s architecture",
+                  virArchToString(arch));
+    } else {
+        virReportError(VIR_ERR_NO_SUPPORT,
+                       _("cannot detect host CPU model for %s architecture"),
+                       virArchToString(arch));
+        goto error;
+    }
+
+    return cpu;
+
+ error:
+    virCPUDefFree(cpu);
+    return NULL;
 }
 
 
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index 0324284b9..cbbb45223 100644
--- a/src/cpu/cpu.h
+++ b/src/cpu/cpu.h
@@ -70,8 +70,8 @@ typedef int
 typedef void
 (*cpuArchDataFree)  (virCPUDataPtr data);
 
-typedef virCPUDataPtr
-(*cpuArchNodeData)  (virArch arch);
+typedef int
+(*virCPUArchGetHost)(virCPUDefPtr cpu);
 
 typedef virCPUDefPtr
 (*cpuArchBaseline)  (virCPUDefPtr *cpus,
@@ -117,7 +117,7 @@ struct cpuArchDriver {
     cpuArchDecode       decode;
     cpuArchEncode       encode;
     cpuArchDataFree     dataFree;
-    cpuArchNodeData     nodeData;
+    virCPUArchGetHost   getHost;
     cpuArchBaseline     baseline;
     virCPUArchUpdate    update;
     virCPUArchCheckFeature checkFeature;
@@ -168,8 +168,9 @@ virCPUDataNew(virArch arch);
 void
 virCPUDataFree(virCPUDataPtr data);
 
-virCPUDataPtr
-cpuNodeData (virArch arch);
+virCPUDefPtr
+virCPUGetHost(virArch arch,
+              virNodeInfoPtr nodeInfo);
 
 char *
 cpuBaselineXML(const char **xmlCPUs,
diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c
index 3a0ee2b14..a1aba2554 100644
--- a/src/cpu/cpu_arm.c
+++ b/src/cpu/cpu_arm.c
@@ -111,7 +111,6 @@ struct cpuArchDriver cpuDriverArm = {
     .compare = virCPUarmCompare,
     .decode = NULL,
     .encode = NULL,
-    .nodeData = NULL,
     .baseline = armBaseline,
     .update = virCPUarmUpdate,
 };
diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c
index a7c8545db..bb715546b 100644
--- a/src/cpu/cpu_ppc64.c
+++ b/src/cpu/cpu_ppc64.c
@@ -714,19 +714,21 @@ virCPUppc64DataFree(virCPUDataPtr data)
     VIR_FREE(data);
 }
 
-static virCPUDataPtr
-ppc64DriverNodeData(virArch arch)
+
+static int
+virCPUppc64GetHost(virCPUDefPtr cpu)
 {
-    virCPUDataPtr nodeData;
+    virCPUDataPtr cpuData = NULL;
     virCPUppc64Data *data;
+    int ret = -1;
 
-    if (VIR_ALLOC(nodeData) < 0)
-        goto error;
+    if (!(cpuData = virCPUDataNew(archs[0])))
+        goto cleanup;
 
-    data = &nodeData->data.ppc64;
+    data = &cpuData->data.ppc64;
 
     if (VIR_ALLOC_N(data->pvr, 1) < 0)
-        goto error;
+        goto cleanup;
 
     data->len = 1;
 
@@ -736,13 +738,11 @@ ppc64DriverNodeData(virArch arch)
 #endif
     data->pvr[0].mask = 0xfffffffful;
 
-    nodeData->arch = arch;
+    ret = ppc64DriverDecode(cpu, cpuData, NULL, 0, NULL, 0);
 
-    return nodeData;
-
- error:
-    virCPUppc64DataFree(nodeData);
-    return NULL;
+ cleanup:
+    virCPUppc64DataFree(cpuData);
+    return ret;
 }
 
 
@@ -902,7 +902,7 @@ struct cpuArchDriver cpuDriverPPC64 = {
     .decode     = ppc64DriverDecode,
     .encode     = NULL,
     .dataFree   = virCPUppc64DataFree,
-    .nodeData   = ppc64DriverNodeData,
+    .getHost    = virCPUppc64GetHost,
     .baseline   = ppc64DriverBaseline,
     .update     = virCPUppc64Update,
     .getModels  = virCPUppc64DriverGetModels,
diff --git a/src/cpu/cpu_s390.c b/src/cpu/cpu_s390.c
index 9503e8e2b..c08a24a53 100644
--- a/src/cpu/cpu_s390.c
+++ b/src/cpu/cpu_s390.c
@@ -109,7 +109,6 @@ struct cpuArchDriver cpuDriverS390 = {
     .compare    = virCPUs390Compare,
     .decode     = NULL,
     .encode     = NULL,
-    .nodeData   = NULL,
     .baseline   = NULL,
     .update     = virCPUs390Update,
 };
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index bcf50cb9e..bddb169ba 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -2437,25 +2437,24 @@ cpuidSet(uint32_t base, virCPUDataPtr data)
 }
 
 
-static virCPUDataPtr
-x86NodeData(virArch arch)
+static int
+virCPUx86GetHost(virCPUDefPtr cpu)
 {
     virCPUDataPtr cpuData = NULL;
+    int ret = -1;
 
-    if (!(cpuData = virCPUDataNew(arch)))
-        goto error;
+    if (!(cpuData = virCPUDataNew(archs[0])))
+        goto cleanup;
 
-    if (cpuidSet(CPUX86_BASIC, cpuData) < 0)
-        goto error;
+    if (cpuidSet(CPUX86_BASIC, cpuData) < 0 ||
+        cpuidSet(CPUX86_EXTENDED, cpuData) < 0)
+        goto cleanup;
 
-    if (cpuidSet(CPUX86_EXTENDED, cpuData) < 0)
-        goto error;
+    ret = x86DecodeCPUData(cpu, cpuData, NULL, 0, NULL, 0);
 
-    return cpuData;
-
- error:
+ cleanup:
     virCPUx86DataFree(cpuData);
-    return NULL;
+    return ret;
 }
 #endif
 
@@ -2849,9 +2848,7 @@ struct cpuArchDriver cpuDriverX86 = {
     .encode     = x86Encode,
     .dataFree   = virCPUx86DataFree,
 #if defined(__i386__) || defined(__x86_64__)
-    .nodeData   = x86NodeData,
-#else
-    .nodeData   = NULL,
+    .getHost    = virCPUx86GetHost,
 #endif
     .baseline   = x86Baseline,
     .update     = virCPUx86Update,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6c89d44e2..4efea0098 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -996,7 +996,6 @@ cpuBaseline;
 cpuBaselineXML;
 cpuDecode;
 cpuEncode;
-cpuNodeData;
 virCPUCheckFeature;
 virCPUCompare;
 virCPUCompareXML;
@@ -1006,6 +1005,7 @@ virCPUDataFormat;
 virCPUDataFree;
 virCPUDataNew;
 virCPUDataParse;
+virCPUGetHost;
 virCPUGetModels;
 virCPUTranslate;
 virCPUUpdate;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 5a3b4ac50..b0a4861c3 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -1065,39 +1065,15 @@ static int
 virQEMUCapsInitCPU(virCapsPtr caps,
                    virArch arch)
 {
-    virCPUDefPtr cpu = NULL;
-    virCPUDataPtr data = NULL;
     virNodeInfo nodeinfo;
-    int ret = -1;
-
-    if (VIR_ALLOC(cpu) < 0)
-        goto error;
-
-    cpu->arch = arch;
 
     if (nodeGetInfo(&nodeinfo))
-        goto error;
+        return -1;
 
-    cpu->type = VIR_CPU_TYPE_HOST;
-    cpu->sockets = nodeinfo.sockets;
-    cpu->cores = nodeinfo.cores;
-    cpu->threads = nodeinfo.threads;
-    caps->host.cpu = cpu;
+    if (!(caps->host.cpu = virCPUGetHost(arch, &nodeinfo)))
+        return -1;
 
-    if (!(data = cpuNodeData(arch))
-        || cpuDecode(cpu, data, NULL, 0, NULL) < 0)
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    virCPUDataFree(data);
-
-    return ret;
-
- error:
-    virCPUDefFree(cpu);
-    goto cleanup;
+    return 0;
 }
 
 
diff --git a/src/vmware/vmware_conf.c b/src/vmware/vmware_conf.c
index 5b1b5f5fd..d1444e462 100644
--- a/src/vmware/vmware_conf.c
+++ b/src/vmware/vmware_conf.c
@@ -62,7 +62,6 @@ vmwareCapsInit(void)
     virCapsPtr caps = NULL;
     virCapsGuestPtr guest = NULL;
     virCPUDefPtr cpu = NULL;
-    virCPUDataPtr data = NULL;
 
     if ((caps = virCapabilitiesNew(virArchFromHost(),
                                    false, false)) == NULL)
@@ -83,26 +82,18 @@ vmwareCapsInit(void)
                                       NULL, NULL, 0, NULL) == NULL)
         goto error;
 
-    if (VIR_ALLOC(cpu) < 0)
+    if (!(cpu = virCPUGetHost(caps->host.arch, NULL)))
         goto error;
 
-    cpu->arch = caps->host.arch;
-    cpu->type = VIR_CPU_TYPE_HOST;
-
-    if (!(data = cpuNodeData(cpu->arch))
-        || cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
-        goto error;
-    }
-
     /* x86_64 guests are supported if
      *  - Host arch is x86_64
      * Or
      *  - Host CPU is x86_64 with virtualization extensions
      */
     if (caps->host.arch == VIR_ARCH_X86_64 ||
-        (virCPUDataCheckFeature(data, "lm") &&
-         (virCPUDataCheckFeature(data, "vmx") ||
-          virCPUDataCheckFeature(data, "svm")))) {
+        (virCPUCheckFeature(cpu->arch, cpu, "lm") &&
+         (virCPUCheckFeature(cpu->arch, cpu, "vmx") ||
+          virCPUCheckFeature(cpu->arch, cpu, "svm")))) {
 
         if ((guest = virCapabilitiesAddGuest(caps,
                                              VIR_DOMAIN_OSTYPE_HVM,
@@ -118,8 +109,6 @@ vmwareCapsInit(void)
 
  cleanup:
     virCPUDefFree(cpu);
-    virCPUDataFree(data);
-
     return caps;
 
  error:
diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c
index 1ca9fd726..f97a2045b 100644
--- a/src/vz/vz_driver.c
+++ b/src/vz/vz_driver.c
@@ -99,8 +99,6 @@ static virCapsPtr
 vzBuildCapabilities(void)
 {
     virCapsPtr caps = NULL;
-    virCPUDefPtr cpu = NULL;
-    virCPUDataPtr data = NULL;
     virNodeInfo nodeinfo;
     virDomainOSType ostypes[] = {
         VIR_DOMAIN_OSTYPE_HVM,
@@ -131,32 +129,17 @@ vzBuildCapabilities(void)
     if (nodeGetInfo(&nodeinfo))
         goto error;
 
-    if (VIR_ALLOC(cpu) < 0)
+    if (!(caps->host.cpu = virCPUGetHost(caps->host.arch, &nodeinfo)))
         goto error;
 
-    cpu->arch = caps->host.arch;
-    cpu->type = VIR_CPU_TYPE_HOST;
-    cpu->sockets = nodeinfo.sockets;
-    cpu->cores = nodeinfo.cores;
-    cpu->threads = nodeinfo.threads;
-
-    caps->host.cpu = cpu;
-
     if (virCapabilitiesAddHostMigrateTransport(caps, "vzmigr") < 0)
         goto error;
 
-    if (!(data = cpuNodeData(cpu->arch))
-        || cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
-        goto cleanup;
-    }
-
- cleanup:
-    virCPUDataFree(data);
     return caps;
 
  error:
     virObjectUnref(caps);
-    goto cleanup;
+    return NULL;
 }
 
 static void vzDriverDispose(void * obj)
-- 
2.12.0




More information about the libvir-list mailing list