diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index cc7d03ccc7..2ab61d73e7 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -647,6 +647,42 @@ virCPUUpdate(virArch arch, } +/** + * virCPUCheckFeature: + * + * @arch: CPU architecture + * @cpu: CPU definition + * @feature: feature to be checked for + * + * Checks whether @feature is supported by the CPU described by @cpu. + * + * Returns 1 if the feature is supported, 0 if it's not supported, or + * -1 on error. + */ +int +virCPUCheckFeature(virArch arch, + const virCPUDef *cpu, + const char *feature) +{ + struct cpuArchDriver *driver; + + VIR_DEBUG("arch=%s, cpu=%p, feature=%s", + virArchToString(arch), cpu, feature); + + if (!(driver = cpuGetSubDriver(arch))) + return -1; + + if (!driver->checkFeature) { + virReportError(VIR_ERR_NO_SUPPORT, + _("cannot check guest CPU feature for %s architecture"), + virArchToString(arch)); + return -1; + } + + return driver->checkFeature(cpu, feature); +} + + /** * virCPUDataCheckFeature: * diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 71fa2dafe5..f14c2c8577 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -90,6 +90,10 @@ typedef int (*virCPUArchUpdate)(virCPUDefPtr guest, const virCPUDef *host); +typedef int +(*virCPUArchCheckFeature)(const virCPUDef *cpu, + const char *feature); + typedef int (*virCPUArchDataCheckFeature)(const virCPUData *data, const char *feature); @@ -120,6 +124,7 @@ struct cpuArchDriver { cpuArchGuestData guestData; cpuArchBaseline baseline; virCPUArchUpdate update; + virCPUArchCheckFeature checkFeature; virCPUArchDataCheckFeature dataCheckFeature; cpuArchDataFormat dataFormat; cpuArchDataParse dataParse; @@ -193,6 +198,14 @@ virCPUUpdate(virArch arch, const virCPUDef *host) ATTRIBUTE_NONNULL(2); + +int +virCPUCheckFeature(virArch arch, + const virCPUDef *cpu, + const char *feature) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + + int virCPUDataCheckFeature(const virCPUData *data, const char *feature) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index ae552ac247..7224d76bcc 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -2601,6 +2601,28 @@ virCPUx86Update(virCPUDefPtr guest, } +static int +virCPUx86CheckFeature(const virCPUDef *cpu, + const char *name) +{ + int ret = -1; + virCPUx86MapPtr map; + virCPUx86ModelPtr model = NULL; + + if (!(map = virCPUx86GetMap())) + return -1; + + if (!(model = x86ModelFromCPU(cpu, map, -1))) + goto cleanup; + + ret = x86FeatureInData(name, &model->data, map); + + cleanup: + x86ModelFree(model); + return ret; +} + + static int virCPUx86DataCheckFeature(const virCPUData *data, const char *name) @@ -2709,6 +2731,7 @@ struct cpuArchDriver cpuDriverX86 = { .guestData = x86GuestData, .baseline = x86Baseline, .update = virCPUx86Update, + .checkFeature = virCPUx86CheckFeature, .dataCheckFeature = virCPUx86DataCheckFeature, .dataFormat = x86CPUDataFormat, .dataParse = x86CPUDataParse, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ab2b693cc9..4825ab7cc4 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -980,6 +980,7 @@ cpuEncode; cpuGetModels; cpuGuestData; cpuNodeData; +virCPUCheckFeature; virCPUDataCheckFeature; virCPUTranslate; virCPUUpdate; diff --git a/tests/cputest.c b/tests/cputest.c index ce8f8c0062..72f00b6254 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -430,7 +430,11 @@ cpuTestHasFeature(const void *arg) NULL, NULL, NULL, NULL) < 0) goto cleanup; - result = virCPUDataCheckFeature(hostData, data->name); + result = virCPUCheckFeature(host->arch, host, data->name); + + if (data->result == result) + result = virCPUDataCheckFeature(hostData, data->name); + if (data->result == -1) virResetLastError();