[libvirt PATCH 0/5] Add virCPUDataIsIdentical

A function to compare two `virCPUData` objects. This is a prerequisite for a later series, that will add the host's cpuid information to the cpu flag cache as per [1], to solve BZ 1953389 [2]. [1] https://listman.redhat.com/archives/libvir-list/2021-August/msg00293.html [2] https://bugzilla.redhat.com/show_bug.cgi?id=1953389 Tim Wiederhake (5): cpu_arm: No need to protect macro definitions cpu: Add virCPUDataIsIdentical cpu_x86: Implement virCPUDataIsIdentical for x86 cpu_arm: Implement virCPUDataIsIdentical for arm cpu_ppc64: Implement virCPUDataIsIdentical for ppc64 src/cpu/cpu.c | 29 +++++++++++++++++ src/cpu/cpu.h | 9 ++++++ src/cpu/cpu_arm.c | 34 +++++++++++++++++--- src/cpu/cpu_ppc64.c | 26 +++++++++++++++ src/cpu/cpu_x86.c | 69 ++++++++++++++++++++++++++++++++++++++++ src/libvirt_private.syms | 1 + 6 files changed, 164 insertions(+), 4 deletions(-) -- 2.31.1

Signed-off-by: Tim Wiederhake <twiederh@redhat.com> --- src/cpu/cpu_arm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c index 09ade1d422..ac174891b7 100644 --- a/src/cpu/cpu_arm.c +++ b/src/cpu/cpu_arm.c @@ -39,12 +39,11 @@ #include "virxml.h" #define VIR_FROM_THIS VIR_FROM_CPU -#if defined(__aarch64__) + /* Shift bit mask for parsing cpu flags */ -# define BIT_SHIFTS(n) (1UL << (n)) +#define BIT_SHIFTS(n) (1UL << (n)) /* The current max number of cpu flags on ARM is 32 */ -# define MAX_CPU_FLAGS 32 -#endif +#define MAX_CPU_FLAGS 32 VIR_LOG_INIT("cpu.cpu_arm"); -- 2.31.1

