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;
};