|
|
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 |
|