324 lines
10 KiB
Diff
324 lines
10 KiB
Diff
From b61b68abeb8c2c93740698b81d59d2030eea8189 Mon Sep 17 00:00:00 2001
|
|
Message-Id: <b61b68abeb8c2c93740698b81d59d2030eea8189@dist-git>
|
|
From: Jiri Denemark <jdenemar@redhat.com>
|
|
Date: Fri, 21 Jun 2019 09:26:03 +0200
|
|
Subject: [PATCH] qemu: Introduce generic qemuMonitorGetGuestCPU
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
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>
|
|
(cherry picked from commit cc6d6b3cb995110a1d9da97f31ce68c2290f4332)
|
|
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1697627
|
|
|
|
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
Message-Id: <29634994c64ffbf3509238ccbe1937b599e55838.1561068591.git.jdenemar@redhat.com>
|
|
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
---
|
|
src/qemu/qemu_monitor.c | 36 +++++++
|
|
src/qemu/qemu_monitor.h | 10 ++
|
|
src/qemu/qemu_monitor_json.c | 186 +++++++++++++++++++++++++++++++++++
|
|
src/qemu/qemu_monitor_json.h | 7 ++
|
|
4 files changed, 239 insertions(+)
|
|
|
|
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
|
|
index b35187b66d..ae666ce633 100644
|
|
--- a/src/qemu/qemu_monitor.c
|
|
+++ b/src/qemu/qemu_monitor.c
|
|
@@ -4074,6 +4074,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
|
|
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
|
|
index b4d484c703..8d4f6e6062 100644
|
|
--- a/src/qemu/qemu_monitor.h
|
|
+++ b/src/qemu/qemu_monitor.h
|
|
@@ -1099,6 +1099,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 abf952cd34..00a0578809 100644
|
|
--- a/src/qemu/qemu_monitor_json.c
|
|
+++ b/src/qemu/qemu_monitor_json.c
|
|
@@ -5998,6 +5998,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, \
|
|
@@ -7207,6 +7258,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)
|
|
{
|
|
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
|
|
index 57bed027e2..29b10aad26 100644
|
|
--- a/src/qemu/qemu_monitor_json.h
|
|
+++ b/src/qemu/qemu_monitor_json.h
|
|
@@ -490,6 +490,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,
|
|
--
|
|
2.22.0
|
|
|