|
|
43fe83 |
From ba31d47b940dc748a291e9b68efcf84178ea6800 Mon Sep 17 00:00:00 2001
|
|
|
43fe83 |
Message-Id: <ba31d47b940dc748a291e9b68efcf84178ea6800.1383922566.git.jdenemar@redhat.com>
|
|
|
43fe83 |
From: Jiri Denemark <jdenemar@redhat.com>
|
|
|
43fe83 |
Date: Fri, 8 Nov 2013 12:33:17 +0100
|
|
|
43fe83 |
Subject: [PATCH] cpu: Add support for loading and storing CPU data
|
|
|
43fe83 |
|
|
|
43fe83 |
https://bugzilla.redhat.com/show_bug.cgi?id=1008989
|
|
|
43fe83 |
|
|
|
43fe83 |
This patch adds cpuDataFormat and cpuDataParse APIs to be used in unit
|
|
|
43fe83 |
tests for testing APIs that deal with virCPUData. In the x86 world, this
|
|
|
43fe83 |
means we can now store/load arbitrary CPUID data in the test suite to
|
|
|
43fe83 |
check correctness of CPU related APIs that could not be tested before.
|
|
|
43fe83 |
|
|
|
43fe83 |
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
|
|
43fe83 |
(cherry picked from commit 376261d164b0872bf011e525b4f0f050e942ace5)
|
|
|
43fe83 |
|
|
|
43fe83 |
Conflicts:
|
|
|
43fe83 |
src/cpu/cpu.h - virCPUGetModel was not backported (context)
|
|
|
43fe83 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
43fe83 |
---
|
|
|
43fe83 |
src/cpu/cpu.c | 41 ++++++++++++++
|
|
|
43fe83 |
src/cpu/cpu.h | 14 +++++
|
|
|
43fe83 |
src/cpu/cpu_x86.c | 135 +++++++++++++++++++++++++++++++++++++++--------
|
|
|
43fe83 |
src/libvirt_private.syms | 2 +
|
|
|
43fe83 |
4 files changed, 171 insertions(+), 21 deletions(-)
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
|
|
|
43fe83 |
index 4124354..7989b45 100644
|
|
|
43fe83 |
--- a/src/cpu/cpu.c
|
|
|
43fe83 |
+++ b/src/cpu/cpu.c
|
|
|
43fe83 |
@@ -438,6 +438,47 @@ cpuHasFeature(const virCPUDataPtr data,
|
|
|
43fe83 |
return driver->hasFeature(data, feature);
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
+char *
|
|
|
43fe83 |
+cpuDataFormat(const virCPUData *data)
|
|
|
43fe83 |
+{
|
|
|
43fe83 |
+ struct cpuArchDriver *driver;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ VIR_DEBUG("data=%p", data);
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (!(driver = cpuGetSubDriver(data->arch)))
|
|
|
43fe83 |
+ return NULL;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (!driver->dataFormat) {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
43fe83 |
+ _("cannot format %s CPU data"),
|
|
|
43fe83 |
+ virArchToString(data->arch));
|
|
|
43fe83 |
+ return NULL;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ return driver->dataFormat(data);
|
|
|
43fe83 |
+}
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+virCPUDataPtr
|
|
|
43fe83 |
+cpuDataParse(virArch arch,
|
|
|
43fe83 |
+ const char *xmlStr)
|
|
|
43fe83 |
+{
|
|
|
43fe83 |
+ struct cpuArchDriver *driver;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ VIR_DEBUG("arch=%s, xmlStr=%s", virArchToString(arch), xmlStr);
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (!(driver = cpuGetSubDriver(arch)))
|
|
|
43fe83 |
+ return NULL;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (!driver->dataParse) {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
43fe83 |
+ _("cannot parse %s CPU data"),
|
|
|
43fe83 |
+ virArchToString(arch));
|
|
|
43fe83 |
+ return NULL;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ return driver->dataParse(xmlStr);
|
|
|
43fe83 |
+}
|
|
|
43fe83 |
+
|
|
|
43fe83 |
bool
|
|
|
43fe83 |
cpuModelIsAllowed(const char *model,
|
|
|
43fe83 |
const char **models,
|
|
|
43fe83 |
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
|
|
|
43fe83 |
index 4003435..7417f92 100644
|
|
|
43fe83 |
--- a/src/cpu/cpu.h
|
|
|
43fe83 |
+++ b/src/cpu/cpu.h
|
|
|
43fe83 |
@@ -91,6 +91,11 @@ typedef int
|
|
|
43fe83 |
(*cpuArchHasFeature) (const virCPUDataPtr data,
|
|
|
43fe83 |
const char *feature);
|
|
|
43fe83 |
|
|
|
43fe83 |
+typedef char *
|
|
|
43fe83 |
+(*cpuArchDataFormat)(const virCPUData *data);
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+typedef virCPUDataPtr
|
|
|
43fe83 |
+(*cpuArchDataParse) (const char *xmlStr);
|
|
|
43fe83 |
|
|
|
43fe83 |
struct cpuArchDriver {
|
|
|
43fe83 |
const char *name;
|
|
|
43fe83 |
@@ -105,6 +110,8 @@ struct cpuArchDriver {
|
|
|
43fe83 |
cpuArchBaseline baseline;
|
|
|
43fe83 |
cpuArchUpdate update;
|
|
|
43fe83 |
cpuArchHasFeature hasFeature;
|
|
|
43fe83 |
+ cpuArchDataFormat dataFormat;
|
|
|
43fe83 |
+ cpuArchDataParse dataParse;
|
|
|
43fe83 |
};
|
|
|
43fe83 |
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -171,4 +178,11 @@ cpuModelIsAllowed(const char *model,
|
|
|
43fe83 |
const char **models,
|
|
|
43fe83 |
unsigned int nmodels);
|
|
|
43fe83 |
|
|
|
43fe83 |
+/* cpuDataFormat and cpuDataParse are implemented for unit tests only and
|
|
|
43fe83 |
+ * have no real-life usage
|
|
|
43fe83 |
+ */
|
|
|
43fe83 |
+char *cpuDataFormat(const virCPUData *data);
|
|
|
43fe83 |
+virCPUDataPtr cpuDataParse(virArch arch,
|
|
|
43fe83 |
+ const char *xmlStr);
|
|
|
43fe83 |
+
|
|
|
43fe83 |
#endif /* __VIR_CPU_H__ */
|
|
|
43fe83 |
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
|
|
|
43fe83 |
index a388f0f..0bc031b 100644
|
|
|
43fe83 |
--- a/src/cpu/cpu_x86.c
|
|
|
43fe83 |
+++ b/src/cpu/cpu_x86.c
|
|
|
43fe83 |
@@ -666,12 +666,42 @@ x86FeatureNames(const struct x86_map *map,
|
|
|
43fe83 |
|
|
|
43fe83 |
|
|
|
43fe83 |
static int
|
|
|
43fe83 |
+x86ParseCPUID(xmlXPathContextPtr ctxt,
|
|
|
43fe83 |
+ struct cpuX86cpuid *cpuid)
|
|
|
43fe83 |
+{
|
|
|
43fe83 |
+ unsigned long fun, eax, ebx, ecx, edx;
|
|
|
43fe83 |
+ int ret_fun, ret_eax, ret_ebx, ret_ecx, ret_edx;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ memset(cpuid, 0, sizeof(*cpuid));
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ fun = eax = ebx = ecx = edx = 0;
|
|
|
43fe83 |
+ ret_fun = virXPathULongHex("string(@function)", ctxt, &fun);
|
|
|
43fe83 |
+ ret_eax = virXPathULongHex("string(@eax)", ctxt, &eax;;
|
|
|
43fe83 |
+ ret_ebx = virXPathULongHex("string(@ebx)", ctxt, &ebx);
|
|
|
43fe83 |
+ ret_ecx = virXPathULongHex("string(@ecx)", ctxt, &ecx;;
|
|
|
43fe83 |
+ ret_edx = virXPathULongHex("string(@edx)", ctxt, &edx;;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (ret_fun < 0 || ret_eax == -2 || ret_ebx == -2
|
|
|
43fe83 |
+ || ret_ecx == -2 || ret_edx == -2)
|
|
|
43fe83 |
+ return -1;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ cpuid->function = fun;
|
|
|
43fe83 |
+ cpuid->eax = eax;
|
|
|
43fe83 |
+ cpuid->ebx = ebx;
|
|
|
43fe83 |
+ cpuid->ecx = ecx;
|
|
|
43fe83 |
+ cpuid->edx = edx;
|
|
|
43fe83 |
+ return 0;
|
|
|
43fe83 |
+}
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+static int
|
|
|
43fe83 |
x86FeatureLoad(xmlXPathContextPtr ctxt,
|
|
|
43fe83 |
struct x86_map *map)
|
|
|
43fe83 |
{
|
|
|
43fe83 |
xmlNodePtr *nodes = NULL;
|
|
|
43fe83 |
xmlNodePtr ctxt_node = ctxt->node;
|
|
|
43fe83 |
struct x86_feature *feature;
|
|
|
43fe83 |
+ struct cpuX86cpuid cpuid;
|
|
|
43fe83 |
int ret = 0;
|
|
|
43fe83 |
size_t i;
|
|
|
43fe83 |
int n;
|
|
|
43fe83 |
@@ -697,31 +727,13 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
|
|
|
43fe83 |
goto ignore;
|
|
|
43fe83 |
|
|
|
43fe83 |
for (i = 0; i < n; i++) {
|
|
|
43fe83 |
- struct cpuX86cpuid cpuid;
|
|
|
43fe83 |
- unsigned long fun, eax, ebx, ecx, edx;
|
|
|
43fe83 |
- int ret_fun, ret_eax, ret_ebx, ret_ecx, ret_edx;
|
|
|
43fe83 |
-
|
|
|
43fe83 |
ctxt->node = nodes[i];
|
|
|
43fe83 |
- fun = eax = ebx = ecx = edx = 0;
|
|
|
43fe83 |
- ret_fun = virXPathULongHex("string(@function)", ctxt, &fun);
|
|
|
43fe83 |
- ret_eax = virXPathULongHex("string(@eax)", ctxt, &eax;;
|
|
|
43fe83 |
- ret_ebx = virXPathULongHex("string(@ebx)", ctxt, &ebx);
|
|
|
43fe83 |
- ret_ecx = virXPathULongHex("string(@ecx)", ctxt, &ecx;;
|
|
|
43fe83 |
- ret_edx = virXPathULongHex("string(@edx)", ctxt, &edx;;
|
|
|
43fe83 |
-
|
|
|
43fe83 |
- if (ret_fun < 0 || ret_eax == -2 || ret_ebx == -2
|
|
|
43fe83 |
- || ret_ecx == -2 || ret_edx == -2) {
|
|
|
43fe83 |
+ if (x86ParseCPUID(ctxt, &cpuid) < 0) {
|
|
|
43fe83 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
43fe83 |
- _("Invalid cpuid[%zu] in %s feature"), i, feature->name);
|
|
|
43fe83 |
+ _("Invalid cpuid[%zu] in %s feature"),
|
|
|
43fe83 |
+ i, feature->name);
|
|
|
43fe83 |
goto ignore;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
-
|
|
|
43fe83 |
- cpuid.function = fun;
|
|
|
43fe83 |
- cpuid.eax = eax;
|
|
|
43fe83 |
- cpuid.ebx = ebx;
|
|
|
43fe83 |
- cpuid.ecx = ecx;
|
|
|
43fe83 |
- cpuid.edx = edx;
|
|
|
43fe83 |
-
|
|
|
43fe83 |
if (x86DataAddCpuid(feature->data, &cpuid))
|
|
|
43fe83 |
goto error;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
@@ -1124,6 +1136,85 @@ error:
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
|
|
|
43fe83 |
+static char *
|
|
|
43fe83 |
+x86CPUDataFormat(const virCPUData *data)
|
|
|
43fe83 |
+{
|
|
|
43fe83 |
+ struct data_iterator iter = DATA_ITERATOR_INIT(data->data.x86);
|
|
|
43fe83 |
+ struct cpuX86cpuid *cpuid;
|
|
|
43fe83 |
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
|
|
|
43fe83 |
+ while ((cpuid = x86DataCpuidNext(&iter))) {
|
|
|
43fe83 |
+ virBufferAsprintf(&buf,
|
|
|
43fe83 |
+ "
|
|
|
43fe83 |
+ " eax='0x%08x' ebx='0x%08x'"
|
|
|
43fe83 |
+ " ecx='0x%08x' edx='0x%08x'/>\n",
|
|
|
43fe83 |
+ cpuid->function,
|
|
|
43fe83 |
+ cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ virBufferAddLit(&buf, "</cpudata>\n");
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (virBufferError(&buf)) {
|
|
|
43fe83 |
+ virBufferFreeAndReset(&buf;;
|
|
|
43fe83 |
+ virReportOOMError();
|
|
|
43fe83 |
+ return NULL;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ return virBufferContentAndReset(&buf;;
|
|
|
43fe83 |
+}
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+static virCPUDataPtr
|
|
|
43fe83 |
+x86CPUDataParse(const char *xmlStr)
|
|
|
43fe83 |
+{
|
|
|
43fe83 |
+ xmlDocPtr xml = NULL;
|
|
|
43fe83 |
+ xmlXPathContextPtr ctxt = NULL;
|
|
|
43fe83 |
+ xmlNodePtr *nodes = NULL;
|
|
|
43fe83 |
+ virCPUDataPtr cpuData = NULL;
|
|
|
43fe83 |
+ struct cpuX86Data *data = NULL;
|
|
|
43fe83 |
+ struct cpuX86cpuid cpuid;
|
|
|
43fe83 |
+ size_t i;
|
|
|
43fe83 |
+ int n;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (VIR_ALLOC(data) < 0)
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (!(xml = virXMLParseStringCtxt(xmlStr, _("CPU data"), &ctxt))) {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
43fe83 |
+ _("cannot parse CPU data"));
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ ctxt->node = xmlDocGetRootElement(xml);
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ n = virXPathNodeSet("/cpudata[@arch='x86']/data", ctxt, &nodes);
|
|
|
43fe83 |
+ if (n < 0) {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
43fe83 |
+ _("no x86 CPU data found"));
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ for (i = 0; i < n; i++) {
|
|
|
43fe83 |
+ ctxt->node = nodes[i];
|
|
|
43fe83 |
+ if (x86ParseCPUID(ctxt, &cpuid) < 0) {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
43fe83 |
+ _("failed to parse cpuid[%zu]"), i);
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ if (x86DataAddCpuid(data, &cpuid) < 0)
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ cpuData = x86MakeCPUData(VIR_ARCH_X86_64, &data);
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+cleanup:
|
|
|
43fe83 |
+ VIR_FREE(nodes);
|
|
|
43fe83 |
+ xmlXPathFreeContext(ctxt);
|
|
|
43fe83 |
+ xmlFreeDoc(xml);
|
|
|
43fe83 |
+ x86DataFree(data);
|
|
|
43fe83 |
+ return cpuData;
|
|
|
43fe83 |
+}
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+
|
|
|
43fe83 |
/* A helper macro to exit the cpu computation function without writing
|
|
|
43fe83 |
* redundant code:
|
|
|
43fe83 |
* MSG: error message
|
|
|
43fe83 |
@@ -1920,4 +2011,6 @@ struct cpuArchDriver cpuDriverX86 = {
|
|
|
43fe83 |
.baseline = x86Baseline,
|
|
|
43fe83 |
.update = x86Update,
|
|
|
43fe83 |
.hasFeature = x86HasFeature,
|
|
|
43fe83 |
+ .dataFormat = x86CPUDataFormat,
|
|
|
43fe83 |
+ .dataParse = x86CPUDataParse,
|
|
|
43fe83 |
};
|
|
|
43fe83 |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
43fe83 |
index ca6275c..722178b 100644
|
|
|
43fe83 |
--- a/src/libvirt_private.syms
|
|
|
43fe83 |
+++ b/src/libvirt_private.syms
|
|
|
43fe83 |
@@ -715,7 +715,9 @@ cpuBaseline;
|
|
|
43fe83 |
cpuBaselineXML;
|
|
|
43fe83 |
cpuCompare;
|
|
|
43fe83 |
cpuCompareXML;
|
|
|
43fe83 |
+cpuDataFormat;
|
|
|
43fe83 |
cpuDataFree;
|
|
|
43fe83 |
+cpuDataParse;
|
|
|
43fe83 |
cpuDecode;
|
|
|
43fe83 |
cpuEncode;
|
|
|
43fe83 |
cpuGuestData;
|
|
|
43fe83 |
--
|
|
|
43fe83 |
1.8.4.2
|
|
|
43fe83 |
|