* The corresponding features are a genuine part of the new model.
*/
GStrv addedFeatures;
+
+ /* Pinter to the model this one was derived from. */
+ virCPUx86Model *ancestor;
+
+ /* Pointer to the canonical model if this model is just an alias.
+ * Because the aliases were actually added to the CPU map before their
+ * canonical models, we store this relation in the XML reversed. That is,
+ * this model contains all the data and the canonical model is defined
+ * using this model as an ancestor without adding any additional data.
+ */
+ const virCPUx86Model *canonical;
};
typedef struct _virCPUx86Map virCPUx86Map;
return -1;
}
+ model->ancestor = ancestor;
model->vendor = ancestor->vendor;
model->signatures = virCPUx86SignaturesCopy(ancestor->signatures);
x86DataCopy(&model->data, &ancestor->data);
}
+/* Updates @changed if signatures are set. */
static int
x86ModelParseSignatures(virCPUx86Model *model,
- xmlXPathContextPtr ctxt)
+ xmlXPathContextPtr ctxt,
+ bool *changed)
{
g_autofree xmlNodePtr *nodes = NULL;
VIR_XPATH_NODE_AUTORESTORE(ctxt)
return -1;
}
+ *changed = true;
return 0;
}
+/* Updates @changed if vendor changes. */
static int
x86ModelParseVendor(virCPUx86Model *model,
xmlXPathContextPtr ctxt,
- virCPUx86Map *map)
+ virCPUx86Map *map,
+ bool *changed)
{
g_autofree char *vendor = NULL;
int rc;
return -1;
}
+ *changed = true;
return 0;
}
+/* Updates @changed if features are added. */
static int
x86ModelParseFeatures(virCPUx86Model *model,
xmlXPathContextPtr ctxt,
- virCPUx86Map *map)
+ virCPUx86Map *map,
+ bool *changed)
{
g_autofree xmlNodePtr *nodes = NULL;
size_t i;
model->removedFeatures = g_renew(char *, model->removedFeatures, nremoved + 1);
model->addedFeatures = g_renew(char *, model->addedFeatures, nadded + 1);
+ *changed = true;
return 0;
}
{
virCPUx86Map *map = data;
g_autoptr(virCPUx86Model) model = NULL;
+ bool changed = false;
if (x86ModelFind(map, name)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
if (x86ModelParseAncestor(model, ctxt, map) < 0)
return -1;
- if (x86ModelParseSignatures(model, ctxt) < 0)
+ if (x86ModelParseSignatures(model, ctxt, &changed) < 0)
return -1;
- if (x86ModelParseVendor(model, ctxt, map) < 0)
+ if (x86ModelParseVendor(model, ctxt, map, &changed) < 0)
return -1;
- if (x86ModelParseFeatures(model, ctxt, map) < 0)
+ if (x86ModelParseFeatures(model, ctxt, map, &changed) < 0)
return -1;
+ if (model->ancestor && !changed) {
+ if (model->ancestor->canonical) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Cannot set CPU model '%1$s' as canonical name of '%2$s' which is already an alias of '%3$s'"),
+ model->name,
+ model->ancestor->name,
+ model->ancestor->canonical->name);
+ return -1;
+ }
+
+ model->ancestor->canonical = model;
+ }
+
VIR_APPEND_ELEMENT(map->models, map->nmodels, model);
return 0;