提交 376261d1 编写于 作者: J Jiri Denemark 提交者: Peter Krempa

cpu: Add support for loading and storing CPU data

This patch adds cpuDataFormat and cpuDataParse APIs to be used in unit
tests for testing APIs that deal with virCPUData. In the x86 world, this
means we can now store/load arbitrary CPUID data in the test suite to
check correctness of CPU related APIs that could not be tested before.
Signed-off-by: NPeter Krempa <pkrempa@redhat.com>
上级 fe1bf917
......@@ -442,6 +442,47 @@ cpuHasFeature(const virCPUData *data,
return driver->hasFeature(data, feature);
}
char *
cpuDataFormat(const virCPUData *data)
{
struct cpuArchDriver *driver;
VIR_DEBUG("data=%p", data);
if (!(driver = cpuGetSubDriver(data->arch)))
return NULL;
if (!driver->dataFormat) {
virReportError(VIR_ERR_NO_SUPPORT,
_("cannot format %s CPU data"),
virArchToString(data->arch));
return NULL;
}
return driver->dataFormat(data);
}
virCPUDataPtr
cpuDataParse(virArch arch,
const char *xmlStr)
{
struct cpuArchDriver *driver;
VIR_DEBUG("arch=%s, xmlStr=%s", virArchToString(arch), xmlStr);
if (!(driver = cpuGetSubDriver(arch)))
return NULL;
if (!driver->dataParse) {
virReportError(VIR_ERR_NO_SUPPORT,
_("cannot parse %s CPU data"),
virArchToString(arch));
return NULL;
}
return driver->dataParse(xmlStr);
}
bool
cpuModelIsAllowed(const char *model,
const char **models,
......
......@@ -93,6 +93,11 @@ typedef int
(*cpuArchHasFeature) (const virCPUData *data,
const char *feature);
typedef char *
(*cpuArchDataFormat)(const virCPUData *data);
typedef virCPUDataPtr
(*cpuArchDataParse) (const char *xmlStr);
struct cpuArchDriver {
const char *name;
......@@ -107,6 +112,8 @@ struct cpuArchDriver {
cpuArchBaseline baseline;
cpuArchUpdate update;
cpuArchHasFeature hasFeature;
cpuArchDataFormat dataFormat;
cpuArchDataParse dataParse;
};
......@@ -178,4 +185,11 @@ cpuModelIsAllowed(const char *model,
extern int
cpuGetModels(const char *arch, char ***models);
/* cpuDataFormat and cpuDataParse are implemented for unit tests only and
* have no real-life usage
*/
char *cpuDataFormat(const virCPUData *data);
virCPUDataPtr cpuDataParse(virArch arch,
const char *xmlStr);
#endif /* __VIR_CPU_H__ */
......@@ -665,6 +665,35 @@ x86FeatureNames(const struct x86_map *map,
}
static int
x86ParseCPUID(xmlXPathContextPtr ctxt,
struct cpuX86cpuid *cpuid)
{
unsigned long fun, eax, ebx, ecx, edx;
int ret_fun, ret_eax, ret_ebx, ret_ecx, ret_edx;
memset(cpuid, 0, sizeof(*cpuid));
fun = eax = ebx = ecx = edx = 0;
ret_fun = virXPathULongHex("string(@function)", ctxt, &fun);
ret_eax = virXPathULongHex("string(@eax)", ctxt, &eax);
ret_ebx = virXPathULongHex("string(@ebx)", ctxt, &ebx);
ret_ecx = virXPathULongHex("string(@ecx)", ctxt, &ecx);
ret_edx = virXPathULongHex("string(@edx)", ctxt, &edx);
if (ret_fun < 0 || ret_eax == -2 || ret_ebx == -2
|| ret_ecx == -2 || ret_edx == -2)
return -1;
cpuid->function = fun;
cpuid->eax = eax;
cpuid->ebx = ebx;
cpuid->ecx = ecx;
cpuid->edx = edx;
return 0;
}
static int
x86FeatureLoad(xmlXPathContextPtr ctxt,
struct x86_map *map)
......@@ -672,6 +701,7 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
xmlNodePtr *nodes = NULL;
xmlNodePtr ctxt_node = ctxt->node;
struct x86_feature *feature;
struct cpuX86cpuid cpuid;
int ret = 0;
size_t i;
int n;
......@@ -697,31 +727,13 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
goto ignore;
for (i = 0; i < n; i++) {
struct cpuX86cpuid cpuid;
unsigned long fun, eax, ebx, ecx, edx;
int ret_fun, ret_eax, ret_ebx, ret_ecx, ret_edx;
ctxt->node = nodes[i];
fun = eax = ebx = ecx = edx = 0;
ret_fun = virXPathULongHex("string(@function)", ctxt, &fun);
ret_eax = virXPathULongHex("string(@eax)", ctxt, &eax);
ret_ebx = virXPathULongHex("string(@ebx)", ctxt, &ebx);
ret_ecx = virXPathULongHex("string(@ecx)", ctxt, &ecx);
ret_edx = virXPathULongHex("string(@edx)", ctxt, &edx);
if (ret_fun < 0 || ret_eax == -2 || ret_ebx == -2
|| ret_ecx == -2 || ret_edx == -2) {
if (x86ParseCPUID(ctxt, &cpuid) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Invalid cpuid[%zu] in %s feature"), i, feature->name);
_("Invalid cpuid[%zu] in %s feature"),
i, feature->name);
goto ignore;
}
cpuid.function = fun;
cpuid.eax = eax;
cpuid.ebx = ebx;
cpuid.ecx = ecx;
cpuid.edx = edx;
if (x86DataAddCpuid(feature->data, &cpuid))
goto error;
}
......@@ -1124,6 +1136,85 @@ error:
}
static char *
x86CPUDataFormat(const virCPUData *data)
{
struct data_iterator iter = DATA_ITERATOR_INIT(data->data.x86);
struct cpuX86cpuid *cpuid;
virBuffer buf = VIR_BUFFER_INITIALIZER;
virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
while ((cpuid = x86DataCpuidNext(&iter))) {
virBufferAsprintf(&buf,
" <cpuid function='0x%08x'"
" eax='0x%08x' ebx='0x%08x'"
" ecx='0x%08x' edx='0x%08x'/>\n",
cpuid->function,
cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
}
virBufferAddLit(&buf, "</cpudata>\n");
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
return NULL;
}
return virBufferContentAndReset(&buf);
}
static virCPUDataPtr
x86CPUDataParse(const char *xmlStr)
{
xmlDocPtr xml = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlNodePtr *nodes = NULL;
virCPUDataPtr cpuData = NULL;
struct cpuX86Data *data = NULL;
struct cpuX86cpuid cpuid;
size_t i;
int n;
if (VIR_ALLOC(data) < 0)
goto cleanup;
if (!(xml = virXMLParseStringCtxt(xmlStr, _("CPU data"), &ctxt))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot parse CPU data"));
goto cleanup;
}
ctxt->node = xmlDocGetRootElement(xml);
n = virXPathNodeSet("/cpudata[@arch='x86']/data", ctxt, &nodes);
if (n < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("no x86 CPU data found"));
goto cleanup;
}
for (i = 0; i < n; i++) {
ctxt->node = nodes[i];
if (x86ParseCPUID(ctxt, &cpuid) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("failed to parse cpuid[%zu]"), i);
goto cleanup;
}
if (x86DataAddCpuid(data, &cpuid) < 0)
goto cleanup;
}
cpuData = x86MakeCPUData(VIR_ARCH_X86_64, &data);
cleanup:
VIR_FREE(nodes);
xmlXPathFreeContext(ctxt);
xmlFreeDoc(xml);
x86DataFree(data);
return cpuData;
}
/* A helper macro to exit the cpu computation function without writing
* redundant code:
* MSG: error message
......@@ -1956,4 +2047,6 @@ struct cpuArchDriver cpuDriverX86 = {
.baseline = x86Baseline,
.update = x86Update,
.hasFeature = x86HasFeature,
.dataFormat = x86CPUDataFormat,
.dataParse = x86CPUDataParse,
};
......@@ -720,7 +720,9 @@ cpuBaseline;
cpuBaselineXML;
cpuCompare;
cpuCompareXML;
cpuDataFormat;
cpuDataFree;
cpuDataParse;
cpuDecode;
cpuEncode;
cpuGetModels;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册