[libvirt] [PATCH 34/36] vircpuhost: Add support for reading MSRs

Satheesh Rajendran sathnaga at linux.vnet.ibm.com
Mon Apr 15 06:45:53 UTC 2019


On Mon, Apr 08, 2019 at 10:42:38AM +0200, Jiri Denemark wrote:
> The new virHostCPUGetMSR internal API will try to read the MSR from
> /dev/cpu/0/msr and if it is not possible (the device does not exist or
> libvirt is running unprivileged), it will fallback to asking KVM for the
> MSR using KVM_GET_MSRS ioctl.
> 
> Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
> ---
>  src/libvirt_private.syms |  1 +
>  src/util/virhostcpu.c    | 80 ++++++++++++++++++++++++++++++++++++++++
>  src/util/virhostcpu.h    |  3 ++
>  3 files changed, 84 insertions(+)
> 
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 132ee3cae9..59a9a6f093 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -2016,6 +2016,7 @@ virHostCPUGetInfo;
>  virHostCPUGetKVMMaxVCPUs;
>  virHostCPUGetMap;
>  virHostCPUGetMicrocodeVersion;
> +virHostCPUGetMSR;

Hi,

This breaks build on powerpc too.

CC       util/libvirt_util_la-virhook.lo
CC       util/libvirt_util_la-virhostcpu.lo
 util/virhostcpu.c: In function 'virHostCPUGetMSRFromKVM':
 util/virhostcpu.c:1267:25: error: field 'header' has incomplete type
  1267 |         struct kvm_msrs header;
2019-04-15 01:06:28,740 process          L0458 DEBUG| [stdout] make[3]: Leaving directory '/usr/share/avocado-plugins-vt/build/libvirt/src'
       |                         ^~~~~~
2019-04-15 01:06:28,741 process          L0458 DEBUG| [stdout] make[2]: Leaving directory '/usr/share/avocado-plugins-vt/build/libvirt/src'
 util/virhostcpu.c:1268:30: error: field 'entry' has incomplete type
2019-04-15 01:06:28,742 process          L0714 INFO | Command 'make' finished with 2 after 27.617787838s
2019-04-15 01:06:28,742 process          L0458 DEBUG| [stdout] make[1]: Leaving directory '/usr/share/avocado-plugins-vt/build/libvirt'
  1268 |         struct kvm_msr_entry entry;
       |                              ^~~~~
 util/virhostcpu.c:1270:21: error: field name not in record or union initializer
  1270 |         .header = { .nmsrs = 1 },
       |                     ^
 util/virhostcpu.c:1270:21: note: (near initialization for 'msr.header')
 util/virhostcpu.c:1271:20: error: field name not in record or union initializer
  1271 |         .entry = { .index = index },
       |                    ^
 util/virhostcpu.c:1271:20: note: (near initialization for 'msr.entry')
 In file included from /usr/include/asm/ioctl.h:12,
                  from /usr/include/asm/ioctls.h:5,
                  from /usr/include/bits/ioctls.h:23,
                  from /usr/include/sys/ioctl.h:26,
                  from ../gnulib/lib/sys/ioctl.h:27,
                  from util/virhostcpu.c:27:
 util/virhostcpu.c:1279:19: error: invalid application of 'sizeof' to incomplete type 'struct kvm_msrs'
  1279 |     if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) {
       |                   ^~~~~~~~~~~~
 make[3]: *** [Makefile:11963: util/libvirt_util_la-virhostcpu.lo] Error 1
 make[2]: *** [Makefile:7128: all] Error 2
 make[1]: *** [Makefile:2257: all-recursive] Error 1
 make: *** [Makefile:2149: all] Error 2

Regards,
-Satheesh

>  virHostCPUGetOnline;
>  virHostCPUGetOnlineBitmap;
>  virHostCPUGetPresentBitmap;
> diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
> index 6514c3d765..10bf3a93d5 100644
> --- a/src/util/virhostcpu.c
> +++ b/src/util/virhostcpu.c
> @@ -58,6 +58,7 @@
>  VIR_LOG_INIT("util.hostcpu");
> 
>  #define KVM_DEVICE "/dev/kvm"
> +#define MSR_DEVICE "/dev/cpu/0/msr"
> 
> 
>  #if defined(__FreeBSD__) || defined(__APPLE__)
> @@ -1254,3 +1255,82 @@ virHostCPUGetMicrocodeVersion(void)
>  }
> 
>  #endif /* __linux__ */
> +
> +
> +#if HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS)
> +static int
> +virHostCPUGetMSRFromKVM(unsigned long index,
> +                        uint64_t *result)
> +{
> +    VIR_AUTOCLOSE fd = -1;
> +    struct {
> +        struct kvm_msrs header;
> +        struct kvm_msr_entry entry;
> +    } msr = {
> +        .header = { .nmsrs = 1 },
> +        .entry = { .index = index },
> +    };
> +
> +    if ((fd = open(KVM_DEVICE, O_RDONLY)) < 0) {
> +        virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
> +        return -1;
> +    }
> +
> +    if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) {
> +        VIR_DEBUG("Cannot get MSR 0x%lx from KVM", index);
> +        return 1;
> +    }
> +
> +    *result = msr.entry.data;
> +    return 0;
> +}
> +
> +#else
> +
> +static int
> +virHostCPUGetMSRFromKVM(unsigned long index ATTRIBUTE_UNUSED,
> +                        uint64_t *result ATTRIBUTE_UNUSED)
> +{
> +    virReportSystemError(ENOSYS, "%s",
> +                         _("Reading MSRs via KVM is not supported on this platform"));
> +    return -1;
> +}
> +#endif /* HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) */
> +
> +
> +/*
> + * Returns 0 on success,
> + *         1 when the MSR is not supported by the host CPU,
> +*         -1 on error.
> + */
> +int
> +virHostCPUGetMSR(unsigned long index,
> +                 uint64_t *msr)
> +{
> +    VIR_AUTOCLOSE fd = -1;
> +    char ebuf[1024];
> +
> +    *msr = 0;
> +
> +    if ((fd = open(MSR_DEVICE, O_RDONLY)) < 0) {
> +        VIR_DEBUG("Unable to open %s: %s",
> +                  MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf)));
> +    } else {
> +        int rc = pread(fd, msr, sizeof(*msr), index);
> +
> +        if (rc == sizeof(*msr))
> +            return 0;
> +
> +        if (rc < 0 && errno == EIO) {
> +            VIR_DEBUG("CPU does not support MSR 0x%lx", index);
> +            return 1;
> +        }
> +
> +        VIR_DEBUG("Cannot read MSR 0x%lx from %s: %s",
> +                  index, MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf)));
> +    }
> +
> +    VIR_DEBUG("Falling back to KVM ioctl");
> +
> +    return virHostCPUGetMSRFromKVM(index, msr);
> +}
> diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
> index df6a7e789d..0d20dbef61 100644
> --- a/src/util/virhostcpu.h
> +++ b/src/util/virhostcpu.h
> @@ -66,4 +66,7 @@ int virHostCPUGetOnline(unsigned int cpu, bool *online);
> 
>  unsigned int virHostCPUGetMicrocodeVersion(void);
> 
> +int virHostCPUGetMSR(unsigned long index,
> +                     uint64_t *msr);
> +
>  #endif /* LIBVIRT_VIRHOSTCPU_H */
> -- 
> 2.21.0
> 
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
> 




More information about the libvir-list mailing list