Baseline CPU is the best CPU which can be used for a guest on any of the
hosts.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/cpu/cpu.c | 123 +++++++++++++++++++++++++++++++++++++++++++++-
src/cpu/cpu.h | 21 ++++++++-
src/cpu/cpu_generic.c | 3 +-
src/cpu/cpu_x86.c | 3 +-
src/libvirt_private.syms | 2 +
5 files changed, 148 insertions(+), 4 deletions(-)
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index e9ecc98..501a00c 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -1,7 +1,7 @@
/*
* cpu.c: internal functions for CPU manipulation
*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009--2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,6 +23,7 @@
#include <config.h>
+#include "memory.h"
#include "xml.h"
#include "cpu.h"
#include "cpu_x86.h"
@@ -237,3 +238,123 @@ cpuGuestData(virCPUDefPtr host,
return driver->guestData(host, guest, data);
}
+
+
+char *
+cpuBaselineXML(const char **xmlCPUs,
+ unsigned int ncpus,
+ const char **models,
+ unsigned int nmodels)
+{
+ xmlDocPtr doc = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ virCPUDefPtr *cpus = NULL;
+ virCPUDefPtr cpu = NULL;
+ char *cpustr;
+ unsigned int i;
+
+ if (xmlCPUs == NULL && ncpus != 0) {
+ virCPUReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("nonzero ncpus doesn't match with NULL
xmlCPUs"));
+ return NULL;
+ }
+
+ if (ncpus < 1) {
+ virCPUReportError(VIR_ERR_INVALID_ARG, "%s", _("No CPUs
given"));
+ return NULL;
+ }
+
+ if (VIR_ALLOC_N(cpus, ncpus))
+ goto no_memory;
+
+ for (i = 0; i < ncpus; i++) {
+ doc = xmlParseMemory(xmlCPUs[i], strlen(xmlCPUs[i]));
+ if (doc == NULL || (ctxt = xmlXPathNewContext(doc)) == NULL)
+ goto no_memory;
+
+ ctxt->node = xmlDocGetRootElement(doc);
+
+ cpus[i] = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_HOST);
+ if (cpus[i] == NULL)
+ goto error;
+
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(doc);
+ ctxt = NULL;
+ doc = NULL;
+ }
+
+ if (!(cpu = cpuBaseline(cpus, ncpus, models, nmodels)))
+ goto error;
+
+ cpustr = virCPUDefFormat(cpu, "", 0);
+
+cleanup:
+ if (cpus) {
+ for (i = 0; i < ncpus; i++)
+ virCPUDefFree(cpus[i]);
+ VIR_FREE(cpus);
+ }
+ virCPUDefFree(cpu);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(doc);
+
+ return cpustr;
+
+no_memory:
+ virReportOOMError();
+error:
+ cpustr = NULL;
+ goto cleanup;
+}
+
+
+virCPUDefPtr
+cpuBaseline(virCPUDefPtr *cpus,
+ unsigned int ncpus,
+ const char **models,
+ unsigned int nmodels)
+{
+ struct cpuArchDriver *driver;
+ virCPUDefPtr cpu;
+
+ if (cpus == NULL && ncpus != 0) {
+ virCPUReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("nonzero ncpus doesn't match with NULL
cpus"));
+ return NULL;
+ }
+
+ if (ncpus < 1) {
+ virCPUReportError(VIR_ERR_INVALID_ARG, "%s", _("No CPUs
given"));
+ return NULL;
+ }
+
+ if (models == NULL && nmodels != 0) {
+ virCPUReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("nonzero nmodels doesn't match with NULL
models"));
+ return NULL;
+ }
+
+ if ((driver = cpuGetSubDriver(cpus[0]->arch)) == NULL)
+ return NULL;
+
+ if (driver->baseline == NULL) {
+ virCPUReportError(VIR_ERR_NO_SUPPORT,
+ _("cannot compute baseline CPU of %s architecture"),
+ cpus[0]->arch);
+ return NULL;
+ }
+
+ if ((cpu = driver->baseline(cpus, ncpus, models, nmodels))) {
+ int i;
+
+ cpu->type = VIR_CPU_TYPE_GUEST;
+ cpu->match = VIR_CPU_MATCH_EXACT;
+ VIR_FREE(cpu->arch);
+
+ for (i = 0; i < cpu->nfeatures; i++)
+ cpu->features[i].policy = VIR_CPU_FEATURE_REQUIRE;
+ }
+
+ return cpu;
+}
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index 7ee0ce6..c8d961d 100644
--- a/src/cpu/cpu.h
+++ b/src/cpu/cpu.h
@@ -1,7 +1,7 @@
/*
* cpu.h: internal functions for CPU manipulation
*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009--2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -70,6 +70,12 @@ typedef virCPUCompareResult
virCPUDefPtr guest,
union cpuData **data);
+typedef virCPUDefPtr
+(*cpuArchBaseline) (virCPUDefPtr *cpus,
+ unsigned int ncpus,
+ const char **models,
+ unsigned int nmodels);
+
struct cpuArchDriver {
const char *name;
@@ -81,6 +87,7 @@ struct cpuArchDriver {
cpuArchDataFree free;
cpuArchNodeData nodeData;
cpuArchGuestData guestData;
+ cpuArchBaseline baseline;
};
@@ -119,4 +126,16 @@ cpuGuestData(virCPUDefPtr host,
virCPUDefPtr guest,
union cpuData **data);
+extern char *
+cpuBaselineXML(const char **xmlCPUs,
+ unsigned int ncpus,
+ const char **models,
+ unsigned int nmodels);
+
+extern virCPUDefPtr
+cpuBaseline (virCPUDefPtr *cpus,
+ unsigned int ncpus,
+ const char **models,
+ unsigned int nmodels);
+
#endif /* __VIR_CPU_H__ */
diff --git a/src/cpu/cpu_generic.c b/src/cpu/cpu_generic.c
index 566fed0..eac314d 100644
--- a/src/cpu/cpu_generic.c
+++ b/src/cpu/cpu_generic.c
@@ -118,5 +118,6 @@ struct cpuArchDriver cpuDriverGeneric = {
.encode = NULL,
.free = NULL,
.nodeData = NULL,
- .guestData = NULL
+ .guestData = NULL,
+ .baseline = NULL,
};
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index c6ed078..a6db86d 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -1205,5 +1205,6 @@ struct cpuArchDriver cpuDriverX86 = {
#else
.nodeData = NULL,
#endif
- .guestData = x86GuestData
+ .guestData = x86GuestData,
+ .baseline = NULL,
};
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7573af3..aa826d6 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -72,6 +72,8 @@ virCgroupSetFreezerState;
# cpu.h
+cpuBaseline;
+cpuBaselineXML;
cpuCompare;
cpuCompareXML;
cpuDataFree;
--
1.6.6.1