提交 53c4f9fa 编写于 作者: J Jiri Denemark

Support removing features when converting data to CPU

So far, when CPUID data were converted into CPU model and features, the
features can only be added to the model. As a result, when a guest asked
for something like "qemu64,-svm" it would get a qemu32 plus a bunch of
additional features instead.

This patch adds support for removing feature from the base model.
Selection algorithm remains the same: the best CPU model is the model
which requires lowest number of features to be added/removed from it.
上级 60aef9e4
......@@ -27,6 +27,7 @@
#include "logging.h"
#include "memory.h"
#include "util.h"
#include "cpu.h"
#include "cpu_map.h"
#include "cpu_x86.h"
......@@ -211,6 +212,27 @@ x86DataCopy(const union cpuData *data)
}
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)
{
......@@ -282,24 +304,28 @@ x86DataToCPU(const union cpuData *data,
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:
......@@ -1045,8 +1071,7 @@ x86Decode(virCPUDefPtr cpu,
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;
......@@ -1055,13 +1080,6 @@ x86Decode(virCPUDefPtr cpu,
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;
......@@ -1078,6 +1096,19 @@ x86Decode(virCPUDefPtr cpu,
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);
......@@ -1310,6 +1341,8 @@ x86Baseline(virCPUDefPtr *cpus,
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;
......
......@@ -3309,12 +3309,20 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
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 {
/*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册