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(a)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(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list