]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
vircpuhost: Add support for reading MSRs
authorJiri Denemark <jdenemar@redhat.com>
Fri, 22 Mar 2019 15:44:02 +0000 (16:44 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Fri, 12 Apr 2019 20:53:40 +0000 (22:53 +0200)
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@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/libvirt_private.syms
src/util/virhostcpu.c
src/util/virhostcpu.h

index 5d66623350ce7000eee721f045c8c5da514f4511..94c823d39da1ebca022c7827f7613da1afc952ee 100644 (file)
@@ -2027,6 +2027,7 @@ virHostCPUGetInfo;
 virHostCPUGetKVMMaxVCPUs;
 virHostCPUGetMap;
 virHostCPUGetMicrocodeVersion;
+virHostCPUGetMSR;
 virHostCPUGetOnline;
 virHostCPUGetOnlineBitmap;
 virHostCPUGetPresentBitmap;
index 6514c3d76543c82593fabb1c1b72f18709ad5c36..10bf3a93d53d4cbe7dd522d513d76566ba8afb93 100644 (file)
@@ -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);
+}
index df6a7e789dccd4c8e580da055a13ec327470fed2..0d20dbef61ac2fcdd8b3cd1e2e4e7fb45be234d3 100644 (file)
@@ -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 */