From 6094ea6111dd57274b6037e76f662a06b8e5c9d1 Mon Sep 17 00:00:00 2001 Message-Id: <6094ea6111dd57274b6037e76f662a06b8e5c9d1@dist-git> From: Jiri Denemark Date: Fri, 21 Jun 2019 09:25:43 +0200 Subject: [PATCH] vircpuhost: Add support for reading MSRs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Ján Tomko (cherry picked from commit df4b46737f43a1a67f9b5de2840213a1bd2b3cce) https://bugzilla.redhat.com/show_bug.cgi?id=1697627 Conflicts: src/util/virhostcpu.h - different header file guard symbol Signed-off-by: Jiri Denemark Message-Id: <0d4c18704c435cccc2b18ebd55f4f914caf05d13.1561068591.git.jdenemar@redhat.com> Reviewed-by: Ján Tomko --- 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 347667b17c..9ebc5384fb 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1974,6 +1974,7 @@ virHostCPUGetInfo; virHostCPUGetKVMMaxVCPUs; virHostCPUGetMap; virHostCPUGetMicrocodeVersion; +virHostCPUGetMSR; virHostCPUGetOnline; virHostCPUGetOnlineBitmap; virHostCPUGetPresentBitmap; diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c index effe04ca3a..d0c47faa18 100644 --- a/src/util/virhostcpu.c +++ b/src/util/virhostcpu.c @@ -64,6 +64,7 @@ VIR_LOG_INIT("util.hostcpu"); #define KVM_DEVICE "/dev/kvm" +#define MSR_DEVICE "/dev/cpu/0/msr" #if defined(__FreeBSD__) || defined(__APPLE__) @@ -1266,3 +1267,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 f9f3359288..e705623d4f 100644 --- a/src/util/virhostcpu.h +++ b/src/util/virhostcpu.h @@ -68,4 +68,7 @@ int virHostCPUGetOnline(unsigned int cpu, bool *online); unsigned int virHostCPUGetMicrocodeVersion(void); +int virHostCPUGetMSR(unsigned long index, + uint64_t *msr); + #endif /* __VIR_HOSTCPU_H__*/ -- 2.22.0