diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index e9ecc980cfce684b7e526dde2752a502ccc88e27..501a00ca8cc1dfd098d8df7d30af56176438b0d7 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 +#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 7ee0ce6d7c33476e0940ae729e33e42434de6cd7..c8d961db4ea2f04c4d04851390b359522faeb936 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 566fed038c5949bdf03cb3c13ab267547ecfde98..eac314d54450ae965cbd6a036d8b1c9636cf8bc1 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 c6ed078b1c032ea2bc1392b6741d2db9ff6d94ad..a6db86d5f2cb8498929cc866a6bbd930d3231e45 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 7573af31ed7289df96ed8be8cebc68a18f688a9f..aa826d6fb9272efc66e10e5fe39336364400b33d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -72,6 +72,8 @@ virCgroupSetFreezerState; # cpu.h +cpuBaseline; +cpuBaselineXML; cpuCompare; cpuCompareXML; cpuDataFree;