[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