#include "logging.h"
#include "memory.h"
+#include "util.h"
#include "cpu.h"
#include "cpu_map.h"
#include "cpu_x86.h"
}
+static void
+x86DataSubtract(union cpuData *data1,
+ const union cpuData *data2)
+{
+ unsigned int i;
+ unsigned int len;
+
+ len = MIN(data1->x86.basic_len, data2->x86.basic_len);
+ for (i = 0; i < len; i++) {
+ x86cpuidClearBits(data1->x86.basic + i,
+ data2->x86.basic + i);
+ }
+
+ len = MIN(data1->x86.extended_len, data2->x86.extended_len);
+ for (i = 0; i < len; i++) {
+ x86cpuidClearBits(data1->x86.extended + i,
+ data2->x86.extended + i);
+ }
+}
+
+
static union cpuData *
x86DataFromModel(const struct x86_model *model)
{
const struct x86_map *map)
{
virCPUDefPtr cpu;
- union cpuData *tmp = NULL;
- unsigned int i;
+ union cpuData *copy = NULL;
+ union cpuData *modelData = NULL;
if (VIR_ALLOC(cpu) < 0 ||
- (cpu->model = strdup(model->name)) == NULL ||
- (tmp = x86DataCopy(data)) == NULL)
+ !(cpu->model = strdup(model->name)) ||
+ !(copy = x86DataCopy(data)) ||
+ !(modelData = x86DataFromModel(model)))
goto no_memory;
- for (i = 0; i < model->ncpuid; i++) {
- x86cpuidClearBits(x86DataCpuid(tmp, model->cpuid[i].function),
- model->cpuid + i);
- }
+ x86DataSubtract(copy, modelData);
+ x86DataSubtract(modelData, data);
+
+ /* because feature policy is ignored for host CPU */
+ cpu->type = VIR_CPU_TYPE_GUEST;
- if (x86DataToCPUFeatures(cpu, VIR_CPU_FEATURE_REQUIRE, tmp, map))
+ if (x86DataToCPUFeatures(cpu, VIR_CPU_FEATURE_REQUIRE, copy, map) ||
+ x86DataToCPUFeatures(cpu, VIR_CPU_FEATURE_DISABLE, modelData, map))
goto error;
cleanup:
- x86DataFree(tmp);
+ x86DataFree(modelData);
+ x86DataFree(copy);
return cpu;
no_memory:
const struct x86_model *candidate;
virCPUDefPtr cpuCandidate;
virCPUDefPtr cpuModel = NULL;
- struct cpuX86cpuid *cpuid;
- int i;
+ unsigned int i;
if (data == NULL || (map = x86LoadMap()) == NULL)
return -1;
while (candidate != NULL) {
bool allowed = (models == NULL);
- for (i = 0; i < candidate->ncpuid; i++) {
- cpuid = x86DataCpuid(data, candidate->cpuid[i].function);
- if (cpuid == NULL
- || !x86cpuidMatchMasked(cpuid, candidate->cpuid + i))
- goto next;
- }
-
for (i = 0; i < nmodels; i++) {
if (models && models[i] && STREQ(models[i], candidate->name)) {
allowed = true;
if (!(cpuCandidate = x86DataToCPU(data, candidate, map)))
goto out;
+ if (cpu->type == VIR_CPU_TYPE_HOST) {
+ cpuCandidate->type = VIR_CPU_TYPE_HOST;
+ for (i = 0; i < cpuCandidate->nfeatures; i++) {
+ switch (cpuCandidate->features[i].policy) {
+ case VIR_CPU_FEATURE_DISABLE:
+ virCPUDefFree(cpuCandidate);
+ goto next;
+ default:
+ cpuCandidate->features[i].policy = -1;
+ }
+ }
+ }
+
if (cpuModel == NULL
|| cpuModel->nfeatures > cpuCandidate->nfeatures) {
virCPUDefFree(cpuModel);
if (VIR_ALLOC(cpu) < 0 ||
!(cpu->arch = strdup(cpus[0]->arch)))
goto no_memory;
+ cpu->type = VIR_CPU_TYPE_GUEST;
+ cpu->match = VIR_CPU_MATCH_EXACT;
for (i = 1; i < ncpus; i++) {
struct x86_model *model;
if (VIR_ALLOC(guest) < 0 || !(guest->arch = strdup(ut->machine)))
goto no_memory;
+ guest->type = VIR_CPU_TYPE_GUEST;
if (cpuDecode(guest, data, cpus, ncpus) < 0)
goto cleanup;
virBufferVSprintf(&buf, "%s", guest->model);
- for (i = 0; i < guest->nfeatures; i++)
- virBufferVSprintf(&buf, ",+%s", guest->features[i].name);
+ for (i = 0; i < guest->nfeatures; i++) {
+ char sign;
+ if (guest->features[i].policy == VIR_CPU_FEATURE_DISABLE)
+ sign = '-';
+ else
+ sign = '+';
+
+ virBufferVSprintf(&buf, ",%c%s", sign, guest->features[i].name);
+ }
}
else {
/*