Add a new internal qemuCPUModelCompatResult enum to qemu_process.h
with values for IDENTICAL, SUBSET, SUPERSET, INCOMPATIBLE, and ERROR,
and a new shared helper qemuProcessCPUModelComparison() in
qemu_process.c that wraps the QMP probe and maps the result string to
the enum.

Refactor qemuConnectCPUModelComparison() in qemu_driver.c to delegate
to the new helper, eliminating the duplicated QMP probe boilerplate.
qemuConnectCPUModelComparison() maps the internal enum back to
virCPUCompareResult, treating SUBSET as VIR_CPU_COMPARE_INCOMPATIBLE
to preserve existing public API behaviour.

Signed-off-by: Rorie Reyes <[email protected]>
---
 src/qemu/qemu_driver.c  | 20 +++++++----------
 src/qemu/qemu_process.c | 50 +++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_process.h | 21 +++++++++++++++++
 3 files changed, 79 insertions(+), 12 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 7332ec0256..56a254f0ec 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12127,25 +12127,21 @@ qemuConnectCPUModelComparison(virQEMUCaps *qemuCaps,
                               virCPUDef *cpu_b,
                               bool failIncompatible)
 {
-    g_autoptr(qemuProcessQMP) proc = NULL;
-    g_autofree char *result = NULL;
-
-    if (!(proc = qemuProcessQMPNew(virQEMUCapsGetBinary(qemuCaps),
-                                   libDir, runUid, runGid, false)))
-        return VIR_CPU_COMPARE_ERROR;
-
-    if (qemuProcessQMPStart(proc) < 0)
-        return VIR_CPU_COMPARE_ERROR;
+    qemuCPUModelCompatResult cmp =
+        qemuProcessCPUModelComparison(qemuCaps, libDir, runUid, runGid,
+                                      cpu_a, cpu_b, NULL);
 
-    if (qemuMonitorGetCPUModelComparison(proc->mon, cpu_a, cpu_b, &result, 
NULL) < 0)
+    if (cmp == QEMU_CPU_COMPAT_ERROR)
         return VIR_CPU_COMPARE_ERROR;
 
-    if (STREQ(result, "identical"))
+    if (cmp == QEMU_CPU_COMPAT_IDENTICAL)
         return VIR_CPU_COMPARE_IDENTICAL;
 
-    if (STREQ(result, "superset"))
+    if (cmp == QEMU_CPU_COMPAT_SUPERSET)
         return VIR_CPU_COMPARE_SUPERSET;
 
+    /* cpu_a is the host. SUBSET means the host lacks features the guest
+     * needs — treat as incompatible, same as INCOMPATIBLE. */
     if (failIncompatible) {
         virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL);
         return VIR_CPU_COMPARE_ERROR;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 57a3ed3720..90b8acc6c2 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -113,6 +113,14 @@
 
 VIR_LOG_INIT("qemu.qemu_process");
 
+VIR_ENUM_IMPL(qemuCPUModelCompatResult,
+              QEMU_CPU_COMPAT_LAST,
+              "incompatible",
+              "identical",
+              "superset",
+              "subset",
+);
+
 /**
  * qemuProcessRemoveDomainStatus
  *
@@ -10583,6 +10591,48 @@ qemuProcessQMPStart(qemuProcessQMP *proc)
 }
 
 
+qemuCPUModelCompatResult
+qemuProcessCPUModelComparison(virQEMUCaps *qemuCaps,
+                              const char *libDir,
+                              uid_t runUid,
+                              gid_t runGid,
+                              virCPUDef *cpu_a,
+                              virCPUDef *cpu_b,
+                              char ***responsibleProps)
+{
+    g_autoptr(qemuProcessQMP) proc = NULL;
+    g_autofree char *result = NULL;
+    qemuCPUModelCompatResult compatResult;
+
+    if (!(proc = qemuProcessQMPNew(virQEMUCapsGetBinary(qemuCaps),
+                                   libDir, runUid, runGid, false)))
+        return QEMU_CPU_COMPAT_ERROR;
+
+    if (qemuProcessQMPStart(proc) < 0)
+        return QEMU_CPU_COMPAT_ERROR;
+
+    if (qemuMonitorGetCPUModelComparison(proc->mon, cpu_a, cpu_b, &result,
+                                         responsibleProps) < 0)
+        return QEMU_CPU_COMPAT_ERROR;
+
+    compatResult = qemuCPUModelCompatResultTypeFromString(result);
+
+    switch (compatResult) {
+    case QEMU_CPU_COMPAT_INCOMPATIBLE:
+    case QEMU_CPU_COMPAT_IDENTICAL:
+    case QEMU_CPU_COMPAT_SUPERSET:
+    case QEMU_CPU_COMPAT_SUBSET:
+        return compatResult;
+    case QEMU_CPU_COMPAT_ERROR:
+    case QEMU_CPU_COMPAT_LAST:
+    default:
+        VIR_WARN("unknown query-cpu-model-comparison result '%s', treating as 
incompatible",
+                 result);
+        return QEMU_CPU_COMPAT_INCOMPATIBLE;
+    }
+}
+
+
 void
 qemuProcessHandleNbdkitExit(qemuNbdkitProcess *nbdkit,
                             virDomainObj *vm)
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index 5d8f1f89d5..059966e0a7 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -258,6 +258,27 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuProcessQMP, 
qemuProcessQMPFree);
 
 int qemuProcessQMPStart(qemuProcessQMP *proc);
 
+typedef enum {
+    QEMU_CPU_COMPAT_ERROR        = -1,
+    QEMU_CPU_COMPAT_INCOMPATIBLE = 0,
+    QEMU_CPU_COMPAT_IDENTICAL    = 1,
+    QEMU_CPU_COMPAT_SUPERSET     = 2,
+    QEMU_CPU_COMPAT_SUBSET       = 3,
+
+    QEMU_CPU_COMPAT_LAST,
+} qemuCPUModelCompatResult;
+
+VIR_ENUM_DECL(qemuCPUModelCompatResult);
+
+qemuCPUModelCompatResult
+qemuProcessCPUModelComparison(virQEMUCaps *qemuCaps,
+                              const char *libDir,
+                              uid_t runUid,
+                              gid_t runGid,
+                              virCPUDef *cpu_a,
+                              virCPUDef *cpu_b,
+                              char ***responsibleProps);
+
 void qemuProcessCleanupMigrationJob(virQEMUDriver *driver,
                                     virDomainObj *vm);
 
-- 
2.48.1

Reply via email to