render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
99cbc7
From 70fd0697564f6a1f9588f4f795956863959d04eb Mon Sep 17 00:00:00 2001
99cbc7
Message-Id: <70fd0697564f6a1f9588f4f795956863959d04eb@dist-git>
99cbc7
From: Jiri Denemark <jdenemar@redhat.com>
99cbc7
Date: Tue, 4 Jun 2019 13:04:25 +0200
99cbc7
Subject: [PATCH] vircpuhost: Add support for reading MSRs
99cbc7
MIME-Version: 1.0
99cbc7
Content-Type: text/plain; charset=UTF-8
99cbc7
Content-Transfer-Encoding: 8bit
99cbc7
99cbc7
The new virHostCPUGetMSR internal API will try to read the MSR from
99cbc7
/dev/cpu/0/msr and if it is not possible (the device does not exist or
99cbc7
libvirt is running unprivileged), it will fallback to asking KVM for the
99cbc7
MSR using KVM_GET_MSRS ioctl.
99cbc7
99cbc7
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
99cbc7
Reviewed-by: Ján Tomko <jtomko@redhat.com>
99cbc7
(cherry picked from commit df4b46737f43a1a67f9b5de2840213a1bd2b3cce)
99cbc7
99cbc7
https://bugzilla.redhat.com/show_bug.cgi?id=1641702
99cbc7
99cbc7
Conflicts:
99cbc7
	src/util/virhostcpu.h
99cbc7
            - context: the comment after #endif changed upstream
99cbc7
99cbc7
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
99cbc7
Message-Id: <696430bedbef1fd8f1f65339173eda0e0b042e9c.1559646067.git.jdenemar@redhat.com>
99cbc7
Reviewed-by: Ján Tomko <jtomko@redhat.com>
99cbc7
---
99cbc7
 src/libvirt_private.syms |  1 +
99cbc7
 src/util/virhostcpu.c    | 80 ++++++++++++++++++++++++++++++++++++++++
99cbc7
 src/util/virhostcpu.h    |  3 ++
99cbc7
 3 files changed, 84 insertions(+)
99cbc7
99cbc7
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
99cbc7
index 984a9be18f..3a99cb6774 100644
99cbc7
--- a/src/libvirt_private.syms
99cbc7
+++ b/src/libvirt_private.syms
99cbc7
@@ -1961,6 +1961,7 @@ virHostCPUGetInfo;
99cbc7
 virHostCPUGetKVMMaxVCPUs;
99cbc7
 virHostCPUGetMap;
99cbc7
 virHostCPUGetMicrocodeVersion;
99cbc7
+virHostCPUGetMSR;
99cbc7
 virHostCPUGetOnline;
99cbc7
 virHostCPUGetOnlineBitmap;
99cbc7
 virHostCPUGetPresentBitmap;
99cbc7
diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
99cbc7
index 3f7d70b87b..2c1404b07a 100644
99cbc7
--- a/src/util/virhostcpu.c
99cbc7
+++ b/src/util/virhostcpu.c
99cbc7
@@ -64,6 +64,7 @@
99cbc7
 VIR_LOG_INIT("util.hostcpu");
99cbc7
 
99cbc7
 #define KVM_DEVICE "/dev/kvm"
99cbc7
+#define MSR_DEVICE "/dev/cpu/0/msr"
99cbc7
 
99cbc7
 
99cbc7
 #if defined(__FreeBSD__) || defined(__APPLE__)
99cbc7
@@ -1294,3 +1295,82 @@ virHostCPUGetMicrocodeVersion(void)
99cbc7
 }
99cbc7
 
99cbc7
 #endif /* __linux__ */
