render / rpms / libvirt

Forked from rpms/libvirt 8 months ago
Clone
c480ed
From b61b68abeb8c2c93740698b81d59d2030eea8189 Mon Sep 17 00:00:00 2001
c480ed
Message-Id: <b61b68abeb8c2c93740698b81d59d2030eea8189@dist-git>
c480ed
From: Jiri Denemark <jdenemar@redhat.com>
c480ed
Date: Fri, 21 Jun 2019 09:26:03 +0200
c480ed
Subject: [PATCH] qemu: Introduce generic qemuMonitorGetGuestCPU
c480ed
MIME-Version: 1.0
c480ed
Content-Type: text/plain; charset=UTF-8
c480ed
Content-Transfer-Encoding: 8bit
c480ed
c480ed
Unlike the old version (which is now called qemuMonitorGetGuestCPUx86),
c480ed
this monitor API checks for individual features by their names rather
c480ed
than processing CPUID bits. Thus we can get the list of enabled and
c480ed
disabled features for both CPUID and MSR features.
c480ed
c480ed
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c480ed
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c480ed
(cherry picked from commit cc6d6b3cb995110a1d9da97f31ce68c2290f4332)
c480ed
c480ed
https://bugzilla.redhat.com/show_bug.cgi?id=1697627
c480ed
c480ed
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c480ed
Message-Id: <29634994c64ffbf3509238ccbe1937b599e55838.1561068591.git.jdenemar@redhat.com>
c480ed
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c480ed
---
c480ed
 src/qemu/qemu_monitor.c      |  36 +++++++
c480ed
 src/qemu/qemu_monitor.h      |  10 ++
c480ed
 src/qemu/qemu_monitor_json.c | 186 +++++++++++++++++++++++++++++++++++
c480ed
 src/qemu/qemu_monitor_json.h |   7 ++
c480ed
 4 files changed, 239 insertions(+)
c480ed
c480ed
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
c480ed
index b35187b66d..ae666ce633 100644
c480ed
--- a/src/qemu/qemu_monitor.c
c480ed
+++ b/src/qemu/qemu_monitor.c
c480ed
@@ -4074,6 +4074,42 @@ qemuMonitorGetGuestCPUx86(qemuMonitorPtr mon,
c480ed
 }
c480ed
 
c480ed
 
