cpu: Run arch specific code for virCPUUpdate for all custom CPUs

Until now, the function returned immediately when the guest CPU
definition did not use optional features or minimum match. Clearly,
there's nothing to be updated according to the host CPU in this case,
but the arch specific code may still want to do some compatibility
updates based on the model and features used in the guest CPU
definition.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Tim Wiederhake <twiederh@redhat.com>
This commit is contained in:
Jiri Denemark 2020-11-19 21:35:41 +01:00
parent d7756a67bb
commit 8a04e76610
6 changed files with 46 additions and 29 deletions

View File

@ -538,12 +538,11 @@ virCPUBaseline(virArch arch,
* @guest: guest CPU definition to be updated
* @host: host CPU definition
*
* Updates @guest CPU definition according to @host CPU. This is required to
* support guest CPU definitions specified relatively to host CPU, such as
* CPUs with VIR_CPU_MODE_CUSTOM and optional features or
* VIR_CPU_MATCH_MINIMUM, or CPUs with VIR_CPU_MODE_HOST_MODEL.
* When the guest CPU was not specified relatively, the function does nothing
* and returns success.
* Updates @guest CPU definition possibly taking @host CPU into account. This
* is required for maintaining compatibility with older libvirt releases or to
* support guest CPU definitions specified relatively to host CPU, such as CPUs
* with VIR_CPU_MODE_CUSTOM and optional features or VIR_CPU_MATCH_MINIMUM, or
* CPUs with VIR_CPU_MODE_HOST_MODEL.
*
* Returns 0 on success, -1 on error.
*/
@ -553,6 +552,7 @@ virCPUUpdate(virArch arch,
const virCPUDef *host)
{
struct cpuArchDriver *driver;
bool relative;
VIR_DEBUG("arch=%s, guest=%p mode=%s model=%s, host=%p model=%s",
virArchToString(arch), guest, virCPUModeTypeToString(guest->mode),
@ -561,30 +561,36 @@ virCPUUpdate(virArch arch,
if (!(driver = cpuGetSubDriver(arch)))
return -1;
if (guest->mode == VIR_CPU_MODE_HOST_PASSTHROUGH)
switch ((virCPUMode) guest->mode) {
case VIR_CPU_MODE_HOST_PASSTHROUGH:
return 0;
if (guest->mode == VIR_CPU_MODE_CUSTOM &&
guest->match != VIR_CPU_MATCH_MINIMUM) {
size_t i;
bool optional = false;
case VIR_CPU_MODE_HOST_MODEL:
relative = true;
break;
for (i = 0; i < guest->nfeatures; i++) {
if (guest->features[i].policy == VIR_CPU_FEATURE_OPTIONAL) {
optional = true;
break;
case VIR_CPU_MODE_CUSTOM:
if (guest->match == VIR_CPU_MATCH_MINIMUM) {
relative = true;
} else {
size_t i;
relative = false;
for (i = 0; i < guest->nfeatures; i++) {
if (guest->features[i].policy == VIR_CPU_FEATURE_OPTIONAL) {
relative = true;
break;
}
}
}
break;
if (!optional)
return 0;
case VIR_CPU_MODE_LAST:
default:
virReportEnumRangeError(virCPUMode, guest->mode);
return -1;
}
/* We get here if guest CPU is either
* - host-model
* - custom with minimum match
* - custom with optional features
*/
if (!driver->update) {
virReportError(VIR_ERR_NO_SUPPORT,
_("cannot update guest CPU for %s architecture"),
@ -592,7 +598,7 @@ virCPUUpdate(virArch arch,
return -1;
}
if (driver->update(guest, host) < 0)
if (driver->update(guest, host, relative) < 0)
return -1;
VIR_DEBUG("model=%s", NULLSTR(guest->model));

View File

@ -79,7 +79,8 @@ typedef virCPUDefPtr
typedef int
(*virCPUArchUpdate)(virCPUDefPtr guest,
const virCPUDef *host);
const virCPUDef *host,
bool relative);
typedef int
(*virCPUArchUpdateLive)(virCPUDefPtr cpu,

View File

@ -415,11 +415,12 @@ virCPUarmGetMap(void)
static int
virCPUarmUpdate(virCPUDefPtr guest,
const virCPUDef *host)
const virCPUDef *host,
bool relative)
{
g_autoptr(virCPUDef) updated = NULL;
if (guest->mode != VIR_CPU_MODE_HOST_MODEL)
if (!relative || guest->mode != VIR_CPU_MODE_HOST_MODEL)
return 0;
if (!host) {

View File

@ -614,7 +614,8 @@ virCPUppc64GetHost(virCPUDefPtr cpu,
static int
virCPUppc64Update(virCPUDefPtr guest,
const virCPUDef *host G_GNUC_UNUSED)
const virCPUDef *host G_GNUC_UNUSED,
bool relative G_GNUC_UNUSED)
{
/*
* - host-passthrough doesn't even get here

View File

@ -43,11 +43,15 @@ virCPUs390Compare(virCPUDefPtr host G_GNUC_UNUSED,
static int
virCPUs390Update(virCPUDefPtr guest,
const virCPUDef *host)
const virCPUDef *host,
bool relative)
{
g_autoptr(virCPUDef) updated = NULL;
size_t i;
if (!relative)
return 0;
if (guest->mode == VIR_CPU_MODE_CUSTOM) {
if (guest->match == VIR_CPU_MATCH_MINIMUM) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,

View File

@ -2936,12 +2936,16 @@ x86UpdateHostModel(virCPUDefPtr guest,
static int
virCPUx86Update(virCPUDefPtr guest,
const virCPUDef *host)
const virCPUDef *host,
bool relative)
{
g_autoptr(virCPUx86Model) model = NULL;
virCPUx86MapPtr map;
size_t i;
if (!relative)
return 0;
if (!host) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("unknown host CPU model"));