mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
cpuUpdate() for updating guest CPU according to host CPU
Useful mainly for migration. cpuUpdate changes guest CPU requirements in the following way: - match == "strict" || match == "exact" - optional features which are supported by host CPU are changed into required features - optional features which are not supported by host CPU are disabled - all other features remain untouched - match == "minimum" - match is changed into "exact" - optional features and all features not mentioned in guest CPU specification which are supported by host CPU become required features - other optional features are disabled - all other features remain untouched This ensures that no feature will suddenly disappear from the guest after migration.
This commit is contained in:
parent
5982168290
commit
661ae104c2
@ -403,3 +403,25 @@ cpuBaseline(virCPUDefPtr *cpus,
|
|||||||
|
|
||||||
return cpu;
|
return cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
cpuUpdate(virCPUDefPtr guest,
|
||||||
|
const virCPUDefPtr host)
|
||||||
|
{
|
||||||
|
struct cpuArchDriver *driver;
|
||||||
|
|
||||||
|
VIR_DEBUG("guest=%p, host=%p", guest, host);
|
||||||
|
|
||||||
|
if ((driver = cpuGetSubDriver(host->arch)) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (driver->update == NULL) {
|
||||||
|
virCPUReportError(VIR_ERR_NO_SUPPORT,
|
||||||
|
_("cannot update guest CPU data for %s architecture"),
|
||||||
|
host->arch);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return driver->update(guest, host);
|
||||||
|
}
|
||||||
|
@ -76,6 +76,10 @@ typedef virCPUDefPtr
|
|||||||
const char **models,
|
const char **models,
|
||||||
unsigned int nmodels);
|
unsigned int nmodels);
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(*cpuArchUpdate) (virCPUDefPtr guest,
|
||||||
|
const virCPUDefPtr host);
|
||||||
|
|
||||||
|
|
||||||
struct cpuArchDriver {
|
struct cpuArchDriver {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -88,6 +92,7 @@ struct cpuArchDriver {
|
|||||||
cpuArchNodeData nodeData;
|
cpuArchNodeData nodeData;
|
||||||
cpuArchGuestData guestData;
|
cpuArchGuestData guestData;
|
||||||
cpuArchBaseline baseline;
|
cpuArchBaseline baseline;
|
||||||
|
cpuArchUpdate update;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -138,4 +143,8 @@ cpuBaseline (virCPUDefPtr *cpus,
|
|||||||
const char **models,
|
const char **models,
|
||||||
unsigned int nmodels);
|
unsigned int nmodels);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
cpuUpdate (virCPUDefPtr guest,
|
||||||
|
const virCPUDefPtr host);
|
||||||
|
|
||||||
#endif /* __VIR_CPU_H__ */
|
#endif /* __VIR_CPU_H__ */
|
||||||
|
@ -219,4 +219,5 @@ struct cpuArchDriver cpuDriverGeneric = {
|
|||||||
.nodeData = NULL,
|
.nodeData = NULL,
|
||||||
.guestData = NULL,
|
.guestData = NULL,
|
||||||
.baseline = genericBaseline,
|
.baseline = genericBaseline,
|
||||||
|
.update = NULL,
|
||||||
};
|
};
|
||||||
|
@ -249,6 +249,33 @@ x86DataFromModel(const struct x86_model *model)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* also removes all detected features from data */
|
||||||
|
static int
|
||||||
|
x86DataToCPUFeatures(virCPUDefPtr cpu,
|
||||||
|
int policy,
|
||||||
|
union cpuData *data,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
feature = feature->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static virCPUDefPtr
|
static virCPUDefPtr
|
||||||
x86DataToCPU(const union cpuData *data,
|
x86DataToCPU(const union cpuData *data,
|
||||||
const struct x86_model *model,
|
const struct x86_model *model,
|
||||||
@ -256,9 +283,7 @@ x86DataToCPU(const union cpuData *data,
|
|||||||
{
|
{
|
||||||
virCPUDefPtr cpu;
|
virCPUDefPtr cpu;
|
||||||
union cpuData *tmp = NULL;
|
union cpuData *tmp = NULL;
|
||||||
struct cpuX86cpuid *cpuid;
|
unsigned int i;
|
||||||
const struct x86_feature *feature;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (VIR_ALLOC(cpu) < 0 ||
|
if (VIR_ALLOC(cpu) < 0 ||
|
||||||
(cpu->model = strdup(model->name)) == NULL ||
|
(cpu->model = strdup(model->name)) == NULL ||
|
||||||
@ -270,20 +295,8 @@ x86DataToCPU(const union cpuData *data,
|
|||||||
model->cpuid + i);
|
model->cpuid + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
feature = map->features;
|
if (x86DataToCPUFeatures(cpu, VIR_CPU_FEATURE_REQUIRE, tmp, map))
|
||||||
while (feature != NULL) {
|
|
||||||
for (i = 0; i < feature->ncpuid; i++) {
|
|
||||||
if ((cpuid = x86DataCpuid(tmp, feature->cpuid[i].function))
|
|
||||||
&& x86cpuidMatchMasked(cpuid, feature->cpuid + i)) {
|
|
||||||
x86cpuidClearBits(cpuid, feature->cpuid + i);
|
|
||||||
if (virCPUDefAddFeature(cpu, feature->name,
|
|
||||||
VIR_CPU_FEATURE_REQUIRE) < 0)
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
feature = feature->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
x86DataFree(tmp);
|
x86DataFree(tmp);
|
||||||
@ -560,6 +573,29 @@ x86ModelMergeFeature(struct x86_model *model,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 (!x86cpuidMatchMasked(model_cpuid, cpuid))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct x86_model *
|
static struct x86_model *
|
||||||
x86ModelFromCPU(const virCPUDefPtr cpu,
|
x86ModelFromCPU(const virCPUDefPtr cpu,
|
||||||
const struct x86_map *map,
|
const struct x86_map *map,
|
||||||
@ -610,6 +646,47 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
x86ModelSubtractCPU(struct x86_model *model,
|
||||||
|
const virCPUDefPtr cpu,
|
||||||
|
const struct x86_map *map)
|
||||||
|
{
|
||||||
|
const struct x86_model *cpu_model;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!(cpu_model = x86ModelFind(map, cpu->model))) {
|
||||||
|
virCPUReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Unknown CPU model %s"),
|
||||||
|
cpu->model);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
x86ModelSubtract(model, cpu_model);
|
||||||
|
|
||||||
|
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,
|
||||||
|
_("Unknown CPU feature %s"),
|
||||||
|
cpu->features[i].name);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static enum compare_result
|
static enum compare_result
|
||||||
x86ModelCompare(const struct x86_model *model1,
|
x86ModelCompare(const struct x86_model *model1,
|
||||||
const struct x86_model *model2)
|
const struct x86_model *model2)
|
||||||
@ -1277,6 +1354,55 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
x86Update(virCPUDefPtr guest,
|
||||||
|
const virCPUDefPtr host)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
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, 0)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < guest->nfeatures; i++) {
|
||||||
|
if (guest->features[i].policy == VIR_CPU_FEATURE_OPTIONAL) {
|
||||||
|
const struct x86_feature *feature;
|
||||||
|
if (!(feature = x86FeatureFind(map, guest->features[i].name))) {
|
||||||
|
virCPUReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Unknown CPU feature %s"),
|
||||||
|
guest->features[i].name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x86ModelHasFeature(host_model, feature))
|
||||||
|
guest->features[i].policy = VIR_CPU_FEATURE_REQUIRE;
|
||||||
|
else
|
||||||
|
guest->features[i].policy = VIR_CPU_FEATURE_DISABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
x86MapFree(map);
|
||||||
|
x86ModelFree(host_model);
|
||||||
|
x86DataFree(data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct cpuArchDriver cpuDriverX86 = {
|
struct cpuArchDriver cpuDriverX86 = {
|
||||||
.name = "x86",
|
.name = "x86",
|
||||||
.arch = archs,
|
.arch = archs,
|
||||||
@ -1292,4 +1418,5 @@ struct cpuArchDriver cpuDriverX86 = {
|
|||||||
#endif
|
#endif
|
||||||
.guestData = x86GuestData,
|
.guestData = x86GuestData,
|
||||||
.baseline = x86Baseline,
|
.baseline = x86Baseline,
|
||||||
|
.update = x86Update,
|
||||||
};
|
};
|
||||||
|
@ -81,6 +81,7 @@ cpuDecode;
|
|||||||
cpuEncode;
|
cpuEncode;
|
||||||
cpuGuestData;
|
cpuGuestData;
|
||||||
cpuNodeData;
|
cpuNodeData;
|
||||||
|
cpuUpdate;
|
||||||
|
|
||||||
|
|
||||||
# cpu_conf.h
|
# cpu_conf.h
|
||||||
|
Loading…
x
Reference in New Issue
Block a user