[libvirt] [PATCHv3 2/6] qemu: Add monitor APIs to fetch CPUID data from QEMU
John Ferlan
jferlan at redhat.com
Fri Nov 8 17:44:59 UTC 2013
On 11/04/2013 08:55 AM, Peter Krempa wrote:
> From: Jiri Denemark <jdenemar at 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 at redhat.com>
> ---
>
<...snip...>
> 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)) {
> + 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;
> + }
> +
> + cpuid->function = fun;
> + if (STREQ(reg, "EAX")) {
> + cpuid->eax = features;
> + } else if (STREQ(reg, "EBX")) {
> + cpuid->ebx = features;
> + } else if (STREQ(reg, "ECX")) {
> + cpuid->ecx = features;
> + } else if (STREQ(reg, "EDX")) {
> + cpuid->edx = features;
> + } else {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("unknown CPU register '%s'"), reg);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +
> +static virCPUDataPtr
> +qemuMonitorJSONGetCPUx86Data(qemuMonitorPtr mon,
> + const char *property)
> +{
> + virJSONValuePtr cmd;
> + virJSONValuePtr reply = NULL;
> + virJSONValuePtr data;
> + virCPUx86Data *x86Data = NULL;
> + virCPUx86CPUID cpuid;
> + size_t i;
> + virCPUDataPtr ret = NULL;
> + int n;
> +
> + if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
> + "s:path", QOM_CPU_PATH,
> + "s:property", property,
> + NULL)))
> + return NULL;
> +
> + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
> + goto cleanup;
> +
> + if (qemuMonitorJSONCheckError(cmd, reply))
> + goto cleanup;
> +
> + if (!(data = virJSONValueObjectGet(reply, "return"))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("qom-get reply was missing return data"));
> + goto cleanup;
> + }
> +
> + if ((n = virJSONValueArraySize(data)) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("%s CPU property did not return an array"),
> + property);
> + goto cleanup;
> + }
> +
> + if (VIR_ALLOC(x86Data) < 0)
> + goto cleanup;
> +
> + for (i = 0; i < n; i++) {
> + if (qemuMonitorJSONParseCPUx86FeatureWord(virJSONValueArrayGet(data, i),
> + &cpuid) < 0 ||
> + virCPUx86DataAddCPUID(x86Data, &cpuid) < 0)
> + goto cleanup;
> + }
> +
> + if (!(ret = virCPUx86MakeData(VIR_ARCH_X86_64, &x86Data)))
> + goto cleanup;
> +
> +cleanup:
> + virJSONValueFree(cmd);
> + virJSONValueFree(reply);
> + virCPUx86DataFree(x86Data);
> + return ret;
> +}
> +
> +
> +/**
> + * 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
> +qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
> + virArch arch)
> +{
> + switch (arch) {
> + case VIR_ARCH_X86_64:
> + case VIR_ARCH_I686:
> + return qemuMonitorJSONGetCPUx86Data(mon, "feature-words");
According to:
http://wiki.qemu.org/Features/CPUModels
This was added in qemu 1.5, I have qemu 1.4.2 installed right now and VM
startups fail:
error: Failed to start domain f18
error: internal error: unable to execute QEMU command 'qom-get':
Property '.feature-words' not found
John
> +
> + default:
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("CPU definition retrieval isn't supported for '%s'"),
> + virArchToString(arch));
> + return NULL;
> + }
> +}
More information about the libvir-list
mailing list