[libvirt] [PATCH 21/24] qemu: Introduce generic qemuMonitorGetGuestCPU

Ján Tomko jtomko at redhat.com
Wed Jun 19 12:32:36 UTC 2019


On Wed, Jun 19, 2019 at 11:38:18AM +0200, Jiri Denemark wrote:
>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 at redhat.com>
>---
> src/qemu/qemu_monitor.c      |  36 ++++++
> src/qemu/qemu_monitor.h      |  10 ++
> src/qemu/qemu_monitor_json.c | 211 +++++++++++++++++++++++++++++++++++
> src/qemu/qemu_monitor_json.h |   7 ++
> 4 files changed, 264 insertions(+)
>
>diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
>index 344aac09f0..99aadba2e2 100644
>--- a/src/qemu/qemu_monitor.c
>+++ b/src/qemu/qemu_monitor.c
>@@ -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,

Hehe, "monarch".

>+                                      enabled, disabled);
>+}
>+
>+
> /**
>  * qemuMonitorRTCResetReinjection:
>  * @mon: Pointer to the monitor
>diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
>index ac2499c22a..f5be74f461 100644
>--- a/src/qemu/qemu_monitor.h
>+++ b/src/qemu/qemu_monitor.h
>@@ -1154,6 +1154,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;
>diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
>index efcef211ed..1662e47301 100644
>--- a/src/qemu/qemu_monitor_json.c
>+++ b/src/qemu/qemu_monitor_json.c
>@@ -6137,6 +6137,64 @@ int qemuMonitorJSONGetObjectProperty(qemuMonitorPtr mon,
> }
>
>
>+static int
>+qemuMonitorJSONGetStringListProperty(qemuMonitorPtr mon,
>+                                     const char *path,
>+                                     const char *property,
>+                                     char ***strList)
>+{
>+    virJSONValuePtr cmd;
>+    virJSONValuePtr reply = NULL;

VIR_AUTOPTR(virJSONValue) cmd = NULL;
VIR_AUTOPTR(virJSONValue) reply = NULL;

>+    virJSONValuePtr data;
>+    char **list = NULL;

VIR_AUTOSTRINGLIST list = NULL;

>+    size_t n;
>+    size_t i;
>+    int ret = -1;
>+
>+    *strList = NULL;
>+
>+    if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
>+                                           "s:path", path,
>+                                           "s:property", property,
>+                                           NULL)))
>+        return -1;
>+
>+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
>+        goto cleanup;
>+
>+    if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
>+        goto cleanup;
>+
>+    data = virJSONValueObjectGetArray(reply, "return");
>+    n = virJSONValueArraySize(data);
>+
>+    if (VIR_ALLOC_N(list, n + 1) < 0)
>+        goto cleanup;
>+
>+    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);
>+            goto cleanup;
>+        }
>+
>+        if (VIR_STRDUP(list[i], virJSONValueGetString(item)) < 0)
>+            goto cleanup;
>+    }
>+
>+    VIR_STEAL_PTR(*strList, list);
>+    ret = n;
>+
>+ cleanup:
>+    virJSONValueFree(cmd);
>+    virJSONValueFree(reply);
>+    virStringListFree(list);
>+    return ret;
>+}
>+
>+
> #define MAKE_SET_CMD(STRING, VALUE) \
>     cmd = qemuMonitorJSONMakeCommand("qom-set", \
>                                       "s:path", path, \
>@@ -7369,6 +7427,159 @@ qemuMonitorJSONGetGuestCPUx86(qemuMonitorPtr mon,
>     return -1;
> }
>
>+
>+static int
>+qemuMonitorJSONGetCPUProperties(qemuMonitorPtr mon,
>+                                char ***props)
>+{
>+    virJSONValuePtr cmd;
>+    virJSONValuePtr reply = NULL;

VIR_AUTOPTR(virJSONValue) cmd = NULL;
VIR_AUTOPTR(virJSONValue) reply = NULL;

>+    int ret = -1;
>+
>+    *props = NULL;
>+
>+    if (!(cmd = qemuMonitorJSONMakeCommand("qom-list",
>+                                           "s:path", QOM_CPU_PATH,
>+                                           NULL)))
>+        return -1;
>+
>+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
>+        goto cleanup;
>+
>+    if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {

Shouldn't this be a hard error? IIUC this will be called only for QEMUs
which do have the capability.

On the other hand, ignoring a missing device is consistent with other
GetProperties helpers.

>+        ret = 0;
>+        goto cleanup;
>+    }
>+
>+    ret = qemuMonitorJSONParsePropsList(cmd, reply, "bool", props);
>+
>+ cleanup:
>+    virJSONValueFree(reply);
>+    virJSONValueFree(cmd);
>+    return ret;
>+}
>+
>+
>+static int
>+qemuMonitorJSONGetCPUData(qemuMonitorPtr mon,
>+                          qemuMonitorCPUFeatureTranslationCallback translate,
>+                          void *opaque,
>+                          virCPUDataPtr data)
>+{
>+    qemuMonitorJSONObjectProperty prop = { .type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN };
>+    char **props;

VIR_AUTOSTRINGLIST props = NULL;

>+    char **p;
>+    int ret = -1;
>+
>+    if (qemuMonitorJSONGetCPUProperties(mon, &props) < 0)
>+        goto cleanup;
>+
>+    for (p = props; p && *p; p++) {
>+        const char *name = *p;
>+
>+        if (qemuMonitorJSONGetObjectProperty(mon, QOM_CPU_PATH, name, &prop) < 0)
>+            goto cleanup;
>+
>+        if (!prop.val.b)
>+            continue;
>+
>+        if (translate)
>+            name = translate(name, opaque);
>+
>+        if (virCPUDataAddFeature(data, name) < 0)
>+            goto cleanup;
>+    }
>+
>+    ret = 0;
>+
>+ cleanup:
>+    virStringListFree(props);
>+    return ret;
>+}
>+
>+
>+static int
>+qemuMonitorJSONGetCPUDataDisabled(qemuMonitorPtr mon,
>+                                  qemuMonitorCPUFeatureTranslationCallback translate,
>+                                  void *opaque,
>+                                  virCPUDataPtr data)
>+{
>+    char **props;

VIR_AUTOSTRINGLIST props = NULL;

>+    char **p;
>+    int ret = -1;
>+
>+    if (qemuMonitorJSONGetStringListProperty(mon, QOM_CPU_PATH,
>+                                             "unavailable-features", &props) < 0)
>+        goto cleanup;
>+
>+    for (p = props; p && *p; p++) {
>+        const char *name = *p;
>+
>+        if (translate)
>+            name = translate(name, opaque);
>+

Reviewed-by: Ján Tomko <jtomko at redhat.com>

Jano
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20190619/245cebcd/attachment-0001.sig>


More information about the libvir-list mailing list