cpu->nfeatures = 0;
for (i = 0; i < modelInfo->nprops; i++) {
- if (VIR_STRDUP(cpu->features[i].name, modelInfo->props[i].name) < 0)
- return -1;
+ virCPUFeatureDefPtr feature = cpu->features + cpu->nfeatures;
+ qemuMonitorCPUPropertyPtr prop = modelInfo->props + i;
- if (modelInfo->props[i].supported)
- cpu->features[i].policy = VIR_CPU_FEATURE_REQUIRE;
- else
- cpu->features[i].policy = VIR_CPU_FEATURE_DISABLE;
+ if (prop->type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN)
+ continue;
+ if (VIR_STRDUP(feature->name, prop->name) < 0)
+ return -1;
+ feature->policy = prop->value.boolean ? VIR_CPU_FEATURE_REQUIRE
+ : VIR_CPU_FEATURE_DISABLE;
cpu->nfeatures++;
}
hostCPU->nprops = n;
for (i = 0; i < n; i++) {
- hostCPU->props[i].name = virXMLPropString(nodes[i], "name");
- if (!hostCPU->props[i].name) {
+ qemuMonitorCPUPropertyPtr prop = hostCPU->props + i;
+ int type;
+
+ ctxt->node = nodes[i];
+
+ if (!(prop->name = virXMLPropString(ctxt->node, "name"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing 'name' attribute for a host CPU"
" model property in QEMU capabilities cache"));
goto cleanup;
}
- if (!(str = virXMLPropString(nodes[i], "value"))) {
+ if (!(str = virXMLPropString(ctxt->node, "type")) ||
+ (type = qemuMonitorCPUPropertyTypeFromString(str)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("missing 'value' attribute for a host CPU"
- " model property in QEMU capabilities cache"));
- goto cleanup;
- }
- if (STREQ(str, "true")) {
- hostCPU->props[i].supported = true;
- } else if (STREQ(str, "false")) {
- hostCPU->props[i].supported = false;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("invalid boolean value: '%s'"), str);
+ _("missing or invalid CPU model property type "
+ "in QEMU capabilities cache"));
goto cleanup;
}
VIR_FREE(str);
+
+ prop->type = type;
+ switch (prop->type) {
+ case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+ if (virXPathBoolean("./@value='true'", ctxt))
+ prop->value.boolean = true;
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_STRING:
+ prop->value.string = virXMLPropString(ctxt->node, "value");
+ if (!prop->value.string) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid string value for '%s' host CPU "
+ "model property in QEMU capabilities cache"),
+ prop->name);
+ goto cleanup;
+ }
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
+ if (virXPathLongLong("string(./@value)", ctxt,
+ &prop->value.number) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid number value for '%s' host CPU "
+ "model property in QEMU capabilities cache"),
+ prop->name);
+ goto cleanup;
+ }
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_LAST:
+ break;
+ }
}
}
virBufferAdjustIndent(buf, 2);
for (i = 0; i < model->nprops; i++) {
- virBufferAsprintf(buf, "<property name='%s' type='boolean' value='%s'/>\n",
- model->props[i].name,
- model->props[i].supported ? "true" : "false");
+ qemuMonitorCPUPropertyPtr prop = model->props + i;
+
+ virBufferAsprintf(buf, "<property name='%s' type='%s' ",
+ prop->name,
+ qemuMonitorCPUPropertyTypeToString(prop->type));
+
+ switch (prop->type) {
+ case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+ virBufferAsprintf(buf, "value='%s'",
+ prop->value.boolean ? "true" : "false");
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_STRING:
+ virBufferEscapeString(buf, "value='%s'", prop->value.string);
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
+ virBufferAsprintf(buf, "value='%lld'", prop->value.number);
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_LAST:
+ break;
+ }
+ virBufferAddLit(buf, "/>\n");
}
virBufferAdjustIndent(buf, -2);
if (!model_info)
return;
- for (i = 0; i < model_info->nprops; i++)
+ for (i = 0; i < model_info->nprops; i++) {
VIR_FREE(model_info->props[i].name);
+ if (model_info->props[i].type == QEMU_MONITOR_CPU_PROPERTY_STRING)
+ VIR_FREE(model_info->props[i].value.string);
+ }
VIR_FREE(model_info->props);
VIR_FREE(model_info->name);
if (VIR_STRDUP(copy->props[i].name, orig->props[i].name) < 0)
goto error;
- copy->props[i].supported = orig->props[i].supported;
+ copy->props[i].type = orig->props[i].type;
+ switch (orig->props[i].type) {
+ case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+ copy->props[i].value.boolean = orig->props[i].value.boolean;
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_STRING:
+ if (VIR_STRDUP(copy->props[i].value.string,
+ orig->props[i].value.string) < 0)
+ goto error;
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
+ copy->props[i].value.number = orig->props[i].value.number;
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_LAST:
+ break;
+ }
}
return copy;
qemuMonitorCPUDefInfoPtr **cpus);
void qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu);
+typedef enum {
+ QEMU_MONITOR_CPU_PROPERTY_BOOLEAN,
+ QEMU_MONITOR_CPU_PROPERTY_STRING,
+ QEMU_MONITOR_CPU_PROPERTY_NUMBER,
+
+ QEMU_MONITOR_CPU_PROPERTY_LAST
+} qemuMonitorCPUPropertyType;
+
+VIR_ENUM_DECL(qemuMonitorCPUProperty)
+
+typedef struct _qemuMonitorCPUProperty qemuMonitorCPUProperty;
+typedef qemuMonitorCPUProperty *qemuMonitorCPUPropertyPtr;
+struct _qemuMonitorCPUProperty {
+ char *name;
+ qemuMonitorCPUPropertyType type;
+ union {
+ bool boolean;
+ char *string;
+ long long number;
+ } value;
+};
+
typedef struct _qemuMonitorCPUModelInfo qemuMonitorCPUModelInfo;
typedef qemuMonitorCPUModelInfo *qemuMonitorCPUModelInfoPtr;
struct _qemuMonitorCPUModelInfo {
char *name;
size_t nprops;
- struct {
- char *name;
- bool supported;
- } *props;
+ qemuMonitorCPUPropertyPtr props;
};
int qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon,
return ret;
}
+
+VIR_ENUM_IMPL(qemuMonitorCPUProperty,
+ QEMU_MONITOR_CPU_PROPERTY_LAST,
+ "boolean", "string", "number")
+
static int
qemuMonitorJSONParseCPUModelProperty(const char *key,
virJSONValue *value,
void *opaque)
{
qemuMonitorCPUModelInfoPtr machine_model = opaque;
- size_t n = machine_model->nprops;
- bool supported;
+ qemuMonitorCPUPropertyPtr prop;
- if (virJSONValueGetBoolean(value, &supported) < 0)
- return 0;
+ prop = machine_model->props + machine_model->nprops;
- if (VIR_STRDUP(machine_model->props[n].name, key) < 0)
- return -1;
+ switch ((virJSONType) value->type) {
+ case VIR_JSON_TYPE_STRING:
+ if (VIR_STRDUP(prop->value.string, virJSONValueGetString(value)) < 0)
+ return -1;
+ prop->type = QEMU_MONITOR_CPU_PROPERTY_STRING;
+ break;
+
+ case VIR_JSON_TYPE_NUMBER:
+ /* Ignore numbers which cannot be parsed as unsigned long long */
+ if (virJSONValueGetNumberLong(value, &prop->value.number) < 0)
+ return 0;
+ prop->type = QEMU_MONITOR_CPU_PROPERTY_NUMBER;
+ break;
- machine_model->props[n].supported = supported;
+ case VIR_JSON_TYPE_BOOLEAN:
+ virJSONValueGetBoolean(value, &prop->value.boolean);
+ prop->type = QEMU_MONITOR_CPU_PROPERTY_BOOLEAN;
+ break;
+
+ case VIR_JSON_TYPE_OBJECT:
+ case VIR_JSON_TYPE_ARRAY:
+ case VIR_JSON_TYPE_NULL:
+ return 0;
+ }
machine_model->nprops++;
+ if (VIR_STRDUP(prop->name, key) < 0)
+ return -1;
+
return 0;
}
<property name='avx512cd' type='boolean' value='false'/>
<property name='decodeassists' type='boolean' value='false'/>
<property name='sse4.1' type='boolean' value='true'/>
+ <property name='family' type='number' value='6'/>
<property name='avx512f' type='boolean' value='false'/>
<property name='msr' type='boolean' value='true'/>
<property name='mce' type='boolean' value='true'/>
<property name='mca' type='boolean' value='true'/>
<property name='xcrypt' type='boolean' value='false'/>
+ <property name='min-level' type='number' value='13'/>
<property name='xgetbv1' type='boolean' value='true'/>
<property name='cid' type='boolean' value='false'/>
<property name='ds' type='boolean' value='false'/>
<property name='xcrypt-en' type='boolean' value='false'/>
<property name='pn' type='boolean' value='false'/>
<property name='dca' type='boolean' value='false'/>
+ <property name='vendor' type='string' value='GenuineIntel'/>
<property name='pku' type='boolean' value='false'/>
<property name='smx' type='boolean' value='false'/>
<property name='cmp-legacy' type='boolean' value='false'/>
<property name='sse4.2' type='boolean' value='true'/>
<property name='pge' type='boolean' value='true'/>
<property name='pdcm' type='boolean' value='false'/>
+ <property name='model' type='number' value='94'/>
<property name='movbe' type='boolean' value='true'/>
<property name='nrip-save' type='boolean' value='false'/>
<property name='ssse3' type='boolean' value='true'/>
<property name='fma' type='boolean' value='true'/>
<property name='cx16' type='boolean' value='true'/>
<property name='de' type='boolean' value='true'/>
+ <property name='stepping' type='number' value='3'/>
<property name='xsave' type='boolean' value='true'/>
<property name='clflush' type='boolean' value='true'/>
<property name='skinit' type='boolean' value='false'/>
<property name='sep' type='boolean' value='true'/>
<property name='nodeid-msr' type='boolean' value='false'/>
<property name='misalignsse' type='boolean' value='false'/>
+ <property name='min-xlevel' type='number' value='2147483656'/>
<property name='bmi1' type='boolean' value='true'/>
<property name='bmi2' type='boolean' value='true'/>
<property name='kvm-pv-unhalt' type='boolean' value='true'/>
<property name='pse36' type='boolean' value='true'/>
<property name='tbm' type='boolean' value='false'/>
<property name='wdt' type='boolean' value='false'/>
+ <property name='model-id' type='string' value='Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz'/>
<property name='sha-ni' type='boolean' value='false'/>
<property name='abm' type='boolean' value='true'/>
<property name='avx512pf' type='boolean' value='false'/>