[libvirt] [PATCH] cpu: Unify CPUID data structures

Jiri Denemark jdenemar at redhat.com
Mon Dec 13 09:06:02 UTC 2010


So far, CPUID data were stored in two different data structures. First
of them was a structure allowing direct access for CPUID data according
to function number and the second was a plain array of struct
cpuX86cpuid. This was a silly design which resulted in converting data
from one type to the other and back again or implementing similar
functionality for both data structures.

The patch leaves only the direct access structure. This makes the code
both smaller and more maintainable since operations on different objects
can use common low-level operations.

All 57 tests for cpu subsystem still pass after this rewrite.
---
 src/cpu/cpu_x86.c      |  576 +++++++++++++++++++++--------------------------
 src/cpu/cpu_x86_data.h |    4 +-
 2 files changed, 259 insertions(+), 321 deletions(-)

diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index 425a8eb..df1e431 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -37,6 +37,7 @@
 
 #define VENDOR_STRING_LENGTH    12
 
+static const struct cpuX86cpuid cpuidNull = { 0, 0, 0, 0, 0 };
 
 static const char *archs[] = { "i686", "x86_64" };
 
@@ -49,8 +50,7 @@ struct x86_vendor {
 
 struct x86_feature {
     char *name;
-    unsigned int ncpuid;
-    struct cpuX86cpuid *cpuid;
+    union cpuData *data;
 
     struct x86_feature *next;
 };
@@ -58,8 +58,7 @@ struct x86_feature {
 struct x86_model {
     char *name;
     const struct x86_vendor *vendor;
-    unsigned int ncpuid;
-    struct cpuX86cpuid *cpuid;
+    union cpuData *data;
 
     struct x86_model *next;
 };
@@ -79,23 +78,28 @@ enum compare_result {
 };
 
 
-static struct cpuX86cpuid *
-x86cpuidFind(struct cpuX86cpuid *cpuids,
-             unsigned int ncpuids,
-             uint32_t function)
-{
-    unsigned int i;
+struct data_iterator {
+    union cpuData *data;
+    int pos;
+    bool extended;
+};
 
-    for (i = 0; i < ncpuids; i++) {
-        if (cpuids[i].function == function)
-            return cpuids + i;
-    }
 
-    return NULL;
+#define DATA_ITERATOR_INIT(data) \
+    { data, -1, false }
+
+
+static void
+x86DataIteratorInit(struct data_iterator *iter,
+                    union cpuData *data)
+{
+    struct data_iterator init = DATA_ITERATOR_INIT(data);
+
+    *iter = init;
 }
 
 
-static inline int
+static int
 x86cpuidMatch(const struct cpuX86cpuid *cpuid1,
               const struct cpuX86cpuid *cpuid2)
 {
@@ -106,7 +110,7 @@ x86cpuidMatch(const struct cpuX86cpuid *cpuid1,
 }
 
 
-static inline int
+static int
 x86cpuidMatchMasked(const struct cpuX86cpuid *cpuid,
                     const struct cpuX86cpuid *mask)
 {
@@ -117,7 +121,7 @@ x86cpuidMatchMasked(const struct cpuX86cpuid *cpuid,
 }
 
 
-static inline int
+static int
 x86cpuidMatchAny(const struct cpuX86cpuid *cpuid,
                  const struct cpuX86cpuid *mask)
 {
@@ -128,7 +132,7 @@ x86cpuidMatchAny(const struct cpuX86cpuid *cpuid,
 }
 
 
-static inline void
+static void
 x86cpuidSetBits(struct cpuX86cpuid *cpuid,
                 const struct cpuX86cpuid *mask)
 {
@@ -139,7 +143,7 @@ x86cpuidSetBits(struct cpuX86cpuid *cpuid,
 }
 
 
-static inline void
+static void
 x86cpuidClearBits(struct cpuX86cpuid *cpuid,
                   const struct cpuX86cpuid *mask)
 {
@@ -150,7 +154,7 @@ x86cpuidClearBits(struct cpuX86cpuid *cpuid,
 }
 
 
-static inline void
+static void
 x86cpuidAndBits(struct cpuX86cpuid *cpuid,
                 const struct cpuX86cpuid *mask)
 {
@@ -161,6 +165,40 @@ x86cpuidAndBits(struct cpuX86cpuid *cpuid,
 }
 
 
+/* skips all zero CPUID leafs */
+static struct cpuX86cpuid *
+x86DataCpuidNext(struct data_iterator *iterator)
+{
+    struct cpuX86cpuid *ret;
+    struct cpuX86Data *data;
+
+    if (!iterator->data)
+        return NULL;
+
+    data = &iterator->data->x86;
+
+    do {
+        ret = NULL;
+        iterator->pos++;
+
+        if (!iterator->extended) {
+            if (iterator->pos < data->basic_len)
+                ret = data->basic + iterator->pos;
+            else {
+                iterator->extended = true;
+                iterator->pos = 0;
+            }
+        }
+
+        if (iterator->extended && iterator->pos < data->extended_len) {
+            ret = data->extended + iterator->pos;
+        }
+    } while (ret && x86cpuidMatch(ret, &cpuidNull));
+
+    return ret;
+}
+
+
 static struct cpuX86cpuid *
 x86DataCpuid(const union cpuData *data,
              uint32_t function)
@@ -180,7 +218,7 @@ x86DataCpuid(const union cpuData *data,
         i = function - CPUX86_EXTENDED;
     }
 
-    if (i < len)
+    if (i < len && !x86cpuidMatch(cpuids + i, &cpuidNull))
         return cpuids + i;
     else
         return NULL;
@@ -225,38 +263,86 @@ x86DataCopy(const union cpuData *data)
 
 
 static int
+x86DataExpand(union cpuData *data,
+              int basic_by,
+              int extended_by)
+{
+    size_t i;
+
+    if (basic_by > 0) {
+        size_t len = data->x86.basic_len;
+        if (VIR_EXPAND_N(data->x86.basic, data->x86.basic_len, basic_by) < 0)
+            goto no_memory;
+
+        for (i = 0; i < basic_by; i++)
+            data->x86.basic[len + i].function = len + i;
+    }
+
+    if (extended_by > 0) {
+        size_t len = data->x86.extended_len;
+        if (VIR_EXPAND_N(data->x86.extended, data->x86.extended_len, extended_by) < 0)
+            goto no_memory;
+
+        for (i = 0; i < extended_by; i++)
+            data->x86.extended[len + i].function = len + i + CPUX86_EXTENDED;
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError();
+    return -1;
+}
+
+
+static int
 x86DataAddCpuid(union cpuData *data,
                 const struct cpuX86cpuid *cpuid)
 {
+    unsigned int basic_by = 0;
+    unsigned int extended_by = 0;
     struct cpuX86cpuid **cpuids;
-    int *len;
     unsigned int pos;
-    unsigned int ext;
 
     if (cpuid->function < CPUX86_EXTENDED) {
         pos = cpuid->function;
-        ext = 0;
-        len = &data->x86.basic_len;
+        basic_by = pos + 1 - data->x86.basic_len;
         cpuids = &data->x86.basic;
     } else {
         pos = cpuid->function - CPUX86_EXTENDED;
-        ext = CPUX86_EXTENDED;
-        len = &data->x86.extended_len;
+        extended_by = pos + 1 - data->x86.extended_len;
         cpuids = &data->x86.extended;
     }
 
-    if (pos >= *len) {
-        unsigned int i;
+    if (x86DataExpand(data, basic_by, extended_by) < 0)
+        return -1;
+
+    x86cpuidSetBits((*cpuids) + pos, cpuid);
 
-        if (VIR_ALLOC_N(*cpuids, pos + 1) < 0)
-            return -1;
+    return 0;
+}
+
+
+static int
+x86DataAdd(union cpuData *data1,
+           const union cpuData *data2)
+{
+    unsigned int i;
+
+    if (x86DataExpand(data1,
+                      data2->x86.basic_len - data1->x86.basic_len,
+                      data2->x86.extended_len - data1->x86.extended_len) < 0)
+        return -1;
 
-        for (i = *len; i <= pos; i++)
-            (*cpuids)[i].function = i + ext;
-        *len = pos + 1;
+    for (i = 0; i < data2->x86.basic_len; i++) {
+        x86cpuidSetBits(data1->x86.basic + i,
+                        data2->x86.basic + i);
     }
 
-    x86cpuidSetBits((*cpuids) + pos, cpuid);
+    for (i = 0; i < data2->x86.extended_len; i++) {
+        x86cpuidSetBits(data1->x86.extended + i,
+                        data2->x86.extended + i);
+    }
 
     return 0;
 }
@@ -283,61 +369,49 @@ x86DataSubtract(union cpuData *data1,
 }
 
 
-static bool
-x86DataIsEmpty(union cpuData *data)
+static void
+x86DataIntersect(union cpuData *data1,
+                 const union cpuData *data2)
 {
-    struct cpuX86cpuid zero = { 0, 0, 0, 0, 0 };
-    unsigned int i;
-
-    for (i = 0; i < data->x86.basic_len; i++) {
-        if (!x86cpuidMatch(data->x86.basic + i, &zero))
-            return false;
-    }
+    struct data_iterator iter = DATA_ITERATOR_INIT(data1);
+    struct cpuX86cpuid *cpuid1;
+    struct cpuX86cpuid *cpuid2;
 
-    for (i = 0; i < data->x86.extended_len; i++) {
-        if (!x86cpuidMatch(data->x86.extended + i, &zero))
-            return false;
+    while ((cpuid1 = x86DataCpuidNext(&iter))) {
+        cpuid2 = x86DataCpuid(data2, cpuid1->function);
+        if (cpuid2)
+            x86cpuidAndBits(cpuid1, cpuid2);
+        else
+            x86cpuidClearBits(cpuid1, cpuid1);
     }
-
-    return true;
 }
 
 
-static union cpuData *
-x86DataFromModel(const struct x86_model *model)
+static bool
+x86DataIsEmpty(union cpuData *data)
 {
-    union cpuData *data = NULL;
-    uint32_t basic_len = 0;
-    uint32_t extended_len = 0;
-    struct cpuX86cpuid *cpuid;
-    int i;
+    struct data_iterator iter = DATA_ITERATOR_INIT(data);
 
-    for (i = 0; i < model->ncpuid; i++) {
-        cpuid = model->cpuid + i;
-        if (cpuid->function < CPUX86_EXTENDED) {
-            if (cpuid->function >= basic_len)
-                basic_len = cpuid->function + 1;
-        }
-        else if (cpuid->function - CPUX86_EXTENDED >= extended_len)
-            extended_len = cpuid->function - CPUX86_EXTENDED + 1;
-    }
+    return (x86DataCpuidNext(&iter) == NULL);
+}
 
-    if (VIR_ALLOC(data) < 0
-        || VIR_ALLOC_N(data->x86.basic, basic_len) < 0
-        || VIR_ALLOC_N(data->x86.extended, extended_len) < 0) {
-        x86DataFree(data);
-        return NULL;
-    }
 
-    data->x86.basic_len = basic_len;
-    data->x86.extended_len = extended_len;
+static bool
+x86DataIsSubset(const union cpuData *data,
+                const union cpuData *subset)
+{
+
+    struct data_iterator iter = DATA_ITERATOR_INIT((union cpuData *) subset);
+    const struct cpuX86cpuid *cpuid;
+    const struct cpuX86cpuid *cpuidSubset;
 
-    for (i = 0; i < model->ncpuid; i++) {
-        cpuid = x86DataCpuid(data, model->cpuid[i].function);
-        *cpuid = model->cpuid[i];
+    while ((cpuidSubset = x86DataCpuidNext(&iter))) {
+        if (!(cpuid = x86DataCpuid(data, cpuidSubset->function)) ||
+            !x86cpuidMatchMasked(cpuid, cpuidSubset))
+            return false;
     }
 
-    return data;
+    return true;
 }
 
 
@@ -349,17 +423,12 @@ x86DataToCPUFeatures(virCPUDefPtr cpu,
                      const struct x86_map *map)
 {
     const struct x86_feature *feature = map->features;
-    struct cpuX86cpuid *cpuid;
-    unsigned int i;
 
     while (feature != NULL) {
-        for (i = 0; i < feature->ncpuid; i++) {
-            if ((cpuid = x86DataCpuid(data, feature->cpuid[i].function))
-                && x86cpuidMatchMasked(cpuid, feature->cpuid + i)) {
-                x86cpuidClearBits(cpuid, feature->cpuid + i);
-                if (virCPUDefAddFeature(cpu, feature->name, policy) < 0)
-                    return -1;
-            }
+        if (x86DataIsSubset(data, feature->data)) {
+            x86DataSubtract(data, feature->data);
+            if (virCPUDefAddFeature(cpu, feature->name, policy) < 0)
+                return -1;
         }
         feature = feature->next;
     }
@@ -402,7 +471,7 @@ x86DataToCPU(const union cpuData *data,
     if (VIR_ALLOC(cpu) < 0 ||
         !(cpu->model = strdup(model->name)) ||
         !(copy = x86DataCopy(data)) ||
-        !(modelData = x86DataFromModel(model)))
+        !(modelData = x86DataCopy(model->data)))
         goto no_memory;
 
     if ((vendor = x86DataToVendor(copy, map)) &&
@@ -441,7 +510,7 @@ x86VendorFree(struct x86_vendor *vendor)
 
     VIR_FREE(vendor->name);
     VIR_FREE(vendor);
-};
+}
 
 
 static struct x86_vendor *
@@ -533,6 +602,23 @@ ignore:
 }
 
 
+static struct x86_feature *
+x86FeatureNew(void)
+{
+    struct x86_feature *feature;
+
+    if (VIR_ALLOC(feature) < 0)
+        return NULL;
+
+    if (VIR_ALLOC(feature->data) < 0) {
+        VIR_FREE(feature);
+        return NULL;
+    }
+
+    return feature;
+}
+
+
 static void
 x86FeatureFree(struct x86_feature *feature)
 {
@@ -540,7 +626,7 @@ x86FeatureFree(struct x86_feature *feature)
         return;
 
     VIR_FREE(feature->name);
-    VIR_FREE(feature->cpuid);
+    x86DataFree(feature->data);
     VIR_FREE(feature);
 }
 
@@ -569,12 +655,12 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
 {
     xmlNodePtr *nodes = NULL;
     xmlNodePtr ctxt_node = ctxt->node;
-    struct x86_feature *feature = NULL;
+    struct x86_feature *feature;
     int ret = 0;
     int i;
     int n;
 
-    if (VIR_ALLOC(feature) < 0)
+    if (!(feature = x86FeatureNew()))
         goto no_memory;
 
     feature->name = virXPathString("string(@name)", ctxt);
@@ -594,14 +680,8 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
     if (n < 0)
         goto ignore;
 
-    if (n > 0) {
-        if (VIR_ALLOC_N(feature->cpuid, n) < 0)
-            goto no_memory;
-        feature->ncpuid = n;
-    }
-
     for (i = 0; i < n; i++) {
-        struct cpuX86cpuid *cpuid = feature->cpuid + i;
+        struct cpuX86cpuid cpuid;
         unsigned long fun, eax, ebx, ecx, edx;
         int ret_fun, ret_eax, ret_ebx, ret_ecx, ret_edx;
 
@@ -620,11 +700,14 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
             goto ignore;
         }
 
-        cpuid->function =  fun;
-        cpuid->eax =  eax;
-        cpuid->ebx =  ebx;
-        cpuid->ecx =  ecx;
-        cpuid->edx =  edx;
+        cpuid.function = fun;
+        cpuid.eax = eax;
+        cpuid.ebx = ebx;
+        cpuid.ecx = ecx;
+        cpuid.edx = edx;
+
+        if (x86DataAddCpuid(feature->data, &cpuid))
+            goto no_memory;
     }
 
     if (map->features == NULL)
@@ -650,6 +733,23 @@ ignore:
 }
 
 
+static struct x86_model *
+x86ModelNew(void)
+{
+    struct x86_model *model;
+
+    if (VIR_ALLOC(model) < 0)
+        return NULL;
+
+    if (VIR_ALLOC(model->data) < 0) {
+        VIR_FREE(model);
+        return NULL;
+    }
+
+    return model;
+}
+
+
 static void
 x86ModelFree(struct x86_model *model)
 {
@@ -657,7 +757,7 @@ x86ModelFree(struct x86_model *model)
         return;
 
     VIR_FREE(model->name);
-    VIR_FREE(model->cpuid);
+    x86DataFree(model->data);
     VIR_FREE(model);
 }
 
@@ -666,99 +766,20 @@ static struct x86_model *
 x86ModelCopy(const struct x86_model *model)
 {
     struct x86_model *copy;
-    int i;
 
     if (VIR_ALLOC(copy) < 0
-        || (copy->name = strdup(model->name)) == NULL
-        || VIR_ALLOC_N(copy->cpuid, model->ncpuid) < 0) {
+        || !(copy->name = strdup(model->name))
+        || !(copy->data = x86DataCopy(model->data))) {
         x86ModelFree(copy);
         return NULL;
     }
 
     copy->vendor = model->vendor;
-    copy->ncpuid = model->ncpuid;
-    for (i = 0; i < model->ncpuid; i++)
-        copy->cpuid[i] = model->cpuid[i];
 
     return copy;
 }
 
 
-static int
-x86ModelAddCpuid(struct x86_model *model,
-                 const struct cpuX86cpuid *cpuid)
-{
-    struct cpuX86cpuid *model_cpuid;
-
-    model_cpuid = x86cpuidFind(model->cpuid, model->ncpuid, cpuid->function);
-
-    if (model_cpuid != NULL)
-        x86cpuidSetBits(model_cpuid, cpuid);
-    else {
-        if (VIR_REALLOC_N(model->cpuid, model->ncpuid + 1) < 0)
-            return -1;
-
-        model->cpuid[model->ncpuid] = *cpuid;
-        model->ncpuid++;
-    }
-
-    return 0;
-}
-
-
-static void
-x86ModelSubtract(struct x86_model *model1,
-                 const struct x86_model *model2)
-{
-    int i;
-    struct cpuX86cpuid *cpuid;
-
-    for (i = 0; i < model2->ncpuid; i++) {
-        cpuid = x86cpuidFind(model1->cpuid,
-                             model1->ncpuid,
-                             model2->cpuid[i].function);
-        if (cpuid != NULL)
-            x86cpuidClearBits(cpuid, model2->cpuid + i);
-    }
-}
-
-
-static void
-x86ModelIntersect(struct x86_model *model1,
-                  const struct x86_model *model2)
-{
-    int i;
-    struct cpuX86cpuid *cpuid;
-
-    for (i = 0; i < model1->ncpuid; i++) {
-        struct cpuX86cpuid *intersection = model1->cpuid + i;
-
-        cpuid = x86cpuidFind(model2->cpuid,
-                             model2->ncpuid,
-                             intersection->function);
-        if (cpuid != NULL)
-            x86cpuidAndBits(intersection, cpuid);
-        else
-            x86cpuidClearBits(intersection, intersection);
-    }
-}
-
-
-static int
-x86ModelAdd(struct x86_model *model1,
-            const struct x86_model *model2)
-{
-    int i;
-
-    for (i = 0; i < model2->ncpuid; i++) {
-        if (x86ModelAddCpuid(model1, model2->cpuid + i))
-            return -1;
-    }
-
-    return 0;
-}
-
-
 static struct x86_model *
 x86ModelFind(const struct x86_map *map,
              const char *name)
@@ -777,47 +798,6 @@ x86ModelFind(const struct x86_map *map,
 }
 
 
-static int
-x86ModelMergeFeature(struct x86_model *model,
-                     const struct x86_feature *feature)
-{
-    int i;
-
-    if (feature == NULL)
-        return 0;
-
-    for (i = 0; i < feature->ncpuid; i++) {
-        if (x86ModelAddCpuid(model, feature->cpuid + i))
-            return -1;
-    }
-
-    return 0;
-}
-
-
-static bool
-x86ModelHasFeature(struct x86_model *model,
-                   const struct x86_feature *feature)
-{
-    unsigned int i;
-    struct cpuX86cpuid *cpuid;
-    struct cpuX86cpuid *model_cpuid;
-
-    if (feature == NULL)
-        return false;
-
-    for (i = 0; i < feature->ncpuid; i++) {
-        cpuid = feature->cpuid + i;
-        model_cpuid = x86cpuidFind(model->cpuid, model->ncpuid,
-                                   cpuid->function);
-        if (!model_cpuid || !x86cpuidMatchMasked(model_cpuid, cpuid))
-            return false;
-    }
-
-    return true;
-}
-
-
 static struct x86_model *
 x86ModelFromCPU(const virCPUDefPtr cpu,
                 const struct x86_map *map,
@@ -835,11 +815,11 @@ x86ModelFromCPU(const virCPUDefPtr cpu,
 
         if ((model = x86ModelCopy(model)) == NULL)
             goto no_memory;
-    }
-    else if (VIR_ALLOC(model) < 0)
+    } else if (!(model = x86ModelNew())) {
         goto no_memory;
-    else if (cpu->type == VIR_CPU_TYPE_HOST)
+    } else if (cpu->type == VIR_CPU_TYPE_HOST) {
         return model;
+    }
 
     for (i = 0; i < cpu->nfeatures; i++) {
         const struct x86_feature *feature;
@@ -854,7 +834,7 @@ x86ModelFromCPU(const virCPUDefPtr cpu,
             goto error;
         }
 
-        if (x86ModelMergeFeature(model, feature))
+        if (x86DataAdd(model->data, feature->data))
             goto no_memory;
     }
 
@@ -884,11 +864,10 @@ x86ModelSubtractCPU(struct x86_model *model,
         return -1;
     }
 
-    x86ModelSubtract(model, cpu_model);
+    x86DataSubtract(model->data, cpu_model->data);
 
     for (i = 0; i < cpu->nfeatures; i++) {
         const struct x86_feature *feature;
-        unsigned int j;
 
         if (!(feature = x86FeatureFind(map, cpu->features[i].name))) {
             virCPUReportError(VIR_ERR_INTERNAL_ERROR,
@@ -897,13 +876,7 @@ x86ModelSubtractCPU(struct x86_model *model,
             return -1;
         }
 
-        for (j = 0; j < feature->ncpuid; j++) {
-            struct cpuX86cpuid *cpuid;
-            cpuid = x86cpuidFind(model->cpuid, model->ncpuid,
-                                 feature->cpuid[j].function);
-            if (cpuid)
-                x86cpuidClearBits(cpuid, feature->cpuid + j);
-        }
+        x86DataSubtract(model->data, feature->data);
     }
 
     return 0;
@@ -915,18 +888,15 @@ x86ModelCompare(const struct x86_model *model1,
                 const struct x86_model *model2)
 {
     enum compare_result result = EQUAL;
+    struct data_iterator iter1 = DATA_ITERATOR_INIT(model1->data);
+    struct data_iterator iter2 = DATA_ITERATOR_INIT(model2->data);
     struct cpuX86cpuid *cpuid1;
     struct cpuX86cpuid *cpuid2;
-    int i;
 
-    for (i = 0; i < model1->ncpuid; i++) {
+    while ((cpuid1 = x86DataCpuidNext(&iter1))) {
         enum compare_result match = SUPERSET;
 
-        cpuid1 = model1->cpuid + i;
-        cpuid2 = x86cpuidFind(model2->cpuid,
-                              model2->ncpuid,
-                              cpuid1->function);
-        if (cpuid2 != NULL) {
+        if ((cpuid2 = x86DataCpuid(model2->data, cpuid1->function))) {
             if (x86cpuidMatch(cpuid1, cpuid2))
                 continue;
             else if (!x86cpuidMatchMasked(cpuid1, cpuid2))
@@ -939,14 +909,10 @@ x86ModelCompare(const struct x86_model *model1,
             return UNRELATED;
     }
 
-    for (i = 0; i < model2->ncpuid; i++) {
+    while ((cpuid2 = x86DataCpuidNext(&iter2))) {
         enum compare_result match = SUBSET;
 
-        cpuid2 = model2->cpuid + i;
-        cpuid1 = x86cpuidFind(model1->cpuid,
-                              model1->ncpuid,
-                              cpuid2->function);
-        if (cpuid1 != NULL) {
+        if ((cpuid1 = x86DataCpuid(model1->data, cpuid2->function))) {
             if (x86cpuidMatch(cpuid2, cpuid1))
                 continue;
             else if (!x86cpuidMatchMasked(cpuid2, cpuid1))
@@ -968,13 +934,13 @@ x86ModelLoad(xmlXPathContextPtr ctxt,
              struct x86_map *map)
 {
     xmlNodePtr *nodes = NULL;
-    struct x86_model *model = NULL;
+    struct x86_model *model;
     char *vendor = NULL;
     int ret = 0;
     int i;
     int n;
 
-    if (VIR_ALLOC(model) < 0)
+    if (!(model = x86ModelNew()))
         goto no_memory;
 
     model->name = virXPathString("string(@name)", ctxt);
@@ -1006,13 +972,9 @@ x86ModelLoad(xmlXPathContextPtr ctxt,
 
         VIR_FREE(name);
 
-        if (VIR_ALLOC_N(model->cpuid, ancestor->ncpuid) < 0)
-            goto no_memory;
-
         model->vendor = ancestor->vendor;
-        model->ncpuid = ancestor->ncpuid;
-        memcpy(model->cpuid, ancestor->cpuid,
-               sizeof(*model->cpuid) * model->ncpuid);
+        if (!(model->data = x86DataCopy(ancestor->data)))
+            goto no_memory;
     }
 
     if (virXPathBoolean("boolean(./vendor)", ctxt)) {
@@ -1055,7 +1017,7 @@ x86ModelLoad(xmlXPathContextPtr ctxt,
         }
         VIR_FREE(name);
 
-        if (x86ModelMergeFeature(model, feature))
+        if (x86DataAdd(model->data, feature->data))
             goto no_memory;
     }
 
@@ -1157,7 +1119,6 @@ x86Compute(virCPUDefPtr host,
            virCPUDefPtr cpu,
            union cpuData **guest)
 {
-    struct cpuX86cpuid cpuid_zero = { 0, 0, 0, 0, 0 };
     struct x86_map *map = NULL;
     struct x86_model *host_model = NULL;
     struct x86_model *cpu_force = NULL;
@@ -1167,6 +1128,8 @@ x86Compute(virCPUDefPtr host,
     struct x86_model *cpu_forbid = NULL;
     struct x86_model *diff = NULL;
     struct x86_model *guest_model = NULL;
+    struct data_iterator iter;
+    const struct cpuX86cpuid *cpuid;
     virCPUCompareResult ret;
     enum compare_result result;
     unsigned int i;
@@ -1203,24 +1166,20 @@ x86Compute(virCPUDefPtr host,
         !(cpu_forbid = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_FORBID)))
         goto error;
 
-    for (i = 0; i < cpu_forbid->ncpuid; i++) {
-        const struct cpuX86cpuid *cpuid1;
+    x86DataIteratorInit(&iter, cpu_forbid->data);
+    while ((cpuid = x86DataCpuidNext(&iter))) {
         const struct cpuX86cpuid *cpuid2;
 
-        cpuid1 = cpu_forbid->cpuid + i;
-        cpuid2 = x86cpuidFind(host_model->cpuid,
-                              host_model->ncpuid,
-                              cpuid1->function);
-
-        if (cpuid2 != NULL && x86cpuidMatchAny(cpuid2, cpuid1)) {
+        cpuid2 = x86DataCpuid(host_model->data, cpuid->function);
+        if (cpuid2 != NULL && x86cpuidMatchAny(cpuid2, cpuid)) {
             VIR_DEBUG("Host CPU provides forbidden features in CPUID function 0x%x",
-                      cpuid1->function);
+                      cpuid->function);
             ret = VIR_CPU_COMPARE_INCOMPATIBLE;
             goto out;
         }
     }
 
-    x86ModelSubtract(cpu_require, cpu_disable);
+    x86DataSubtract(cpu_require->data, cpu_disable->data);
     result = x86ModelCompare(host_model, cpu_require);
     if (result == SUBSET || result == UNRELATED) {
         VIR_DEBUG0("Host CPU does not provide all required features");
@@ -1233,17 +1192,13 @@ x86Compute(virCPUDefPtr host,
     if ((diff = x86ModelCopy(host_model)) == NULL)
         goto no_memory;
 
-    x86ModelSubtract(diff, cpu_optional);
-    x86ModelSubtract(diff, cpu_require);
-    x86ModelSubtract(diff, cpu_disable);
-    x86ModelSubtract(diff, cpu_force);
+    x86DataSubtract(diff->data, cpu_optional->data);
+    x86DataSubtract(diff->data, cpu_require->data);
+    x86DataSubtract(diff->data, cpu_disable->data);
+    x86DataSubtract(diff->data, cpu_force->data);
 
-    for (i = 0; i < diff->ncpuid; i++) {
-        if (!x86cpuidMatch(diff->cpuid + i, &cpuid_zero)) {
-            ret = VIR_CPU_COMPARE_SUPERSET;
-            break;
-        }
-    }
+    if (!x86DataIsEmpty(diff->data))
+        ret = VIR_CPU_COMPARE_SUPERSET;
 
     if (ret == VIR_CPU_COMPARE_SUPERSET
         && cpu->type == VIR_CPU_TYPE_GUEST
@@ -1259,14 +1214,14 @@ x86Compute(virCPUDefPtr host,
 
         if (cpu->type == VIR_CPU_TYPE_GUEST
             && cpu->match == VIR_CPU_MATCH_EXACT)
-            x86ModelSubtract(guest_model, diff);
+            x86DataSubtract(guest_model->data, diff->data);
 
-        if (x86ModelAdd(guest_model, cpu_force))
+        if (x86DataAdd(guest_model->data, cpu_force->data))
             goto no_memory;
 
-        x86ModelSubtract(guest_model, cpu_disable);
+        x86DataSubtract(guest_model->data, cpu_disable->data);
 
-        if ((*guest = x86DataFromModel(guest_model)) == NULL)
+        if ((*guest = x86DataCopy(guest_model->data)) == NULL)
             goto no_memory;
     }
 
@@ -1418,9 +1373,8 @@ x86EncodePolicy(const virCPUDefPtr cpu,
     if (!(model = x86ModelFromCPU(cpu, map, policy)))
         return NULL;
 
-    if (!(data = x86DataFromModel(model)))
-        virReportOOMError();
-
+    data = model->data;
+    model->data = NULL;
     x86ModelFree(model);
 
     return data;
@@ -1584,19 +1538,20 @@ static union cpuData *
 x86NodeData(void)
 {
     union cpuData *data;
+    int ret;
 
     if (VIR_ALLOC(data) < 0) {
         virReportOOMError();
         return NULL;
     }
 
-    data->x86.basic_len = cpuidSet(CPUX86_BASIC, &data->x86.basic);
-    if (data->x86.basic_len < 0)
+    if ((ret = cpuidSet(CPUX86_BASIC, &data->x86.basic)) < 0)
         goto error;
+    data->x86.basic_len = ret;
 
-    data->x86.extended_len = cpuidSet(CPUX86_EXTENDED, &data->x86.extended);
-    if (data->x86.extended_len < 0)
+    if ((ret = cpuidSet(CPUX86_EXTENDED, &data->x86.extended)) < 0)
         goto error;
+    data->x86.extended_len = ret;
 
     return data;
 
@@ -1616,7 +1571,6 @@ x86Baseline(virCPUDefPtr *cpus,
 {
     struct x86_map *map = NULL;
     struct x86_model *base_model = NULL;
-    union cpuData *data = NULL;
     virCPUDefPtr cpu = NULL;
     unsigned int i;
     const struct x86_vendor *vendor = NULL;
@@ -1679,24 +1633,21 @@ x86Baseline(virCPUDefPtr *cpus,
             }
         }
 
-        x86ModelIntersect(base_model, model);
+        x86DataIntersect(base_model->data, model->data);
         x86ModelFree(model);
         model = NULL;
     }
 
-    if (!(data = x86DataFromModel(base_model)))
-        goto no_memory;
-
-    if (x86DataIsEmpty(data)) {
+    if (x86DataIsEmpty(base_model->data)) {
         virCPUReportError(VIR_ERR_OPERATION_FAILED,
                 "%s", _("CPUs are incompatible"));
         goto error;
     }
 
-    if (vendor && x86DataAddCpuid(data, &vendor->cpuid) < 0)
+    if (vendor && x86DataAddCpuid(base_model->data, &vendor->cpuid) < 0)
         goto no_memory;
 
-    if (x86Decode(cpu, data, models, nmodels, NULL) < 0)
+    if (x86Decode(cpu, base_model->data, models, nmodels, NULL) < 0)
         goto error;
 
     if (!outputVendor)
@@ -1705,7 +1656,6 @@ x86Baseline(virCPUDefPtr *cpus,
     VIR_FREE(cpu->arch);
 
 cleanup:
-    x86DataFree(data);
     x86ModelFree(base_model);
     x86MapFree(map);
 
@@ -1729,7 +1679,6 @@ x86Update(virCPUDefPtr guest,
     unsigned int i;
     struct x86_map *map;
     struct x86_model *host_model = NULL;
-    union cpuData *data = NULL;
 
     if (!(map = x86LoadMap()) ||
         !(host_model = x86ModelFromCPU(host, map, VIR_CPU_FEATURE_REQUIRE)))
@@ -1745,7 +1694,7 @@ x86Update(virCPUDefPtr guest,
                 goto cleanup;
             }
 
-            if (x86ModelHasFeature(host_model, feature))
+            if (x86DataIsSubset(host_model->data, feature->data))
                 guest->features[i].policy = VIR_CPU_FEATURE_REQUIRE;
             else
                 guest->features[i].policy = VIR_CPU_FEATURE_DISABLE;
@@ -1755,8 +1704,8 @@ x86Update(virCPUDefPtr guest,
     if (guest->match == VIR_CPU_MATCH_MINIMUM) {
         guest->match = VIR_CPU_MATCH_EXACT;
         if (x86ModelSubtractCPU(host_model, guest, map)
-            || !(data = x86DataFromModel(host_model))
-            || x86DataToCPUFeatures(guest, VIR_CPU_FEATURE_REQUIRE, data, map))
+            || x86DataToCPUFeatures(guest, VIR_CPU_FEATURE_REQUIRE,
+                                    host_model->data, map))
             goto cleanup;
     }
 
@@ -1765,7 +1714,6 @@ x86Update(virCPUDefPtr guest,
 cleanup:
     x86MapFree(map);
     x86ModelFree(host_model);
-    x86DataFree(data);
     return ret;
 }
 
@@ -1775,7 +1723,6 @@ static int x86HasFeature(const union cpuData *data,
     struct x86_map *map;
     struct x86_feature *feature;
     int ret = -1;
-    int i;
 
     if (!(map = x86LoadMap()))
         return -1;
@@ -1783,16 +1730,7 @@ static int x86HasFeature(const union cpuData *data,
     if (!(feature = x86FeatureFind(map, name)))
         goto cleanup;
 
-    for (i = 0 ; i < feature->ncpuid ; i++) {
-        struct cpuX86cpuid *cpuid;
-
-        cpuid = x86DataCpuid(data, feature->cpuid[i].function);
-        if (cpuid && x86cpuidMatchMasked(cpuid, feature->cpuid + i)) {
-            ret = 1;
-            goto cleanup;
-        }
-    }
-    ret = 0;
+    ret = x86DataIsSubset(data, feature->data) ? 1 : 0;
 
 cleanup:
     x86MapFree(map);
diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
index 46d2517..34a5b06 100644
--- a/src/cpu/cpu_x86_data.h
+++ b/src/cpu/cpu_x86_data.h
@@ -38,9 +38,9 @@ struct cpuX86cpuid {
 # define CPUX86_EXTENDED 0x80000000
 
 struct cpuX86Data {
-    int basic_len;
+    size_t basic_len;
     struct cpuX86cpuid *basic;
-    int extended_len;
+    size_t extended_len;
     struct cpuX86cpuid *extended;
 };
 
-- 
1.7.3.3




More information about the libvir-list mailing list