diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index bd2beab33eee1951016659c6c171b76f39d16a2f..dc46e7f57a46f224aee103435319e37dfb125e1e 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -112,6 +112,7 @@ virCPUDefFree(virCPUDefPtr def) virCPUDefFreeModel(def); VIR_FREE(def->cache); + VIR_FREE(def->tsc); VIR_FREE(def); } @@ -233,6 +234,13 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu) *copy->cache = *cpu->cache; } + if (cpu->tsc) { + if (VIR_ALLOC(copy->tsc) < 0) + goto error; + + *copy->tsc = *cpu->tsc; + } + return copy; error: @@ -286,6 +294,8 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, char *cpuMode; char *fallback = NULL; char *vendor_id = NULL; + char *tscScaling = NULL; + virHostCPUTscInfoPtr tsc = NULL; int ret = -1; *cpu = NULL; @@ -402,6 +412,32 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, _("invalid microcode version")); goto cleanup; } + + if (virXPathBoolean("boolean(./counter[@name='tsc'])", ctxt) > 0) { + if (VIR_ALLOC(tsc) < 0) + goto cleanup; + + if (virXPathULongLong("./counter[@name='tsc']/@frequency", ctxt, + &tsc->frequency) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Invalid TSC frequency")); + goto cleanup; + } + + tscScaling = virXPathString("string(./counter[@name='tsc']/@scaling)", + ctxt); + if (tscScaling) { + int scaling = virTristateBoolTypeFromString(tscScaling); + if (scaling < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Invalid TSC scaling attribute")); + goto cleanup; + } + tsc->scaling = scaling; + } + + VIR_STEAL_PTR(def->tsc, tsc); + } } if (!(def->model = virXPathString("string(./model[1])", ctxt)) && @@ -587,6 +623,8 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, VIR_FREE(fallback); VIR_FREE(vendor_id); VIR_FREE(nodes); + VIR_FREE(tscScaling); + VIR_FREE(tsc); virCPUDefFree(def); return ret; } @@ -744,6 +782,16 @@ virCPUDefFormatBuf(virBufferPtr buf, virBufferAsprintf(buf, "\n", def->microcodeVersion); + if (def->type == VIR_CPU_TYPE_HOST && def->tsc) { + virBufferAddLit(buf, "tsc->frequency); + if (def->tsc->scaling) { + virBufferAsprintf(buf, " scaling='%s'", + virTristateBoolTypeToString(def->tsc->scaling)); + } + virBufferAddLit(buf, "/>\n"); + } + if (def->sockets && def->cores && def->threads) { virBufferAddLit(buf, "sockets); diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index c98db65693142693125b4d21244de6d6854ed357..51bf744fab145baf2ea6a58f750a7da9eb7f5e16 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -28,6 +28,7 @@ # include "virarch.h" # include "numa_conf.h" # include "virenum.h" +# include "virhostcpu.h" # define VIR_CPU_VENDOR_ID_LENGTH 12 @@ -139,6 +140,7 @@ struct _virCPUDef { size_t nfeatures_max; virCPUFeatureDefPtr features; virCPUCacheDefPtr cache; + virHostCPUTscInfoPtr tsc; };