]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Introduce generic qemuMonitorGetGuestCPU
authorJiri Denemark <jdenemar@redhat.com>
Mon, 17 Jun 2019 21:36:53 +0000 (23:36 +0200)
committerJiri Denemark <jdenemar@redhat.com>
Wed, 19 Jun 2019 22:22:39 +0000 (00:22 +0200)
Unlike the old version (which is now called qemuMonitorGetGuestCPUx86),
this monitor API checks for individual features by their names rather
than processing CPUID bits. Thus we can get the list of enabled and
disabled features for both CPUID and MSR features.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h

index 344aac09f02e5c36410a995702f8d8cb0ee77080..99aadba2e2dfcf845fc9ac9718ff044ffa20d2a1 100644 (file)
@@ -4107,6 +4107,42 @@ qemuMonitorGetGuestCPUx86(qemuMonitorPtr mon,
 }
 
 
+/**
+ * qemuMonitorGetGuestCPU:
+ * @mon: Pointer to the monitor
+ * @arch: CPU architecture
+ * @translate: callback for translating CPU feature names from QEMU to libvirt
+ * @opaque: data for @translate callback
+ * @enabled: returns the CPU data for all enabled features
+ * @disabled: returns the CPU data for features which we asked for
+ *      (either explicitly or via a named CPU model) but QEMU disabled them
+ *
+ * Retrieve the definition of the guest CPU from a running QEMU instance.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int
+qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
+                       virArch arch,
+                       qemuMonitorCPUFeatureTranslationCallback translate,
+                       void *opaque,
+                       virCPUDataPtr *enabled,
+                       virCPUDataPtr *disabled)
+{
+    VIR_DEBUG("arch=%s translate=%p opaque=%p enabled=%p disabled=%p",
+              virArchToString(arch), translate, opaque, enabled, disabled);
+
+    QEMU_CHECK_MONITOR(mon);
+
+    *enabled = NULL;
+    if (disabled)
+        *disabled = NULL;
+
+    return qemuMonitorJSONGetGuestCPU(mon, arch, translate, opaque,
+                                      enabled, disabled);
+}
+
+
 /**
  * qemuMonitorRTCResetReinjection:
  * @mon: Pointer to the monitor
index f166f5f949464422e9a47d1e6fbfe2af246e561d..209bf2af56d42822d84c26fbbcf9606ccf540ad6 100644 (file)
@@ -1153,6 +1153,16 @@ int qemuMonitorGetGuestCPUx86(qemuMonitorPtr mon,
                               virCPUDataPtr *data,
                               virCPUDataPtr *disabled);
 
+typedef const char *(*qemuMonitorCPUFeatureTranslationCallback)(const char *name,
+                                                                void *opaque);
+
+int qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
+                           virArch arch,
+                           qemuMonitorCPUFeatureTranslationCallback translate,
+                           void *opaque,
+                           virCPUDataPtr *enabled,
+                           virCPUDataPtr *disabled);
+
 int qemuMonitorRTCResetReinjection(qemuMonitorPtr mon);
 
 typedef struct _qemuMonitorIOThreadInfo qemuMonitorIOThreadInfo;
index efcef211ed1badb30d6277d67b33d830f14b49e0..96f44bc7604a93f2404651caf2763c35514a8b75 100644 (file)
@@ -6137,6 +6137,57 @@ int qemuMonitorJSONGetObjectProperty(qemuMonitorPtr mon,
 }
 
 
+static int
+qemuMonitorJSONGetStringListProperty(qemuMonitorPtr mon,
+                                     const char *path,
+                                     const char *property,
+                                     char ***strList)
+{
+    VIR_AUTOPTR(virJSONValue) cmd = NULL;
+    VIR_AUTOPTR(virJSONValue) reply = NULL;
+    VIR_AUTOSTRINGLIST list = NULL;
+    virJSONValuePtr data;
+    size_t n;
+    size_t i;
+
+    *strList = NULL;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
+                                           "s:path", path,
+                                           "s:property", property,
+                                           NULL)))
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
+        return -1;
+
+    data = virJSONValueObjectGetArray(reply, "return");
+    n = virJSONValueArraySize(data);
+
+    if (VIR_ALLOC_N(list, n + 1) < 0)
+        return -1;
+
+    for (i = 0; i < n; i++) {
+        virJSONValuePtr item = virJSONValueArrayGet(data, i);
+
+        if (virJSONValueGetType(item) != VIR_JSON_TYPE_STRING) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("unexpected value in %s array"), property);
+            return -1;
+        }
+
+        if (VIR_STRDUP(list[i], virJSONValueGetString(item)) < 0)
+            return -1;
+    }
+
+    VIR_STEAL_PTR(*strList, list);
+    return n;
+}
+
+
 #define MAKE_SET_CMD(STRING, VALUE) \
     cmd = qemuMonitorJSONMakeCommand("qom-set", \
                                       "s:path", path, \
@@ -7369,6 +7420,141 @@ qemuMonitorJSONGetGuestCPUx86(qemuMonitorPtr mon,
     return -1;
 }
 
+
+static int
+qemuMonitorJSONGetCPUProperties(qemuMonitorPtr mon,
+                                char ***props)
+{
+    VIR_AUTOPTR(virJSONValue) cmd = NULL;
+    VIR_AUTOPTR(virJSONValue) reply = NULL;
+
+    *props = NULL;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("qom-list",
+                                           "s:path", QOM_CPU_PATH,
+                                           NULL)))
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    if (qemuMonitorJSONHasError(reply, "DeviceNotFound"))
+        return 0;
+
+    return qemuMonitorJSONParsePropsList(cmd, reply, "bool", props);
+}
+
+
+static int
+qemuMonitorJSONGetCPUData(qemuMonitorPtr mon,
+                          qemuMonitorCPUFeatureTranslationCallback translate,
+                          void *opaque,
+                          virCPUDataPtr data)
+{
+    qemuMonitorJSONObjectProperty prop = { .type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN };
+    VIR_AUTOSTRINGLIST props = NULL;
+    char **p;
+
+    if (qemuMonitorJSONGetCPUProperties(mon, &props) < 0)
+        return -1;
+
+    for (p = props; p && *p; p++) {
+        const char *name = *p;
+
+        if (qemuMonitorJSONGetObjectProperty(mon, QOM_CPU_PATH, name, &prop) < 0)
+            return -1;
+
+        if (!prop.val.b)
+            continue;
+
+        if (translate)
+            name = translate(name, opaque);
+
+        if (virCPUDataAddFeature(data, name) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+static int
+qemuMonitorJSONGetCPUDataDisabled(qemuMonitorPtr mon,
+                                  qemuMonitorCPUFeatureTranslationCallback translate,
+                                  void *opaque,
+                                  virCPUDataPtr data)
+{
+    VIR_AUTOSTRINGLIST props = NULL;
+    char **p;
+
+    if (qemuMonitorJSONGetStringListProperty(mon, QOM_CPU_PATH,
+                                             "unavailable-features", &props) < 0)
+        return -1;
+
+    for (p = props; p && *p; p++) {
+        const char *name = *p;
+
+        if (translate)
+            name = translate(name, opaque);
+
+        if (virCPUDataAddFeature(data, name) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+/**
+ * qemuMonitorJSONGetGuestCPU:
+ * @mon: Pointer to the monitor
+ * @arch: CPU architecture
+ * @translate: callback for translating CPU feature names from QEMU to libvirt
+ * @opaque: data for @translate callback
+ * @enabled: returns the CPU data for all enabled features
+ * @disabled: returns the CPU data for features which we asked for
+ *      (either explicitly or via a named CPU model) but QEMU disabled them
+ *
+ * Retrieve the definition of the guest CPU from a running QEMU instance.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int
+qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
+                           virArch arch,
+                           qemuMonitorCPUFeatureTranslationCallback translate,
+                           void *opaque,
+                           virCPUDataPtr *enabled,
+                           virCPUDataPtr *disabled)
+{
+    virCPUDataPtr cpuEnabled = NULL;
+    virCPUDataPtr cpuDisabled = NULL;
+    int ret = -1;
+
+    if (!(cpuEnabled = virCPUDataNew(arch)) ||
+        !(cpuDisabled = virCPUDataNew(arch)))
+        goto cleanup;
+
+    if (qemuMonitorJSONGetCPUData(mon, translate, opaque, cpuEnabled) < 0)
+        goto cleanup;
+
+    if (disabled &&
+        qemuMonitorJSONGetCPUDataDisabled(mon, translate, opaque, cpuDisabled) < 0)
+        goto cleanup;
+
+    VIR_STEAL_PTR(*enabled, cpuEnabled);
+    if (disabled)
+        VIR_STEAL_PTR(*disabled, cpuDisabled);
+
+    ret = 0;
+
+ cleanup:
+    virCPUDataFree(cpuEnabled);
+    virCPUDataFree(cpuDisabled);
+    return ret;
+}
+
+
 int
 qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon)
 {
index 1bc1df0e3bcc6e658b3c9dd83fc660e09a19542b..d0b519c88ecb943a17da3963666ca478833921a9 100644 (file)
@@ -492,6 +492,13 @@ int qemuMonitorJSONGetGuestCPUx86(qemuMonitorPtr mon,
                                   virCPUDataPtr *data,
                                   virCPUDataPtr *disabled);
 
+int qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
+                               virArch arch,
+                               qemuMonitorCPUFeatureTranslationCallback translate,
+                               void *opaque,
+                               virCPUDataPtr *enabled,
+                               virCPUDataPtr *disabled);
+
 int qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon);
 
 int qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon,