cpu_x86: Replace 32b signatures in virCPUx86Model with a struct

The CPU models in our cpu_map define their signatures using separate
family and model numbers. Let's store the signatures in the same way in
our runtime representation of the cpu_map.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Jiri Denemark 2020-03-26 16:16:00 +01:00
parent 3b474c1f8f
commit 22bded201f

View File

@ -121,6 +121,19 @@ static virCPUx86Feature x86_kvm_features[] =
KVM_FEATURE(VIR_CPU_x86_HV_STIMER_DIRECT), KVM_FEATURE(VIR_CPU_x86_HV_STIMER_DIRECT),
}; };
typedef struct _virCPUx86Signature virCPUx86Signature;
struct _virCPUx86Signature {
unsigned int family;
unsigned int model;
};
typedef struct _virCPUx86Signatures virCPUx86Signatures;
typedef virCPUx86Signatures *virCPUx86SignaturesPtr;
struct _virCPUx86Signatures {
size_t count;
virCPUx86Signature *items;
};
typedef struct _virCPUx86Model virCPUx86Model; typedef struct _virCPUx86Model virCPUx86Model;
typedef virCPUx86Model *virCPUx86ModelPtr; typedef virCPUx86Model *virCPUx86ModelPtr;
struct _virCPUx86Model { struct _virCPUx86Model {
@ -128,8 +141,7 @@ struct _virCPUx86Model {
bool decodeHost; bool decodeHost;
bool decodeGuest; bool decodeGuest;
virCPUx86VendorPtr vendor; virCPUx86VendorPtr vendor;
size_t nsignatures; virCPUx86SignaturesPtr signatures;
uint32_t *signatures;
virCPUx86Data data; virCPUx86Data data;
}; };
@ -717,6 +729,13 @@ x86MakeSignature(unsigned int family,
} }
static uint32_t
virCPUx86SignatureToCPUID(virCPUx86Signature *sig)
{
return x86MakeSignature(sig->family, sig->model, 0);
}
static void static void
virCPUx86SignatureFromCPUID(uint32_t sig, virCPUx86SignatureFromCPUID(uint32_t sig,
unsigned int *family, unsigned int *family,
@ -1099,41 +1118,65 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
} }
static void static virCPUx86SignaturesPtr
virCPUx86SignaturesFree(uint32_t *signatures) virCPUx86SignaturesNew(size_t count)
{ {
g_free(signatures); virCPUx86SignaturesPtr sigs;
sigs = g_new0(virCPUx86Signatures, 1);
sigs->items = g_new0(virCPUx86Signature, count);
sigs->count = count;
return sigs;
} }
static int static void
virCPUx86SignaturesCopy(virCPUx86ModelPtr dst, virCPUx86SignaturesFree(virCPUx86SignaturesPtr sigs)
virCPUx86ModelPtr src)
{ {
if (!sigs)
return;
g_free(sigs->items);
g_free(sigs);
}
static virCPUx86SignaturesPtr
virCPUx86SignaturesCopy(virCPUx86SignaturesPtr src)
{
virCPUx86SignaturesPtr dst;
size_t i; size_t i;
if (src->nsignatures == 0) if (!src || src->count == 0)
return 0; return NULL;
if (VIR_ALLOC_N(dst->signatures, src->nsignatures) < 0) dst = virCPUx86SignaturesNew(src->count);
return -1;
dst->nsignatures = src->nsignatures; for (i = 0; i < src->count; i++)
for (i = 0; i < src->nsignatures; i++) dst->items[i] = src->items[i];
dst->signatures[i] = src->signatures[i];
return 0; return dst;
} }
static bool static bool
virCPUx86SignaturesMatch(virCPUx86ModelPtr model, virCPUx86SignaturesMatch(virCPUx86SignaturesPtr sigs,
uint32_t signature) uint32_t signature)
{ {
size_t i; size_t i;
unsigned int family;
unsigned int model;
unsigned int stepping;
for (i = 0; i < model->nsignatures; i++) { if (!sigs)
if (model->signatures[i] == signature) return false;
virCPUx86SignatureFromCPUID(signature, &family, &model, &stepping);
for (i = 0; i < sigs->count; i++) {
if (sigs->items[i].family == family &&
sigs->items[i].model == model)
return true; return true;
} }
@ -1142,14 +1185,18 @@ virCPUx86SignaturesMatch(virCPUx86ModelPtr model,
static char * static char *
virCPUx86SignaturesFormat(virCPUx86ModelPtr model) virCPUx86SignaturesFormat(virCPUx86SignaturesPtr sigs)
{ {
virBuffer buf = VIR_BUFFER_INITIALIZER; virBuffer buf = VIR_BUFFER_INITIALIZER;
size_t i; size_t i;
for (i = 0; i < model->nsignatures; i++) { if (!sigs)
virBufferAsprintf(&buf, "%06lx,", return virBufferContentAndReset(&buf);
(unsigned long)model->signatures[i]);
for (i = 0; i < sigs->count; i++) {
virBufferAsprintf(&buf, "(%u,%u,0), ",
sigs->items[i].family,
sigs->items[i].model);
} }
virBufferTrim(&buf, ", "); virBufferTrim(&buf, ", ");
@ -1179,16 +1226,11 @@ x86ModelCopy(virCPUx86ModelPtr model)
copy = g_new0(virCPUx86Model, 1); copy = g_new0(virCPUx86Model, 1);
copy->name = g_strdup(model->name); copy->name = g_strdup(model->name);
copy->signatures = virCPUx86SignaturesCopy(model->signatures);
if (virCPUx86SignaturesCopy(copy, model) < 0) {
x86ModelFree(copy);
return NULL;
}
x86DataCopy(&copy->data, &model->data); x86DataCopy(&copy->data, &model->data);
copy->vendor = model->vendor; copy->vendor = model->vendor;
return copy; return g_steal_pointer(&copy);
} }
@ -1408,9 +1450,7 @@ x86ModelParseAncestor(virCPUx86ModelPtr model,
} }
model->vendor = ancestor->vendor; model->vendor = ancestor->vendor;
if (virCPUx86SignaturesCopy(model, ancestor) < 0) model->signatures = virCPUx86SignaturesCopy(ancestor->signatures);
return -1;
x86DataCopy(&model->data, &ancestor->data); x86DataCopy(&model->data, &ancestor->data);
return 0; return 0;
@ -1432,34 +1472,29 @@ x86ModelParseSignatures(virCPUx86ModelPtr model,
/* Remove inherited signatures. */ /* Remove inherited signatures. */
virCPUx86SignaturesFree(model->signatures); virCPUx86SignaturesFree(model->signatures);
model->nsignatures = n; model->signatures = virCPUx86SignaturesNew(n);
if (VIR_ALLOC_N(model->signatures, n) < 0)
return -1;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
unsigned int sigFamily = 0; virCPUx86Signature *sig = &model->signatures->items[i];
unsigned int sigModel = 0;
int rc; int rc;
ctxt->node = nodes[i]; ctxt->node = nodes[i];
rc = virXPathUInt("string(@family)", ctxt, &sigFamily); rc = virXPathUInt("string(@family)", ctxt, &sig->family);
if (rc < 0 || sigFamily == 0) { if (rc < 0 || sig->family == 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Invalid CPU signature family in model %s"), _("Invalid CPU signature family in model %s"),
model->name); model->name);
return -1; return -1;
} }
rc = virXPathUInt("string(@model)", ctxt, &sigModel); rc = virXPathUInt("string(@model)", ctxt, &sig->model);
if (rc < 0) { if (rc < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Invalid CPU signature model in model %s"), _("Invalid CPU signature model in model %s"),
model->name); model->name);
return -1; return -1;
} }
model->signatures[i] = x86MakeSignature(sigFamily, sigModel, 0);
} }
ctxt->node = root; ctxt->node = root;
@ -1865,9 +1900,12 @@ x86Compute(virCPUDefPtr host,
&host_model->vendor->data) < 0) &host_model->vendor->data) < 0)
return VIR_CPU_COMPARE_ERROR; return VIR_CPU_COMPARE_ERROR;
if (host_model->signatures && if (host_model->signatures && host_model->signatures->count > 0) {
x86DataAddSignature(&guest_model->data, *host_model->signatures) < 0) virCPUx86Signature *sig = &host_model->signatures->items[0];
if (x86DataAddSignature(&guest_model->data,
virCPUx86SignatureToCPUID(sig)) < 0)
return VIR_CPU_COMPARE_ERROR; return VIR_CPU_COMPARE_ERROR;
}
if (cpu->type == VIR_CPU_TYPE_GUEST if (cpu->type == VIR_CPU_TYPE_GUEST
&& cpu->match == VIR_CPU_MATCH_EXACT) && cpu->match == VIR_CPU_MATCH_EXACT)
@ -1977,8 +2015,8 @@ x86DecodeUseCandidate(virCPUx86ModelPtr current,
* consider candidates with matching family/model. * consider candidates with matching family/model.
*/ */
if (signature && if (signature &&
virCPUx86SignaturesMatch(current, signature) && virCPUx86SignaturesMatch(current->signatures, signature) &&
!virCPUx86SignaturesMatch(candidate, signature)) { !virCPUx86SignaturesMatch(candidate->signatures, signature)) {
VIR_DEBUG("%s differs in signature from matching %s", VIR_DEBUG("%s differs in signature from matching %s",
cpuCandidate->model, cpuCurrent->model); cpuCandidate->model, cpuCurrent->model);
return 0; return 0;
@ -1994,8 +2032,8 @@ x86DecodeUseCandidate(virCPUx86ModelPtr current,
* result in longer list of features. * result in longer list of features.
*/ */
if (signature && if (signature &&
virCPUx86SignaturesMatch(candidate, signature) && virCPUx86SignaturesMatch(candidate->signatures, signature) &&
!virCPUx86SignaturesMatch(current, signature)) { !virCPUx86SignaturesMatch(current->signatures, signature)) {
VIR_DEBUG("%s provides matching signature", cpuCandidate->model); VIR_DEBUG("%s provides matching signature", cpuCandidate->model);
return 1; return 1;
} }
@ -2150,7 +2188,7 @@ x86Decode(virCPUDefPtr cpu,
if (vendor) if (vendor)
cpu->vendor = g_strdup(vendor->name); cpu->vendor = g_strdup(vendor->name);
sigs = virCPUx86SignaturesFormat(model); sigs = virCPUx86SignaturesFormat(model->signatures);
VIR_DEBUG("Using CPU model %s (signatures %s) for CPU with signature %06lx", VIR_DEBUG("Using CPU model %s (signatures %s) for CPU with signature %06lx",
model->name, NULLSTR(sigs), (unsigned long)signature); model->name, NULLSTR(sigs), (unsigned long)signature);
@ -3046,9 +3084,12 @@ virCPUx86Translate(virCPUDefPtr cpu,
virCPUx86DataAddItem(&model->data, &model->vendor->data) < 0) virCPUx86DataAddItem(&model->data, &model->vendor->data) < 0)
return -1; return -1;
if (model->signatures && if (model->signatures && model->signatures->count > 0) {
x86DataAddSignature(&model->data, model->signatures[0]) < 0) virCPUx86Signature *sig = &model->signatures->items[0];
if (x86DataAddSignature(&model->data,
virCPUx86SignatureToCPUID(sig)) < 0)
return -1; return -1;
}
if (!(translated = virCPUDefCopyWithoutModel(cpu))) if (!(translated = virCPUDefCopyWithoutModel(cpu)))
return -1; return -1;