mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 15:27:47 +00:00
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.
This commit is contained in:
parent
60aef9e467
commit
53c4f9fa1c
@ -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);
|
||||
|
||||
if (x86DataToCPUFeatures(cpu, VIR_CPU_FEATURE_REQUIRE, tmp, map))
|
||||
/* because feature policy is ignored for host CPU */
|
||||
cpu->type = VIR_CPU_TYPE_GUEST;
|
||||
|
||||
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 {
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user