On Mon, Nov 04, 2013 at 14:55:03 +0100, Peter Krempa wrote:
From: Jiri Denemark <jdenemar(a)redhat.com>
The qemu monitor supports retrieval of actual CPUID bits presented to
the guest using QMP monitor. Add APIs to extract these information and
tests for them.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
Notes:
Version 3:
- removed unneeded error state
- fixed typo in error message
Version 2:
- unified global and JSON monitor func signatures
- changed return values so that errors can be differenitated from lack of support
- code is conditionally run only when architecture matches
src/qemu/qemu_monitor.c | 31 +++++
src/qemu/qemu_monitor.h | 4 +
src/qemu/qemu_monitor_json.c | 133 +++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 2 +
tests/Makefile.am | 1 +
.../qemumonitorjson-getcpu-full.data | 5 +
.../qemumonitorjson-getcpu-full.json | 46 +++++++
.../qemumonitorjson-getcpu-host.data | 6 +
.../qemumonitorjson-getcpu-host.json | 45 +++++++
tests/qemumonitorjsontest.c | 75 ++++++++++++
10 files changed, 348 insertions(+)
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.data
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-full.json
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.data
create mode 100644 tests/qemumonitorjsondata/qemumonitorjson-getcpu-host.json
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 2bafe28..e865808 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3926,3 +3926,34 @@ qemuMonitorSetDomainLog(qemuMonitorPtr mon, int logfd)
return 0;
}
+
+
+/**
+ * qemuMonitorJSONGetGuestCPU:
+ * @mon: Pointer to the monitor
+ * @arch: arch of the guest
+ *
+ * Retrieve the definition of the guest CPU from a running qemu instance.
+ *
+ * Returns the cpu definition object. On error returns NULL.
+ */
+virCPUDataPtr
+qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
+ virArch arch)
+{
+ VIR_DEBUG("mon=%p, arch='%s'", mon, virArchToString(arch));
+
+ if (!mon) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("monitor must not be NULL"));
+ return NULL;
+ }
+
+ if (!mon->json) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("JSON monitor is required"));
+ return NULL;
+ }
+
+ return qemuMonitorJSONGetGuestCPU(mon, arch);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 06ba7e8..ecc6d7b 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -32,6 +32,7 @@
# include "virhash.h"
# include "virjson.h"
# include "device_conf.h"
+# include "cpu/cpu.h"
typedef struct _qemuMonitor qemuMonitor;
typedef qemuMonitor *qemuMonitorPtr;
@@ -763,6 +764,9 @@ int qemuMonitorGetDeviceAliases(qemuMonitorPtr mon,
int qemuMonitorSetDomainLog(qemuMonitorPtr mon, int logfd);
+virCPUDataPtr qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
+ virArch arch);
+
/**
* When running two dd process and using <> redirection, we need a
* shell that will not truncate files. These two strings serve that
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 05f8aa6..e738fe3 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -42,6 +42,7 @@
#include "virerror.h"
#include "virjson.h"
#include "virstring.h"
+#include "cpu/cpu_x86.h"
#ifdef WITH_DTRACE_PROBES
# include "libvirt_qemu_probes.h"
@@ -49,6 +50,7 @@
#define VIR_FROM_THIS VIR_FROM_QEMU
+#define QOM_CPU_PATH "/machine/unattached/device[0]"
#define LINE_ENDING "\r\n"
@@ -5454,3 +5456,134 @@ cleanup:
VIR_FREE(paths);
return ret;
}
+
+
+static int
+qemuMonitorJSONParseCPUx86FeatureWord(virJSONValuePtr data,
+ virCPUx86CPUID *cpuid)
+{
+ const char *reg;
+ unsigned long long fun;
+ unsigned long long features;
+
+ memset(cpuid, 0, sizeof(*cpuid));
+
+ if (!(reg = virJSONValueObjectGetString(data, "cpuid-register"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing cpuid-register in CPU data"));
+ return -1;
+ }
+ if (virJSONValueObjectGetNumberUlong(data, "cpuid-input-eax", &fun)) {
I guess this should have been "if (... < 0)", right?
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing or invalid cpuid-input-eax in CPU data"));
+ return -1;
+ }
+ if (virJSONValueObjectGetNumberUlong(data, "features", &features) <
0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing or invalid features in CPU data"));
+ return -1;
+ }
...
ACK
Jirka