99cbc7
+
99cbc7
+
99cbc7
+#if HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS)
99cbc7
+static int
99cbc7
+virHostCPUGetMSRFromKVM(unsigned long index,
99cbc7
+                        uint64_t *result)
99cbc7
+{
99cbc7
+    VIR_AUTOCLOSE fd = -1;
99cbc7
+    struct {
99cbc7
+        struct kvm_msrs header;
99cbc7
+        struct kvm_msr_entry entry;
99cbc7
+    } msr = {
99cbc7
+        .header = { .nmsrs = 1 },
99cbc7
+        .entry = { .index = index },
99cbc7
+    };
99cbc7
+
99cbc7
+    if ((fd = open(KVM_DEVICE, O_RDONLY)) < 0) {
99cbc7
+        virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
99cbc7
+        return -1;
99cbc7
+    }
99cbc7
+
99cbc7
+    if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) {
99cbc7
+        VIR_DEBUG("Cannot get MSR 0x%lx from KVM", index);
99cbc7
+        return 1;
99cbc7
+    }
99cbc7
+
99cbc7
+    *result = msr.entry.data;
99cbc7
+    return 0;
99cbc7
+}
99cbc7
+
99cbc7
+#else
99cbc7
+
99cbc7
+static int
99cbc7
+virHostCPUGetMSRFromKVM(unsigned long index ATTRIBUTE_UNUSED,
99cbc7
+                        uint64_t *result ATTRIBUTE_UNUSED)
99cbc7
+{
99cbc7
+    virReportSystemError(ENOSYS, "%s",
99cbc7
+                         _("Reading MSRs via KVM is not supported on this platform"));
99cbc7
+    return -1;
99cbc7
+}
99cbc7
+#endif /* HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) */
99cbc7
+
99cbc7
+
99cbc7
+/*
99cbc7
+ * Returns 0 on success,
99cbc7
+ *         1 when the MSR is not supported by the host CPU,
99cbc7
+*         -1 on error.
99cbc7
+ */
99cbc7
+int
99cbc7
+virHostCPUGetMSR(unsigned long index,
99cbc7
+                 uint64_t *msr)
99cbc7
+{
99cbc7
+    VIR_AUTOCLOSE fd = -1;
99cbc7
+    char ebuf[1024];
99cbc7
+
99cbc7
+    *msr = 0;
99cbc7
+
99cbc7
+    if ((fd = open(MSR_DEVICE, O_RDONLY)) < 0) {
99cbc7
+        VIR_DEBUG("Unable to open %s: %s",
99cbc7
+                  MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf)));
99cbc7
+    } else {
99cbc7
+        int rc = pread(fd, msr, sizeof(*msr), index);
99cbc7
+
99cbc7
+        if (rc == sizeof(*msr))
99cbc7
+            return 0;
99cbc7
+
99cbc7
+        if (rc < 0 && errno == EIO) {
99cbc7
+            VIR_DEBUG("CPU does not support MSR 0x%lx", index);
99cbc7
+            return 1;
99cbc7
+        }
99cbc7
+
99cbc7
+        VIR_DEBUG("Cannot read MSR 0x%lx from %s: %s",
99cbc7
+                  index, MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf)));
99cbc7
+    }
99cbc7
+
99cbc7
+    VIR_DEBUG("Falling back to KVM ioctl");
99cbc7
+
99cbc7
+    return virHostCPUGetMSRFromKVM(index, msr);
99cbc7
+}
99cbc7
diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
99cbc7
index f9f3359288..e705623d4f 100644
99cbc7
--- a/src/util/virhostcpu.h
99cbc7
+++ b/src/util/virhostcpu.h
99cbc7
@@ -68,4 +68,7 @@ int virHostCPUGetOnline(unsigned int cpu, bool *online);
99cbc7
 
99cbc7
 unsigned int virHostCPUGetMicrocodeVersion(void);
99cbc7
 
99cbc7
+int virHostCPUGetMSR(unsigned long index,
99cbc7
+                     uint64_t *msr);
99cbc7
+
99cbc7
 #endif /* __VIR_HOSTCPU_H__*/
99cbc7
-- 
99cbc7
2.21.0
99cbc7