|
|
0a7476 |
From 8953e599b13320239ced8e2422f95a1286847d93 Mon Sep 17 00:00:00 2001
|
|
|
0a7476 |
Message-Id: <8953e599b13320239ced8e2422f95a1286847d93@dist-git>
|
|
|
0a7476 |
From: Jiri Denemark <jdenemar@redhat.com>
|
|
|
0a7476 |
Date: Tue, 4 Jun 2019 13:04:29 +0200
|
|
|
0a7476 |
Subject: [PATCH] util: Add virHostCPUGetTscInfo
|
|
|
0a7476 |
MIME-Version: 1.0
|
|
|
0a7476 |
Content-Type: text/plain; charset=UTF-8
|
|
|
0a7476 |
Content-Transfer-Encoding: 8bit
|
|
|
0a7476 |
|
|
|
0a7476 |
On a KVM x86_64 host which supports invariant TSC this function can be
|
|
|
0a7476 |
used to detect the TSC frequency and the availability of TSC scaling.
|
|
|
0a7476 |
|
|
|
0a7476 |
The magic MSR numbers required to check if VMX scaling is supported on
|
|
|
0a7476 |
the host are documented in Volume 3 of the Intel® 64 and IA-32
|
|
|
0a7476 |
Architectures Software Developer’s Manual.
|
|
|
0a7476 |
|
|
|
0a7476 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
0a7476 |
(cherry picked from commit f0f6faba63becfab38c928905ac6ed79f9a318b8)
|
|
|
0a7476 |
|
|
|
0a7476 |
https://bugzilla.redhat.com/show_bug.cgi?id=1641702
|
|
|
0a7476 |
|
|
|
0a7476 |
Conflicts:
|
|
|
0a7476 |
src/util/virhostcpu.h
|
|
|
0a7476 |
- virenum.h doesn't exist downstream, the content is still
|
|
|
0a7476 |
in virutil.h
|
|
|
0a7476 |
- the comment after #endif changed upstream
|
|
|
0a7476 |
|
|
|
0a7476 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
0a7476 |
Message-Id: <b44a5f67b95fde34eacabf86c47c1c278d4cf03f.1559646067.git.jdenemar@redhat.com>
|
|
|
0a7476 |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
0a7476 |
---
|
|
|
0a7476 |
src/util/virhostcpu.c | 71 +++++++++++++++++++++++++++++++++++++++++++
|
|
|
0a7476 |
src/util/virhostcpu.h | 11 +++++++
|
|
|
0a7476 |
2 files changed, 82 insertions(+)
|
|
|
0a7476 |
|
|
|
0a7476 |
diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
|
|
|
0a7476 |
index 1b6570568c..0f84780e09 100644
|
|
|
0a7476 |
--- a/src/util/virhostcpu.c
|
|
|
0a7476 |
+++ b/src/util/virhostcpu.c
|
|
|
0a7476 |
@@ -1364,6 +1364,69 @@ virHostCPUGetMSR(unsigned long index,
|
|
|
0a7476 |
return virHostCPUGetMSRFromKVM(index, msr);
|
|
|
0a7476 |
}
|
|
|
0a7476 |
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+# define VMX_PROCBASED_CTLS2_MSR 0x48b
|
|
|
0a7476 |
+# define VMX_USE_TSC_SCALING (1 << 25)
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+/*
|
|
|
0a7476 |
+ * This function should only be called when the host CPU supports invariant TSC
|
|
|
0a7476 |
+ * (invtsc CPUID feature).
|
|
|
0a7476 |
+ *
|
|
|
0a7476 |
+ * Returns pointer to the TSC info structure on success,
|
|
|
0a7476 |
+ * NULL when TSC cannot be probed otherwise.
|
|
|
0a7476 |
+ */
|
|
|
0a7476 |
+virHostCPUTscInfoPtr
|
|
|
0a7476 |
+virHostCPUGetTscInfo(void)
|
|
|
0a7476 |
+{
|
|
|
0a7476 |
+ virHostCPUTscInfoPtr info;
|
|
|
0a7476 |
+ VIR_AUTOCLOSE kvmFd = -1;
|
|
|
0a7476 |
+ VIR_AUTOCLOSE vmFd = -1;
|
|
|
0a7476 |
+ VIR_AUTOCLOSE vcpuFd = -1;
|
|
|
0a7476 |
+ uint64_t msr = 0;
|
|
|
0a7476 |
+ int rc;
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ if ((kvmFd = open(KVM_DEVICE, O_RDONLY)) < 0) {
|
|
|
0a7476 |
+ virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
|
|
|
0a7476 |
+ return NULL;
|
|
|
0a7476 |
+ }
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ if ((vmFd = ioctl(kvmFd, KVM_CREATE_VM, 0)) < 0) {
|
|
|
0a7476 |
+ virReportSystemError(errno, "%s",
|
|
|
0a7476 |
+ _("Unable to create KVM VM for TSC probing"));
|
|
|
0a7476 |
+ return NULL;
|
|
|
0a7476 |
+ }
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ if ((vcpuFd = ioctl(vmFd, KVM_CREATE_VCPU, 0)) < 0) {
|
|
|
0a7476 |
+ virReportSystemError(errno, "%s",
|
|
|
0a7476 |
+ _("Unable to create KVM vCPU for TSC probing"));
|
|
|
0a7476 |
+ return NULL;
|
|
|
0a7476 |
+ }
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ if ((rc = ioctl(vcpuFd, KVM_GET_TSC_KHZ)) < 0) {
|
|
|
0a7476 |
+ virReportSystemError(errno, "%s",
|
|
|
0a7476 |
+ _("Unable to probe TSC frequency"));
|
|
|
0a7476 |
+ return NULL;
|
|
|
0a7476 |
+ }
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ if (VIR_ALLOC(info) < 0)
|
|
|
0a7476 |
+ return NULL;
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ info->frequency = rc * 1000ULL;
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ if (virHostCPUGetMSR(VMX_PROCBASED_CTLS2_MSR, &msr) == 0) {
|
|
|
0a7476 |
+ /* High 32 bits of the MSR value indicate whether specific control
|
|
|
0a7476 |
+ * can be set to 1. */
|
|
|
0a7476 |
+ msr >>= 32;
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ info->scaling = virTristateBoolFromBool(!!(msr & VMX_USE_TSC_SCALING));
|
|
|
0a7476 |
+ }
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ VIR_DEBUG("Detected TSC frequency %llu Hz, scaling %s",
|
|
|
0a7476 |
+ info->frequency, virTristateBoolTypeToString(info->scaling));
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ return info;
|
|
|
0a7476 |
+}
|
|
|
0a7476 |
+
|
|
|
0a7476 |
#else
|
|
|
0a7476 |
|
|
|
0a7476 |
int
|
|
|
0a7476 |
@@ -1375,6 +1438,14 @@ virHostCPUGetMSR(unsigned long index ATTRIBUTE_UNUSED,
|
|
|
0a7476 |
return -1;
|
|
|
0a7476 |
}
|
|
|
0a7476 |
|
|
|
0a7476 |
+virHostCPUTscInfoPtr
|
|
|
0a7476 |
+virHostCPUGetTscInfo(void)
|
|
|
0a7476 |
+{
|
|
|
0a7476 |
+ virReportSystemError(ENOSYS, "%s",
|
|
|
0a7476 |
+ _("Probing TSC is not supported on this platform"));
|
|
|
0a7476 |
+ return NULL;
|
|
|
0a7476 |
+}
|
|
|
0a7476 |
+
|
|
|
0a7476 |
#endif /* HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) && \
|
|
|
0a7476 |
(defined(__i386__) || defined(__x86_64__)) && \
|
|
|
0a7476 |
(defined(__linux__) || defined(__FreeBSD__)) */
|
|
|
0a7476 |
diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
|
|
|
0a7476 |
index e705623d4f..ee9d755c83 100644
|
|
|
0a7476 |
--- a/src/util/virhostcpu.h
|
|
|
0a7476 |
+++ b/src/util/virhostcpu.h
|
|
|
0a7476 |
@@ -27,6 +27,15 @@
|
|
|
0a7476 |
# include "internal.h"
|
|
|
0a7476 |
# include "virarch.h"
|
|
|
0a7476 |
# include "virbitmap.h"
|
|
|
0a7476 |
+# include "virutil.h"
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+typedef struct _virHostCPUTscInfo virHostCPUTscInfo;
|
|
|
0a7476 |
+typedef virHostCPUTscInfo *virHostCPUTscInfoPtr;
|
|
|
0a7476 |
+struct _virHostCPUTscInfo {
|
|
|
0a7476 |
+ unsigned long long frequency;
|
|
|
0a7476 |
+ virTristateBool scaling;
|
|
|
0a7476 |
+};
|
|
|
0a7476 |
|
|
|
0a7476 |
|
|
|
0a7476 |
int virHostCPUGetStats(int cpuNum,
|
|
|
0a7476 |
@@ -71,4 +80,6 @@ unsigned int virHostCPUGetMicrocodeVersion(void);
|
|
|
0a7476 |
int virHostCPUGetMSR(unsigned long index,
|
|
|
0a7476 |
uint64_t *msr);
|
|
|
0a7476 |
|
|
|
0a7476 |
+virHostCPUTscInfoPtr virHostCPUGetTscInfo(void);
|
|
|
0a7476 |
+
|
|
|
0a7476 |
#endif /* __VIR_HOSTCPU_H__*/
|
|
|
0a7476 |
--
|
|
|
0a7476 |
2.21.0
|
|
|
0a7476 |
|