Signed-off-by: Tim Wiederhake <twiederh@redhat.com> --- src/cpu/cpu.c | 29 +++++++++++++++++++++++++++++ src/cpu/cpu.h | 9 +++++++++ src/libvirt_private.syms | 1 + 3 files changed, 39 insertions(+) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index b4965f3ee0..a3531dd665 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1128,6 +1128,35 @@ virCPUDataAddFeature(virCPUData *cpuData, } +/** + * virCPUDataIsIdentical: + * + * Returns VIR_CPU_COMPARE_IDENTICAL if @a and @b are identical, + * VIR_CPU_COMPARE_INCOMPATIBLE if @a and @b are not identical, or + * VIR_CPU_COMPARE_ERROR on error. + */ +virCPUCompareResult +virCPUDataIsIdentical(const virCPUData *a, + const virCPUData *b) +{ + struct cpuArchDriver *driver; + + VIR_DEBUG("a=%p, b=%p", a, b); + + if (!a || !b) + return VIR_CPU_COMPARE_ERROR; + + if (!(driver = cpuGetSubDriver(a->arch))) + return VIR_CPU_COMPARE_ERROR; + + if (!driver->dataIsIdentical) { + return VIR_CPU_COMPARE_ERROR; + } + + return driver->dataIsIdentical(a, b); +} + + /** * virCPUArchIsSupported: * diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index d11d2641fc..e752126813 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -123,6 +123,10 @@ typedef int (*virCPUArchDataAddFeature)(virCPUData *cpuData, const char *name); +typedef virCPUCompareResult +(*virCPUArchDataIsIdentical)(const virCPUData *a, + const virCPUData *b); + struct cpuArchDriver { const char *name; const virArch *arch; @@ -146,6 +150,7 @@ struct cpuArchDriver { virCPUArchCopyMigratable copyMigratable; virCPUArchValidateFeatures validateFeatures; virCPUArchDataAddFeature dataAddFeature; + virCPUArchDataIsIdentical dataIsIdentical; }; @@ -275,6 +280,10 @@ int virCPUDataAddFeature(virCPUData *cpuData, const char *name); +virCPUCompareResult +virCPUDataIsIdentical(const virCPUData *a, + const virCPUData *b); + bool virCPUArchIsSupported(virArch arch); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fd0eea0777..b63165f354 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1459,6 +1459,7 @@ virCPUDataAddFeature; virCPUDataCheckFeature; virCPUDataFormat; virCPUDataFree; +virCPUDataIsIdentical; virCPUDataNew; virCPUDataParse; virCPUExpandFeatures; -- 2.31.1

Signed-off-by: Tim Wiederhake <twiederh@redhat.com> --- src/cpu/cpu_x86.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 1b829e5658..55da407ec4 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -3369,6 +3369,74 @@ virCPUx86DataAddFeature(virCPUData *cpuData, } +static bool +virCPUx86DataItemIsIdentical(const virCPUx86DataItem *a, + const virCPUx86DataItem *b) +{ + if (a->type != b->type) + return false; + + switch (a->type) { + case VIR_CPU_X86_DATA_NONE: + break; + + case VIR_CPU_X86_DATA_CPUID: + return a->data.cpuid.eax_in == b->data.cpuid.eax_in && + a->data.cpuid.ecx_in == b->data.cpuid.ecx_in && + a->data.cpuid.eax == b->data.cpuid.eax && + a->data.cpuid.ebx == b->data.cpuid.ebx && + a->data.cpuid.ecx == b->data.cpuid.ecx && + a->data.cpuid.edx == b->data.cpuid.edx; + + case VIR_CPU_X86_DATA_MSR: + return a->data.msr.index == b->data.msr.index && + a->data.msr.eax == b->data.msr.eax && + a->data.msr.edx == b->data.msr.edx; + } + + return true; +} + +static virCPUCompareResult +virCPUx86DataIsIdentical(const virCPUData *a, + const virCPUData *b) +{ + const virCPUx86Data *adata; + const virCPUx86Data *bdata; + size_t i; + size_t j; + + if (!a || !b) + return VIR_CPU_COMPARE_ERROR; + + if (a->arch != b->arch) + return VIR_CPU_COMPARE_INCOMPATIBLE; + + if (!((adata = &a->data.x86) && (bdata = &b->data.x86))) + return VIR_CPU_COMPARE_ERROR; + + if (adata->len != bdata->len) + return VIR_CPU_COMPARE_INCOMPATIBLE; + + for (i = 0; i < adata->len; ++i) { + bool found = false; + + for (j = 0; j < bdata->len; ++j) { + if (!virCPUx86DataItemIsIdentical(&adata->items[i], + &bdata->items[j])) + continue; + + found = true; + break; + } + + if (!found) + return VIR_CPU_COMPARE_INCOMPATIBLE; + } + + return VIR_CPU_COMPARE_IDENTICAL; +} + static bool virCPUx86FeatureIsMSR(const char *name) { @@ -3452,4 +3520,5 @@ struct cpuArchDriver cpuDriverX86 = { .copyMigratable = virCPUx86CopyMigratable, .validateFeatures = virCPUx86ValidateFeatures, .dataAddFeature = virCPUx86DataAddFeature, + .dataIsIdentical = virCPUx86DataIsIdentical, }; -- 2.31.1

Signed-off-by: Tim Wiederhake <twiederh@redhat.com> --- src/cpu/cpu_arm.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c index ac174891b7..c9114d53bf 100644 --- a/src/cpu/cpu_arm.c +++ b/src/cpu/cpu_arm.c @@ -124,6 +124,32 @@ virCPUarmDataClear(virCPUarmData *data) g_strfreev(data->features); } +static virCPUCompareResult +virCPUarmDataIsIdentical(const virCPUData *a, + const virCPUData *b) +{ + size_t i; + + if (!a || !b) + return VIR_CPU_COMPARE_ERROR; + + if (a->arch != b->arch) + return VIR_CPU_COMPARE_INCOMPATIBLE; + + if (a->data.arm.pvr != b->data.arm.pvr) + return VIR_CPU_COMPARE_INCOMPATIBLE; + + if (a->data.arm.vendor_id != b->data.arm.vendor_id) + return VIR_CPU_COMPARE_INCOMPATIBLE; + + for (i = 0; i < MAX_CPU_FLAGS; ++i) { + if (STRNEQ(a->data.arm.features[i], b->data.arm.features[i])) + return VIR_CPU_COMPARE_INCOMPATIBLE; + } + + return VIR_CPU_COMPARE_IDENTICAL; +} + static void virCPUarmDataFree(virCPUData *cpuData) { @@ -674,4 +700,5 @@ struct cpuArchDriver cpuDriverArm = { .baseline = virCPUarmBaseline, .update = virCPUarmUpdate, .validateFeatures = virCPUarmValidateFeatures, + .dataIsIdentical = virCPUarmDataIsIdentical, }; -- 2.31.1

Signed-off-by: Tim Wiederhake <twiederh@redhat.com> --- src/cpu/cpu_ppc64.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c index 4909f61ff1..fcd68c8a7c 100644 --- a/src/cpu/cpu_ppc64.c +++ b/src/cpu/cpu_ppc64.c @@ -578,6 +578,31 @@ ppc64DriverDecode(virCPUDef *cpu, return 0; } +static virCPUCompareResult +virCPUppc64DataIsIdentical(const virCPUData *a, + const virCPUData *b) +{ + size_t i; + + if (!a || !b) + return VIR_CPU_COMPARE_ERROR; + + if (a->arch != b->arch) + return VIR_CPU_COMPARE_INCOMPATIBLE; + + if (a->data.ppc64.len != b->data.ppc64.len) + return VIR_CPU_COMPARE_INCOMPATIBLE; + + for (i = 0; i < a->data.ppc64.len; ++i) { + if (a->data.ppc64.pvr[i].mask != b->data.ppc64.pvr[i].mask) + return VIR_CPU_COMPARE_INCOMPATIBLE; + if (a->data.ppc64.pvr[i].value != b->data.ppc64.pvr[i].value) + return VIR_CPU_COMPARE_INCOMPATIBLE; + } + + return VIR_CPU_COMPARE_IDENTICAL; +} + static void virCPUppc64DataFree(virCPUData *data) { @@ -749,4 +774,5 @@ struct cpuArchDriver cpuDriverPPC64 = { .update = virCPUppc64Update, .getModels = virCPUppc64DriverGetModels, .convertLegacy = virCPUppc64ConvertLegacy, + .dataIsIdentical = virCPUppc64DataIsIdentical, }; -- 2.31.1
participants (1)
-
Tim Wiederhake