c480ed
+/**
c480ed
+ * qemuMonitorGetGuestCPU:
c480ed
+ * @mon: Pointer to the monitor
c480ed
+ * @arch: CPU architecture
c480ed
+ * @translate: callback for translating CPU feature names from QEMU to libvirt
c480ed
+ * @opaque: data for @translate callback
c480ed
+ * @enabled: returns the CPU data for all enabled features
c480ed
+ * @disabled: returns the CPU data for features which we asked for
c480ed
+ *      (either explicitly or via a named CPU model) but QEMU disabled them
c480ed
+ *
c480ed
+ * Retrieve the definition of the guest CPU from a running QEMU instance.
c480ed
+ *
c480ed
+ * Returns 0 on success, -1 on error.
c480ed
+ */
c480ed
+int
c480ed
+qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
c480ed
+                       virArch arch,
c480ed
+                       qemuMonitorCPUFeatureTranslationCallback translate,
c480ed
+                       void *opaque,
c480ed
+                       virCPUDataPtr *enabled,
c480ed
+                       virCPUDataPtr *disabled)
c480ed
+{
c480ed
+    VIR_DEBUG("arch=%s translate=%p opaque=%p enabled=%p disabled=%p",
c480ed
+              virArchToString(arch), translate, opaque, enabled, disabled);
c480ed
+
c480ed
+    QEMU_CHECK_MONITOR(mon);
c480ed
+
c480ed
+    *enabled = NULL;
c480ed
+    if (disabled)
c480ed
+        *disabled = NULL;
c480ed
+
c480ed
+    return qemuMonitorJSONGetGuestCPU(mon, arch, translate, opaque,
c480ed
+                                      enabled, disabled);
c480ed
+}
c480ed
+
c480ed
+
c480ed
 /**
c480ed
  * qemuMonitorRTCResetReinjection:
c480ed
  * @mon: Pointer to the monitor
c480ed
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
c480ed
index b4d484c703..8d4f6e6062 100644
c480ed
--- a/src/qemu/qemu_monitor.h
c480ed
+++ b/src/qemu/qemu_monitor.h
c480ed
@@ -1099,6 +1099,16 @@ int qemuMonitorGetGuestCPUx86(qemuMonitorPtr mon,
c480ed
                               virCPUDataPtr *data,
c480ed
                               virCPUDataPtr *disabled);
c480ed
 
c480ed
+typedef const char *(*qemuMonitorCPUFeatureTranslationCallback)(const char *name,
c480ed
+                                                                void *opaque);
c480ed
+
c480ed
+int qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
c480ed
+                           virArch arch,
c480ed
+                           qemuMonitorCPUFeatureTranslationCallback translate,
c480ed
+                           void *opaque,
c480ed
+                           virCPUDataPtr *enabled,
c480ed
+                           virCPUDataPtr *disabled);
c480ed
+
c480ed
 int qemuMonitorRTCResetReinjection(qemuMonitorPtr mon);
c480ed
 
c480ed
 typedef struct _qemuMonitorIOThreadInfo qemuMonitorIOThreadInfo;
c480ed
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
c480ed
index abf952cd34..00a0578809 100644
c480ed
--- a/src/qemu/qemu_monitor_json.c
c480ed
+++ b/src/qemu/qemu_monitor_json.c
c480ed
@@ -5998,6 +5998,57 @@ int qemuMonitorJSONGetObjectProperty(qemuMonitorPtr mon,
c480ed
 }
c480ed
 
c480ed
 
c480ed
+static int
c480ed
+qemuMonitorJSONGetStringListProperty(qemuMonitorPtr mon,
c480ed
+                                     const char *path,
c480ed
+                                     const char *property,
c480ed
+                                     char ***strList)
c480ed
+{
c480ed
+    VIR_AUTOPTR(virJSONValue) cmd = NULL;
c480ed
+    VIR_AUTOPTR(virJSONValue) reply = NULL;
c480ed
+    VIR_AUTOSTRINGLIST list = NULL;
c480ed
+    virJSONValuePtr data;
c480ed
+    size_t n;
c480ed
+    size_t i;
c480ed
+
c480ed
+    *strList = NULL;
c480ed
+
c480ed
+    if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
c480ed
+                                           "s:path", path,
c480ed
+                                           "s:property", property,
c480ed
+                                           NULL)))
c480ed
+        return -1;
c480ed
+
c480ed
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
c480ed
+        return -1;
c480ed
+
c480ed
+    if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
c480ed
+        return -1;
c480ed
+
c480ed
+    data = virJSONValueObjectGetArray(reply, "return");
c480ed
+    n = virJSONValueArraySize(data);
c480ed
+
c480ed
+    if (VIR_ALLOC_N(list, n + 1) < 0)
c480ed
+        return -1;
c480ed
+
c480ed
+    for (i = 0; i < n; i++) {
c480ed
+        virJSONValuePtr item = virJSONValueArrayGet(data, i);
c480ed
+
c480ed
+        if (virJSONValueGetType(item) != VIR_JSON_TYPE_STRING) {
c480ed
+            virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
+                           _("unexpected value in %s array"), property);
c480ed
+            return -1;
c480ed
+        }
c480ed
+
c480ed
+        if (VIR_STRDUP(list[i], virJSONValueGetString(item)) < 0)
c480ed
+            return -1;
c480ed
+    }
c480ed
+
c480ed
+    VIR_STEAL_PTR(*strList, list);
c480ed
+    return n;
c480ed
+}
c480ed
+
c480ed
+
c480ed
 #define MAKE_SET_CMD(STRING, VALUE) \
c480ed
     cmd = qemuMonitorJSONMakeCommand("qom-set", \
c480ed
                                       "s:path", path, \
c480ed
@@ -7207,6 +7258,141 @@ qemuMonitorJSONGetGuestCPUx86(qemuMonitorPtr mon,
c480ed
     return -1;
c480ed
 }
c480ed
 
c480ed
+
c480ed
+static int
c480ed
+qemuMonitorJSONGetCPUProperties(qemuMonitorPtr mon,
c480ed
+                                char ***props)
c480ed
+{
c480ed
+    VIR_AUTOPTR(virJSONValue) cmd = NULL;
c480ed
+    VIR_AUTOPTR(virJSONValue) reply = NULL;
c480ed
+
c480ed
+    *props = NULL;
c480ed
+
c480ed
+    if (!(cmd = qemuMonitorJSONMakeCommand("qom-list",
c480ed
+                                           "s:path", QOM_CPU_PATH,
c480ed
+                                           NULL)))
c480ed
+        return -1;
c480ed
+
c480ed
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
c480ed
+        return -1;
c480ed
+
c480ed
+    if (qemuMonitorJSONHasError(reply, "DeviceNotFound"))
c480ed
+        return 0;
c480ed
+
c480ed
+    return qemuMonitorJSONParsePropsList(cmd, reply, "bool", props);
c480ed
+}
c480ed
+
c480ed
+
c480ed
+static int
c480ed
+qemuMonitorJSONGetCPUData(qemuMonitorPtr mon,
c480ed
+                          qemuMonitorCPUFeatureTranslationCallback translate,
c480ed
+                          void *opaque,
c480ed
+                          virCPUDataPtr data)
c480ed
+{
c480ed
+    qemuMonitorJSONObjectProperty prop = { .type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN };
c480ed
+    VIR_AUTOSTRINGLIST props = NULL;
c480ed
+    char **p;
c480ed
+
c480ed
+    if (qemuMonitorJSONGetCPUProperties(mon, &props) < 0)
c480ed
+        return -1;
c480ed
+
c480ed
+    for (p = props; p && *p; p++) {
c480ed
+        const char *name = *p;
c480ed
+
c480ed
+        if (qemuMonitorJSONGetObjectProperty(mon, QOM_CPU_PATH, name, &prop) < 0)
c480ed
+            return -1;
c480ed
+
c480ed
+        if (!prop.val.b)
c480ed
+            continue;
c480ed
+
c480ed
+        if (translate)
c480ed
+            name = translate(name, opaque);
c480ed
+
c480ed
+        if (virCPUDataAddFeature(data, name) < 0)
c480ed
+            return -1;
c480ed
+    }
c480ed
+
c480ed
+    return 0;
c480ed
+}
c480ed
+
c480ed
+
c480ed
+static int
c480ed
+qemuMonitorJSONGetCPUDataDisabled(qemuMonitorPtr mon,
c480ed
+                                  qemuMonitorCPUFeatureTranslationCallback translate,
c480ed
+                                  void *opaque,
c480ed
+                                  virCPUDataPtr data)
c480ed
+{
c480ed
+    VIR_AUTOSTRINGLIST props = NULL;
c480ed
+    char **p;
c480ed
+
c480ed
+    if (qemuMonitorJSONGetStringListProperty(mon, QOM_CPU_PATH,
c480ed
+                                             "unavailable-features", &props) < 0)
c480ed
+        return -1;
c480ed
+
c480ed
+    for (p = props; p && *p; p++) {
c480ed
+        const char *name = *p;
c480ed
+
c480ed
+        if (translate)
c480ed
+            name = translate(name, opaque);
c480ed
+
c480ed
+        if (virCPUDataAddFeature(data, name) < 0)
c480ed
+            return -1;
c480ed
+    }
c480ed
+
c480ed
+    return 0;
c480ed
+}
c480ed
+
c480ed
+
c480ed
+/**
c480ed
+ * qemuMonitorJSONGetGuestCPU:
c480ed
+ * @mon: Pointer to the monitor
c480ed
+ * @arch: CPU architecture
c480ed
+ * @translate: callback for translating CPU feature names from QEMU to libvirt
c480ed
+ * @opaque: data for @translate callback
c480ed
+ * @enabled: returns the CPU data for all enabled features
c480ed
+ * @disabled: returns the CPU data for features which we asked for
c480ed
+ *      (either explicitly or via a named CPU model) but QEMU disabled them
c480ed
+ *
c480ed
+ * Retrieve the definition of the guest CPU from a running QEMU instance.
c480ed
+ *
c480ed
+ * Returns 0 on success, -1 on error.
c480ed
+ */
c480ed
+int
c480ed
+qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
c480ed
+                           virArch arch,
c480ed
+                           qemuMonitorCPUFeatureTranslationCallback translate,
c480ed
+                           void *opaque,
c480ed
+                           virCPUDataPtr *enabled,
c480ed
+                           virCPUDataPtr *disabled)
c480ed
+{
c480ed
+    virCPUDataPtr cpuEnabled = NULL;
c480ed
+    virCPUDataPtr cpuDisabled = NULL;
c480ed
+    int ret = -1;
c480ed
+
c480ed
+    if (!(cpuEnabled = virCPUDataNew(arch)) ||
c480ed
+        !(cpuDisabled = virCPUDataNew(arch)))
c480ed
+        goto cleanup;
c480ed
+
c480ed
+    if (qemuMonitorJSONGetCPUData(mon, translate, opaque, cpuEnabled) < 0)
c480ed
+        goto cleanup;
c480ed
+
c480ed
+    if (disabled &&
c480ed
+        qemuMonitorJSONGetCPUDataDisabled(mon, translate, opaque, cpuDisabled) < 0)
c480ed
+        goto cleanup;
c480ed
+
c480ed
+    VIR_STEAL_PTR(*enabled, cpuEnabled);
c480ed
+    if (disabled)
c480ed
+        VIR_STEAL_PTR(*disabled, cpuDisabled);
c480ed
+
c480ed
+    ret = 0;
c480ed
+
c480ed
+ cleanup:
c480ed
+    virCPUDataFree(cpuEnabled);
c480ed
+    virCPUDataFree(cpuDisabled);
c480ed
+    return ret;
c480ed
+}
c480ed
+
c480ed
+
c480ed
 int
c480ed
 qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon)
c480ed
 {
c480ed
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
c480ed
index 57bed027e2..29b10aad26 100644
c480ed
--- a/src/qemu/qemu_monitor_json.h
c480ed
+++ b/src/qemu/qemu_monitor_json.h
c480ed
@@ -490,6 +490,13 @@ int qemuMonitorJSONGetGuestCPUx86(qemuMonitorPtr mon,
c480ed
                                   virCPUDataPtr *data,
c480ed
                                   virCPUDataPtr *disabled);
c480ed
 
c480ed
+int qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
c480ed
+                               virArch arch,
c480ed
+                               qemuMonitorCPUFeatureTranslationCallback translate,
c480ed
+                               void *opaque,
c480ed
+                               virCPUDataPtr *enabled,
c480ed
+                               virCPUDataPtr *disabled);
c480ed
+
c480ed
 int qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon);
c480ed
 
c480ed
 int qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon,
c480ed
-- 
c480ed
2.22.0
c480ed