--- src/cpu/cpu.h | 2 +- src/cpu/cpu_x86.c | 271 ++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 173 insertions(+), 100 deletions(-) diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index cba7149..b2c02db 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -33,7 +33,7 @@ union cpuData { - struct cpuX86Data x86; + struct cpuX86Data *x86; /* generic driver needs no data */ /* PowerPC driver need data*/ struct cpuPPCData ppc; diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index cc7926e..c6e78c5 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -51,7 +51,7 @@ struct x86_vendor { struct x86_feature { char *name; - union cpuData *data; + struct cpuX86Data *data; struct x86_feature *next; }; @@ -59,7 +59,7 @@ struct x86_feature { struct x86_model { char *name; const struct x86_vendor *vendor; - union cpuData *data; + struct cpuX86Data *data; struct x86_model *next; }; @@ -80,7 +80,7 @@ enum compare_result { struct data_iterator { - union cpuData *data; + struct cpuX86Data *data; int pos; bool extended; }; @@ -150,13 +150,11 @@ static struct cpuX86cpuid * x86DataCpuidNext(struct data_iterator *iterator) { struct cpuX86cpuid *ret; - struct cpuX86Data *data; + struct cpuX86Data *data = iterator->data; - if (!iterator->data) + if (!data) return NULL; - data = &iterator->data->x86; - do { ret = NULL; iterator->pos++; @@ -180,7 +178,7 @@ x86DataCpuidNext(struct data_iterator *iterator) static struct cpuX86cpuid * -x86DataCpuid(const union cpuData *data, +x86DataCpuid(const struct cpuX86Data *data, uint32_t function) { struct cpuX86cpuid *cpuids; @@ -188,13 +186,13 @@ x86DataCpuid(const union cpuData *data, size_t i; if (function < CPUX86_EXTENDED) { - cpuids = data->x86.basic; - len = data->x86.basic_len; + cpuids = data->basic; + len = data->basic_len; i = function; } else { - cpuids = data->x86.extended; - len = data->x86.extended_len; + cpuids = data->extended; + len = data->extended_len; i = function - CPUX86_EXTENDED; } @@ -206,65 +204,90 @@ x86DataCpuid(const union cpuData *data, static void -x86DataFree(union cpuData *data) +x86DataFree(struct cpuX86Data *data) { if (data == NULL) return; - VIR_FREE(data->x86.basic); - VIR_FREE(data->x86.extended); + VIR_FREE(data->basic); + VIR_FREE(data->extended); VIR_FREE(data); } static union cpuData * -x86DataCopy(const union cpuData *data) +x86MakeCPUData(struct cpuX86Data **data) +{ + union cpuData *cpuData; + + if (VIR_ALLOC(cpuData) < 0) + return NULL; + + cpuData->x86 = *data; + *data = NULL; + + return cpuData; +} + +static void +x86FreeCPUData(union cpuData *data) +{ + if (!data) + return; + + x86DataFree(data->x86); + VIR_FREE(data); +} + + +static struct cpuX86Data * +x86DataCopy(const struct cpuX86Data *data) { - union cpuData *copy = NULL; + struct cpuX86Data *copy = NULL; size_t i; if (VIR_ALLOC(copy) < 0 - || VIR_ALLOC_N(copy->x86.basic, data->x86.basic_len) < 0 - || VIR_ALLOC_N(copy->x86.extended, data->x86.extended_len) < 0) { + || VIR_ALLOC_N(copy->basic, data->basic_len) < 0 + || VIR_ALLOC_N(copy->extended, data->extended_len) < 0) { x86DataFree(copy); return NULL; } - copy->x86.basic_len = data->x86.basic_len; - for (i = 0; i < data->x86.basic_len; i++) - copy->x86.basic[i] = data->x86.basic[i]; + copy->basic_len = data->basic_len; + for (i = 0; i < data->basic_len; i++) + copy->basic[i] = data->basic[i]; - copy->x86.extended_len = data->x86.extended_len; - for (i = 0; i < data->x86.extended_len; i++) - copy->x86.extended[i] = data->x86.extended[i]; + copy->extended_len = data->extended_len; + for (i = 0; i < data->extended_len; i++) + copy->extended[i] = data->extended[i]; return copy; } static int -x86DataExpand(union cpuData *data, +x86DataExpand(struct cpuX86Data *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) + size_t len = data->basic_len; + if (VIR_EXPAND_N(data->basic, data->basic_len, basic_by) < 0) return -1; for (i = 0; i < basic_by; i++) - data->x86.basic[len + i].function = len + i; + data->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) + size_t len = data->extended_len; + if (VIR_EXPAND_N(data->extended, data->extended_len, extended_by) < 0) return -1; for (i = 0; i < extended_by; i++) - data->x86.extended[len + i].function = len + i + CPUX86_EXTENDED; + data->extended[len + i].function = len + i + CPUX86_EXTENDED; } return 0; @@ -272,7 +295,7 @@ x86DataExpand(union cpuData *data, static int -x86DataAddCpuid(union cpuData *data, +x86DataAddCpuid(struct cpuX86Data *data, const struct cpuX86cpuid *cpuid) { unsigned int basic_by = 0; @@ -282,12 +305,12 @@ x86DataAddCpuid(union cpuData *data, if (cpuid->function < CPUX86_EXTENDED) { pos = cpuid->function; - basic_by = pos + 1 - data->x86.basic_len; - cpuids = &data->x86.basic; + basic_by = pos + 1 - data->basic_len; + cpuids = &data->basic; } else { pos = cpuid->function - CPUX86_EXTENDED; - extended_by = pos + 1 - data->x86.extended_len; - cpuids = &data->x86.extended; + extended_by = pos + 1 - data->extended_len; + cpuids = &data->extended; } if (x86DataExpand(data, basic_by, extended_by) < 0) @@ -300,24 +323,24 @@ x86DataAddCpuid(union cpuData *data, static int -x86DataAdd(union cpuData *data1, - const union cpuData *data2) +x86DataAdd(struct cpuX86Data *data1, + const struct cpuX86Data *data2) { size_t i; if (x86DataExpand(data1, - data2->x86.basic_len - data1->x86.basic_len, - data2->x86.extended_len - data1->x86.extended_len) < 0) + data2->basic_len - data1->basic_len, + data2->extended_len - data1->extended_len) < 0) return -1; - for (i = 0; i < data2->x86.basic_len; i++) { - x86cpuidSetBits(data1->x86.basic + i, - data2->x86.basic + i); + for (i = 0; i < data2->basic_len; i++) { + x86cpuidSetBits(data1->basic + i, + data2->basic + i); } - for (i = 0; i < data2->x86.extended_len; i++) { - x86cpuidSetBits(data1->x86.extended + i, - data2->x86.extended + i); + for (i = 0; i < data2->extended_len; i++) { + x86cpuidSetBits(data1->extended + i, + data2->extended + i); } return 0; @@ -325,29 +348,29 @@ x86DataAdd(union cpuData *data1, static void -x86DataSubtract(union cpuData *data1, - const union cpuData *data2) +x86DataSubtract(struct cpuX86Data *data1, + const struct cpuX86Data *data2) { size_t i; unsigned int len; - len = MIN(data1->x86.basic_len, data2->x86.basic_len); + len = MIN(data1->basic_len, data2->basic_len); for (i = 0; i < len; i++) { - x86cpuidClearBits(data1->x86.basic + i, - data2->x86.basic + i); + x86cpuidClearBits(data1->basic + i, + data2->basic + i); } - len = MIN(data1->x86.extended_len, data2->x86.extended_len); + len = MIN(data1->extended_len, data2->extended_len); for (i = 0; i < len; i++) { - x86cpuidClearBits(data1->x86.extended + i, - data2->x86.extended + i); + x86cpuidClearBits(data1->extended + i, + data2->extended + i); } } static void -x86DataIntersect(union cpuData *data1, - const union cpuData *data2) +x86DataIntersect(struct cpuX86Data *data1, + const struct cpuX86Data *data2) { struct data_iterator iter = DATA_ITERATOR_INIT(data1); struct cpuX86cpuid *cpuid1; @@ -364,7 +387,7 @@ x86DataIntersect(union cpuData *data1, static bool -x86DataIsEmpty(union cpuData *data) +x86DataIsEmpty(struct cpuX86Data *data) { struct data_iterator iter = DATA_ITERATOR_INIT(data); @@ -373,11 +396,11 @@ x86DataIsEmpty(union cpuData *data) static bool -x86DataIsSubset(const union cpuData *data, - const union cpuData *subset) +x86DataIsSubset(const struct cpuX86Data *data, + const struct cpuX86Data *subset) { - struct data_iterator iter = DATA_ITERATOR_INIT((union cpuData *) subset); + struct data_iterator iter = DATA_ITERATOR_INIT((struct cpuX86Data *)subset); const struct cpuX86cpuid *cpuid; const struct cpuX86cpuid *cpuidSubset; @@ -395,7 +418,7 @@ x86DataIsSubset(const union cpuData *data, static int x86DataToCPUFeatures(virCPUDefPtr cpu, int policy, - union cpuData *data, + struct cpuX86Data *data, const struct x86_map *map) { const struct x86_feature *feature = map->features; @@ -415,7 +438,7 @@ x86DataToCPUFeatures(virCPUDefPtr cpu, /* also removes bits corresponding to vendor string from data */ static const struct x86_vendor * -x86DataToVendor(union cpuData *data, +x86DataToVendor(struct cpuX86Data *data, const struct x86_map *map) { const struct x86_vendor *vendor = map->vendors; @@ -435,13 +458,13 @@ x86DataToVendor(union cpuData *data, static virCPUDefPtr -x86DataToCPU(const union cpuData *data, +x86DataToCPU(const struct cpuX86Data *data, const struct x86_model *model, const struct x86_map *map) { virCPUDefPtr cpu; - union cpuData *copy = NULL; - union cpuData *modelData = NULL; + struct cpuX86Data *copy = NULL; + struct cpuX86Data *modelData = NULL; const struct x86_vendor *vendor; if (VIR_ALLOC(cpu) < 0 || @@ -616,7 +639,7 @@ x86FeatureFind(const struct x86_map *map, static char * x86FeatureNames(const struct x86_map *map, const char *separator, - union cpuData *data) + struct cpuX86Data *data) { virBuffer ret = VIR_BUFFER_INITIALIZER; bool first = true; @@ -1103,7 +1126,7 @@ error: /* A helper macro to exit the cpu computation function without writing * redundant code: * MSG: error message - * CPU_DEF: a union cpuData pointer with flags that are conflicting + * CPU_DEF: a struct cpuX86Data pointer with flags that are conflicting * RET: return code to set * * This macro generates the error string outputs it into logs. @@ -1228,6 +1251,8 @@ x86Compute(virCPUDefPtr host, } if (guest != NULL) { + struct cpuX86Data *guestData; + if ((guest_model = x86ModelCopy(host_model)) == NULL) goto error; @@ -1240,8 +1265,11 @@ x86Compute(virCPUDefPtr host, x86DataSubtract(guest_model->data, cpu_disable->data); - if ((*guest = x86DataCopy(guest_model->data)) == NULL) + if (!(guestData = x86DataCopy(guest_model->data)) || + !(*guest = x86MakeCPUData(&guestData))) { + x86DataFree(guestData); goto error; + } } out: @@ -1284,7 +1312,7 @@ x86GuestData(virCPUDefPtr host, static int x86Decode(virCPUDefPtr cpu, - const union cpuData *data, + const struct cpuX86Data *data, const char **models, unsigned int nmodels, const char *preferred) @@ -1383,14 +1411,24 @@ out: return ret; } +static int +x86DecodeCPUData(virCPUDefPtr cpu, + const union cpuData *data, + const char **models, + unsigned int nmodels, + const char *preferred) +{ + return x86Decode(cpu, data->x86, models, nmodels, preferred); +} -static union cpuData * + +static struct cpuX86Data * x86EncodePolicy(const virCPUDefPtr cpu, const struct x86_map *map, enum virCPUFeaturePolicy policy) { struct x86_model *model; - union cpuData *data = NULL; + struct cpuX86Data *data = NULL; if (!(model = x86ModelFromCPU(cpu, map, policy))) return NULL; @@ -1413,14 +1451,27 @@ x86Encode(const virCPUDefPtr cpu, union cpuData **vendor) { struct x86_map *map = NULL; - union cpuData *data_forced = NULL; - union cpuData *data_required = NULL; - union cpuData *data_optional = NULL; - union cpuData *data_disabled = NULL; - union cpuData *data_forbidden = NULL; - union cpuData *data_vendor = NULL; + struct cpuX86Data *data_forced = NULL; + struct cpuX86Data *data_required = NULL; + struct cpuX86Data *data_optional = NULL; + struct cpuX86Data *data_disabled = NULL; + struct cpuX86Data *data_forbidden = NULL; + struct cpuX86Data *data_vendor = NULL; int ret = -1; + if (forced) + *forced = NULL; + if (required) + *required = NULL; + if (optional) + *optional = NULL; + if (disabled) + *disabled = NULL; + if (forbidden) + *forbidden = NULL; + if (vendor) + *vendor = NULL; + if ((map = x86LoadMap()) == NULL) goto error; @@ -1470,18 +1521,24 @@ x86Encode(const virCPUDefPtr cpu, } } - if (forced) - *forced = data_forced; - if (required) - *required = data_required; - if (optional) - *optional = data_optional; - if (disabled) - *disabled = data_disabled; - if (forbidden) - *forbidden = data_forbidden; - if (vendor) - *vendor = data_vendor; + if (forced && + !(*forced = x86MakeCPUData(&data_forced))) + goto error; + if (required && + !(*required = x86MakeCPUData(&data_required))) + goto error; + if (optional && + !(*optional = x86MakeCPUData(&data_optional))) + goto error; + if (disabled && + !(*disabled = x86MakeCPUData(&data_disabled))) + goto error; + if (forbidden && + !(*forbidden = x86MakeCPUData(&data_forbidden))) + goto error; + if (vendor && + !(*vendor = x86MakeCPUData(&data_vendor))) + goto error; ret = 0; @@ -1497,6 +1554,18 @@ error: x86DataFree(data_disabled); x86DataFree(data_forbidden); x86DataFree(data_vendor); + if (forced) + x86FreeCPUData(*forced); + if (required) + x86FreeCPUData(*required); + if (optional) + x86FreeCPUData(*optional); + if (disabled) + x86FreeCPUData(*disabled); + if (forbidden) + x86FreeCPUData(*forbidden); + if (vendor) + x86FreeCPUData(*vendor); goto cleanup; } @@ -1562,21 +1631,25 @@ cpuidSet(uint32_t base, struct cpuX86cpuid **set) static union cpuData * x86NodeData(void) { - union cpuData *data; + union cpuData *cpuData = NULL; + struct cpuX86Data *data; int ret; if (VIR_ALLOC(data) < 0) return NULL; - if ((ret = cpuidSet(CPUX86_BASIC, &data->x86.basic)) < 0) + if ((ret = cpuidSet(CPUX86_BASIC, &data->basic)) < 0) goto error; - data->x86.basic_len = ret; + data->basic_len = ret; - if ((ret = cpuidSet(CPUX86_EXTENDED, &data->x86.extended)) < 0) + if ((ret = cpuidSet(CPUX86_EXTENDED, &data->extended)) < 0) goto error; - data->x86.extended_len = ret; + data->extended_len = ret; - return data; + if (!(cpuData = x86MakeCPUData(&data))) + goto error; + + return cpuData; error: x86DataFree(data); @@ -1812,7 +1885,7 @@ static int x86HasFeature(const union cpuData *data, if (!(feature = x86FeatureFind(map, name))) goto cleanup; - ret = x86DataIsSubset(data, feature->data) ? 1 : 0; + ret = x86DataIsSubset(data->x86, feature->data) ? 1 : 0; cleanup: x86MapFree(map); @@ -1824,9 +1897,9 @@ struct cpuArchDriver cpuDriverX86 = { .arch = archs, .narch = ARRAY_CARDINALITY(archs), .compare = x86Compare, - .decode = x86Decode, + .decode = x86DecodeCPUData, .encode = x86Encode, - .free = x86DataFree, + .free = x86FreeCPUData, #if HAVE_CPUID .nodeData = x86NodeData, #else -- 1.8.3.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list