Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1251380 > unrolled thread
| Started by | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| First post | 2015-10-20 09:50 +0200 |
| Last post | 2015-10-23 16:40 +0200 |
| Articles | 17 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-20 09:50 +0200
[PATCH v2 09/12] KVM: VMX: Enable and initialize VMX TSC scaling Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-20 09:50 +0200
[PATCH v2 03/12] KVM: x86: Add a common TSC scaling function Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-20 09:50 +0200
[PATCH v2 02/12] KVM: x86: Add a common TSC scaling ratio field in kvm_vcpu_arch Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-20 09:50 +0200
[PATCH v2 12/12] KVM: VMX: Dump TSC multiplier in dump_vmcs() Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-20 09:50 +0200
[PATCH v2 06/12] KVM: x86: Move TSC scaling logic out of call-back adjust_tsc_offset() Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-20 09:50 +0200
[PATCH v2 11/12] KVM: VMX: Use a scaled host TSC for guest readings of MSR_IA32_TSC Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-20 10:00 +0200
[PATCH v2 01/12] KVM: x86: Collect information for setting TSC scaling ratio Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-20 10:00 +0200
[PATCH v2 05/12] KVM: x86: Replace call-back compute_tsc_offset() with a common function Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-20 10:00 +0200
[PATCH v2 04/12] KVM: x86: Replace call-back set_tsc_khz() with a common function Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-20 10:00 +0200
Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Joerg Roedel <joro@8bytes.org> - 2015-10-23 12:10 +0200
Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-23 14:40 +0200
Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Joerg Roedel <joro@8bytes.org> - 2015-10-23 14:50 +0200
Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Paolo Bonzini <pbonzini@redhat.com> - 2015-10-23 15:00 +0200
Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-23 16:40 +0200
Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-23 15:00 +0200
Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang <haozhong.zhang@intel.com> - 2015-10-23 16:40 +0200
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-20 09:50 +0200 |
| Subject | [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling |
| Message-ID | <qlzQe-5Bb-33@gated-at.bofh.it> |
This patchset adds support for VMX TSC scaling feature which is available on Intel Skylake CPU. The specification of VMX TSC scaling can be found at http://www.intel.com/content/www/us/en/processors/timestamp-counter-scaling-virtualization-white-paper.html VMX TSC scaling allows guest TSC which is read by guest rdtsc(p) instructions increases in a rate that is customized by the hypervisor and can be different than the host TSC rate. Basically, VMX TSC scaling adds a 64-bit field called TSC multiplier in VMCS so that, if VMX TSC scaling is enabled, TSC read by guest rdtsc(p) instructions will be calculated by the following formula: guest EDX:EAX = (Host TSC * TSC multiplier) >> 48 + VMX TSC Offset where, Host TSC = Host MSR_IA32_TSC + Host MSR_IA32_TSC_ADJUST. This patchset, when cooperating with another QEMU patchset (sent in another email "target-i386: save/restore vcpu's TSC rate during migration"), allows guest programs observe a consistent TSC rate even though they are migrated among machines with different host TSC rates. VMX TSC scaling shares some common logics with SVM TSC ratio which is already supported by KVM. Patch 1 ~ 8 move those common logics from SVM code to the common code. Upon them, patch 9 ~ 12 add VMX-specific support for VMX TSC scaling. Changes in v2: * Remove the duplicated variable 'kvm_tsc_scaling_ratio_rsvd'. * Remove an unnecessary error check in original patch 2. * Do 64-bit arithmetic by functions recommended by Paolo. * Make kvm_set_tsc_khz() returns an error number so that ioctl KVM_SET_TSC_KHZ does not return 0 if errors happen. Reviewed-by: Eric Northup <digitaleric@google.com> Haozhong Zhang (12): KVM: x86: Collect information for setting TSC scaling ratio KVM: x86: Add a common TSC scaling ratio field in kvm_vcpu_arch KVM: x86: Add a common TSC scaling function KVM: x86: Replace call-back set_tsc_khz() with a common function KVM: x86: Replace call-back compute_tsc_offset() with a common function KVM: x86: Move TSC scaling logic out of call-back adjust_tsc_offset() KVM: x86: Move TSC scaling logic out of call-back read_l1_tsc() KVM: x86: Use the correct vcpu's TSC rate to compute time scale KVM: VMX: Enable and initialize VMX TSC scaling KVM: VMX: Setup TSC scaling ratio when a vcpu is loaded KVM: VMX: Use a scaled host TSC for guest readings of MSR_IA32_TSC KVM: VMX: Dump TSC multiplier in dump_vmcs() arch/x86/include/asm/kvm_host.h | 24 +++---- arch/x86/include/asm/vmx.h | 3 + arch/x86/kvm/lapic.c | 4 +- arch/x86/kvm/svm.c | 116 ++++------------------------------ arch/x86/kvm/vmx.c | 64 ++++++++++--------- arch/x86/kvm/x86.c | 134 +++++++++++++++++++++++++++++++++++----- include/linux/kvm_host.h | 20 ++++++ include/linux/math64.h | 99 +++++++++++++++++++++++++++++ 8 files changed, 297 insertions(+), 167 deletions(-) -- 2.4.8 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-20 09:50 +0200 |
| Subject | [PATCH v2 09/12] KVM: VMX: Enable and initialize VMX TSC scaling |
| Message-ID | <qlzQf-5Bb-49@gated-at.bofh.it> |
| In reply to | #1251380 |
This patch exhances kvm-intel module to enable VMX TSC scaling and
collects information of TSC scaling ratio during initialization.
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
arch/x86/include/asm/vmx.h | 3 +++
arch/x86/kvm/vmx.c | 19 ++++++++++++++++++-
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index aa336ff..14c63c7 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -73,6 +73,7 @@
#define SECONDARY_EXEC_ENABLE_PML 0x00020000
#define SECONDARY_EXEC_XSAVES 0x00100000
#define SECONDARY_EXEC_PCOMMIT 0x00200000
+#define SECONDARY_EXEC_TSC_SCALING 0x02000000
#define PIN_BASED_EXT_INTR_MASK 0x00000001
#define PIN_BASED_NMI_EXITING 0x00000008
@@ -167,6 +168,8 @@ enum vmcs_field {
VMWRITE_BITMAP = 0x00002028,
XSS_EXIT_BITMAP = 0x0000202C,
XSS_EXIT_BITMAP_HIGH = 0x0000202D,
+ TSC_MULTIPLIER = 0x00002032,
+ TSC_MULTIPLIER_HIGH = 0x00002033,
GUEST_PHYSICAL_ADDRESS = 0x00002400,
GUEST_PHYSICAL_ADDRESS_HIGH = 0x00002401,
VMCS_LINK_POINTER = 0x00002800,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 1f72480..a86f790 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -107,6 +107,9 @@ static u64 __read_mostly host_xss;
static bool __read_mostly enable_pml = 1;
module_param_named(pml, enable_pml, bool, S_IRUGO);
+#define KVM_VMX_TSC_MULTIPLIER_DEFAULT 0x0001000000000000ULL
+#define KVM_VMX_TSC_MULTIPLIER_MAX 0xffffffffffffffffULL
+
#define KVM_GUEST_CR0_MASK (X86_CR0_NW | X86_CR0_CD)
#define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST (X86_CR0_WP | X86_CR0_NE)
#define KVM_VM_CR0_ALWAYS_ON \
@@ -1172,6 +1175,12 @@ static inline bool cpu_has_vmx_pml(void)
return vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_ENABLE_PML;
}
+static inline bool cpu_has_vmx_tsc_scaling(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_TSC_SCALING;
+}
+
static inline bool report_flexpriority(void)
{
return flexpriority_enabled;
@@ -3133,7 +3142,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
SECONDARY_EXEC_SHADOW_VMCS |
SECONDARY_EXEC_XSAVES |
SECONDARY_EXEC_ENABLE_PML |
- SECONDARY_EXEC_PCOMMIT;
+ SECONDARY_EXEC_PCOMMIT |
+ SECONDARY_EXEC_TSC_SCALING;
if (adjust_vmx_controls(min2, opt2,
MSR_IA32_VMX_PROCBASED_CTLS2,
&_cpu_based_2nd_exec_control) < 0)
@@ -6177,6 +6187,13 @@ static __init int hardware_setup(void)
if (!cpu_has_vmx_apicv())
enable_apicv = 0;
+ if (cpu_has_vmx_tsc_scaling()) {
+ kvm_has_tsc_control = true;
+ kvm_max_tsc_scaling_ratio = KVM_VMX_TSC_MULTIPLIER_MAX;
+ kvm_tsc_scaling_ratio_frac_bits = 48;
+ }
+ kvm_default_tsc_scaling_ratio = KVM_VMX_TSC_MULTIPLIER_DEFAULT;
+
if (enable_apicv)
kvm_x86_ops->update_cr8_intercept = NULL;
else {
--
2.4.8
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-20 09:50 +0200 |
| Subject | [PATCH v2 03/12] KVM: x86: Add a common TSC scaling function |
| Message-ID | <qlzQf-5Bb-51@gated-at.bofh.it> |
| In reply to | #1251380 |
VMX and SVM calculate the TSC scaling ratio in a similar logic, so this
patch generalizes it to a common TSC scaling function.
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
arch/x86/kvm/svm.c | 48 +++------------------------------
arch/x86/kvm/x86.c | 45 +++++++++++++++++++++++++++++++
include/linux/kvm_host.h | 3 +++
include/linux/math64.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 122 insertions(+), 44 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 04b58cf..d347170 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -212,7 +212,6 @@ static int nested_svm_intercept(struct vcpu_svm *svm);
static int nested_svm_vmexit(struct vcpu_svm *svm);
static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
bool has_error_code, u32 error_code);
-static u64 __scale_tsc(u64 ratio, u64 tsc);
enum {
VMCB_INTERCEPTS, /* Intercept vectors, TSC offset,
@@ -892,21 +891,7 @@ static __init int svm_hardware_setup(void)
kvm_enable_efer_bits(EFER_FFXSR);
if (boot_cpu_has(X86_FEATURE_TSCRATEMSR)) {
- u64 max;
-
kvm_has_tsc_control = true;
-
- /*
- * Make sure the user can only configure tsc_khz values that
- * fit into a signed integer.
- * A min value is not calculated needed because it will always
- * be 1 on all machines and a value of 0 is used to disable
- * tsc-scaling for the vcpu.
- */
- max = min(0x7fffffffULL, __scale_tsc(tsc_khz, TSC_RATIO_MAX));
-
- kvm_max_guest_tsc_khz = max;
-
kvm_max_tsc_scaling_ratio = TSC_RATIO_MAX;
kvm_tsc_scaling_ratio_frac_bits = 32;
}
@@ -973,31 +958,6 @@ static void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
seg->base = 0;
}
-static u64 __scale_tsc(u64 ratio, u64 tsc)
-{
- u64 mult, frac, _tsc;
-
- mult = ratio >> 32;
- frac = ratio & ((1ULL << 32) - 1);
-
- _tsc = tsc;
- _tsc *= mult;
- _tsc += (tsc >> 32) * frac;
- _tsc += ((tsc & ((1ULL << 32) - 1)) * frac) >> 32;
-
- return _tsc;
-}
-
-static u64 svm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
-{
- u64 _tsc = tsc;
-
- if (vcpu->arch.tsc_scaling_ratio != TSC_RATIO_DEFAULT)
- _tsc = __scale_tsc(vcpu->arch.tsc_scaling_ratio, tsc);
-
- return _tsc;
-}
-
static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
{
u64 ratio;
@@ -1066,7 +1026,7 @@ static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool ho
if (host) {
if (vcpu->arch.tsc_scaling_ratio != TSC_RATIO_DEFAULT)
WARN_ON(adjustment < 0);
- adjustment = svm_scale_tsc(vcpu, (u64)adjustment);
+ adjustment = kvm_scale_tsc(vcpu, (u64)adjustment);
}
svm->vmcb->control.tsc_offset += adjustment;
@@ -1084,7 +1044,7 @@ static u64 svm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
{
u64 tsc;
- tsc = svm_scale_tsc(vcpu, rdtsc());
+ tsc = kvm_scale_tsc(vcpu, rdtsc());
return target_tsc - tsc;
}
@@ -3076,7 +3036,7 @@ static u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)
{
struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu));
return vmcb->control.tsc_offset +
- svm_scale_tsc(vcpu, host_tsc);
+ kvm_scale_tsc(vcpu, host_tsc);
}
static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
@@ -3086,7 +3046,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
switch (msr_info->index) {
case MSR_IA32_TSC: {
msr_info->data = svm->vmcb->control.tsc_offset +
- svm_scale_tsc(vcpu, rdtsc());
+ kvm_scale_tsc(vcpu, rdtsc());
break;
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8849e8b..29c5781 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1328,6 +1328,39 @@ static void update_ia32_tsc_adjust_msr(struct kvm_vcpu *vcpu, s64 offset)
vcpu->arch.ia32_tsc_adjust_msr += offset - curr_offset;
}
+/*
+ * Multiply tsc by a fixed point number represented by ratio.
+ *
+ * The most significant 64-N bits (mult) of ratio represent the
+ * integral part of the fixed point number; the remaining N bits
+ * (frac) represent the fractional part, ie. ratio represents a fixed
+ * point number (mult + frac * 2^(-N)).
+ *
+ * N.B: we always assume not all 64 bits of ratio are used for the
+ * fractional part and the ratio has at least 1 bit for the fractional
+ * part, i.e. 0 < N < 64.
+ *
+ * N equals to kvm_tsc_scaling_ratio_frac_bits.
+ */
+static inline u64 __scale_tsc(u64 ratio, u64 tsc)
+{
+ BUG_ON(kvm_tsc_scaling_ratio_frac_bits >= 64 ||
+ kvm_tsc_scaling_ratio_frac_bits == 0);
+ return mul_u64_u64_shr(tsc, ratio, kvm_tsc_scaling_ratio_frac_bits);
+}
+
+u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
+{
+ u64 _tsc = tsc;
+ u64 ratio = vcpu->arch.tsc_scaling_ratio;
+
+ if (ratio != kvm_default_tsc_scaling_ratio)
+ _tsc = __scale_tsc(ratio, tsc);
+
+ return _tsc;
+}
+EXPORT_SYMBOL_GPL(kvm_scale_tsc);
+
void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
{
struct kvm *kvm = vcpu->kvm;
@@ -7366,6 +7399,18 @@ int kvm_arch_hardware_setup(void)
if (r != 0)
return r;
+ /*
+ * Make sure the user can only configure tsc_khz values that
+ * fit into a signed integer.
+ * A min value is not calculated needed because it will always
+ * be 1 on all machines.
+ */
+ if (kvm_has_tsc_control) {
+ u64 max = min(0x7fffffffULL,
+ __scale_tsc(kvm_max_tsc_scaling_ratio, tsc_khz));
+ kvm_max_guest_tsc_khz = max;
+ }
+
kvm_init_msr_list();
return 0;
}
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index eba9cae..3556148 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1183,4 +1183,7 @@ void kvm_arch_irq_bypass_start(struct irq_bypass_consumer *);
int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq,
uint32_t guest_irq, bool set);
#endif /* CONFIG_HAVE_KVM_IRQ_BYPASS */
+
+u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc);
+
#endif
diff --git a/include/linux/math64.h b/include/linux/math64.h
index c45c089..78aa80b 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -142,6 +142,13 @@ static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
}
#endif /* mul_u64_u32_shr */
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift)
+{
+ return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u64_shr */
+
#else
#ifndef mul_u64_u32_shr
@@ -161,6 +168,69 @@ static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
}
#endif /* mul_u64_u32_shr */
+#ifndef mul64
+static inline void mul64(u64 *lo, u64 *hi, u64 a, u64 b)
+{
+ typedef union {
+ u64 ll;
+ struct {
+#ifdef __BIG_ENDIAN
+ u32 high, low;
+#else
+ u32 low, high;
+#endif
+ } l;
+ } LL;
+ LL rl, rm, rn, rh, a0, b0;
+ u64 c;
+
+ a0.ll = a;
+ b0.ll = b;
+
+ rl.ll = (u64)a0.l.low * b0.l.low;
+ rm.ll = (u64)a0.l.low * b0.l.high;
+ rn.ll = (u64)a0.l.high * b0.l.low;
+ rh.ll = (u64)a0.l.high * b0.l.high;
+
+ c = (u64)rl.l.high + rm.l.low + rn.l.low;
+ rl.l.high = c;
+ c >>= 32;
+ c = c + rm.l.high + rn.l.high + rh.l.low;
+ rh.l.low = c;
+ rh.l.high += (u32)(c >> 32);
+
+ *lo = rl.ll;
+ *hi = rh.ll;
+}
+#endif /* mul64 */
+
+#ifndef rshift128
+static inline void rshift128(u64 *lo, u64 *hi, unsigned int n)
+{
+ u64 h;
+ if (!n)
+ return;
+ h = *hi >> (n & 63);
+ if (n >= 64) {
+ *hi = 0;
+ *lo = h;
+ } else {
+ *lo = (*lo >> n) | (*hi << (64 - n));
+ *hi = h;
+ }
+}
+#endif /* rshift128 */
+
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift)
+{
+ u64 lo, hi;
+ mul64(&lo, &hi, a, mul);
+ rshift128(&lo, &hi, shift);
+ return lo;
+}
+#endif /* mul_u64_u64_shr */
+
#endif
#endif /* _LINUX_MATH64_H */
--
2.4.8
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-20 09:50 +0200 |
| Subject | [PATCH v2 02/12] KVM: x86: Add a common TSC scaling ratio field in kvm_vcpu_arch |
| Message-ID | <qlzQf-5Bb-57@gated-at.bofh.it> |
| In reply to | #1251380 |
This patch moves the field of TSC scaling ratio from the architecture
struct vcpu_svm to the common struct kvm_vcpu_arch.
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
arch/x86/include/asm/kvm_host.h | 1 +
arch/x86/kvm/svm.c | 23 +++++++++--------------
arch/x86/kvm/x86.c | 5 ++++-
3 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 0540dc8..1e08ad5 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -505,6 +505,7 @@ struct kvm_vcpu_arch {
u32 virtual_tsc_mult;
u32 virtual_tsc_khz;
s64 ia32_tsc_adjust_msr;
+ u64 tsc_scaling_ratio;
atomic_t nmi_queued; /* unprocessed asynchronous NMIs */
unsigned nmi_pending; /* NMI queued after currently running handler */
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 55f5f49..04b58cf 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -158,8 +158,6 @@ struct vcpu_svm {
unsigned long int3_rip;
u32 apf_reason;
- u64 tsc_ratio;
-
/* cached guest cpuid flags for faster access */
bool nrips_enabled : 1;
};
@@ -992,24 +990,22 @@ static u64 __scale_tsc(u64 ratio, u64 tsc)
static u64 svm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
{
- struct vcpu_svm *svm = to_svm(vcpu);
u64 _tsc = tsc;
- if (svm->tsc_ratio != TSC_RATIO_DEFAULT)
- _tsc = __scale_tsc(svm->tsc_ratio, tsc);
+ if (vcpu->arch.tsc_scaling_ratio != TSC_RATIO_DEFAULT)
+ _tsc = __scale_tsc(vcpu->arch.tsc_scaling_ratio, tsc);
return _tsc;
}
static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
{
- struct vcpu_svm *svm = to_svm(vcpu);
u64 ratio;
u64 khz;
/* Guest TSC same frequency as host TSC? */
if (!scale) {
- svm->tsc_ratio = TSC_RATIO_DEFAULT;
+ vcpu->arch.tsc_scaling_ratio = TSC_RATIO_DEFAULT;
return;
}
@@ -1034,7 +1030,7 @@ static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
user_tsc_khz);
return;
}
- svm->tsc_ratio = ratio;
+ vcpu->arch.tsc_scaling_ratio = ratio;
}
static u64 svm_read_tsc_offset(struct kvm_vcpu *vcpu)
@@ -1068,7 +1064,7 @@ static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool ho
struct vcpu_svm *svm = to_svm(vcpu);
if (host) {
- if (svm->tsc_ratio != TSC_RATIO_DEFAULT)
+ if (vcpu->arch.tsc_scaling_ratio != TSC_RATIO_DEFAULT)
WARN_ON(adjustment < 0);
adjustment = svm_scale_tsc(vcpu, (u64)adjustment);
}
@@ -1240,8 +1236,6 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
goto out;
}
- svm->tsc_ratio = TSC_RATIO_DEFAULT;
-
err = kvm_vcpu_init(&svm->vcpu, kvm, id);
if (err)
goto free_svm;
@@ -1311,6 +1305,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
int i;
+ u64 tsc_ratio = vcpu->arch.tsc_scaling_ratio;
if (unlikely(cpu != vcpu->cpu)) {
svm->asid_generation = 0;
@@ -1328,9 +1323,9 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
rdmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
if (static_cpu_has(X86_FEATURE_TSCRATEMSR) &&
- svm->tsc_ratio != __this_cpu_read(current_tsc_ratio)) {
- __this_cpu_write(current_tsc_ratio, svm->tsc_ratio);
- wrmsrl(MSR_AMD64_TSC_RATIO, svm->tsc_ratio);
+ tsc_ratio != __this_cpu_read(current_tsc_ratio)) {
+ __this_cpu_write(current_tsc_ratio, tsc_ratio);
+ wrmsrl(MSR_AMD64_TSC_RATIO, tsc_ratio);
}
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 79cbbb5..8849e8b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1258,8 +1258,11 @@ static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
int use_scaling = 0;
/* tsc_khz can be zero if TSC calibration fails */
- if (this_tsc_khz == 0)
+ if (this_tsc_khz == 0) {
+ /* set tsc_scaling_ratio to a safe value */
+ vcpu->arch.tsc_scaling_ratio = kvm_default_tsc_scaling_ratio;
return;
+ }
/* Compute a scale to convert nanoseconds in TSC cycles */
kvm_get_time_scale(this_tsc_khz, NSEC_PER_SEC / 1000,
--
2.4.8
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-20 09:50 +0200 |
| Subject | [PATCH v2 12/12] KVM: VMX: Dump TSC multiplier in dump_vmcs() |
| Message-ID | <qlzQg-5Bb-69@gated-at.bofh.it> |
| In reply to | #1251380 |
This patch enhances dump_vmcs() to dump the value of TSC multiplier
field in VMCS.
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
arch/x86/kvm/vmx.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index a02b59c..66d25be 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -8013,6 +8013,9 @@ static void dump_vmcs(void)
vmcs_read32(IDT_VECTORING_INFO_FIELD),
vmcs_read32(IDT_VECTORING_ERROR_CODE));
pr_err("TSC Offset = 0x%016lx\n", vmcs_readl(TSC_OFFSET));
+ if (secondary_exec_control & SECONDARY_EXEC_TSC_SCALING)
+ pr_err("TSC Multiplier = 0x%016lx\n",
+ vmcs_readl(TSC_MULTIPLIER));
if (cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW)
pr_err("TPR Threshold = 0x%02x\n", vmcs_read32(TPR_THRESHOLD));
if (pin_based_exec_ctrl & PIN_BASED_POSTED_INTR)
--
2.4.8
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-20 09:50 +0200 |
| Subject | [PATCH v2 06/12] KVM: x86: Move TSC scaling logic out of call-back adjust_tsc_offset() |
| Message-ID | <qlzQg-5Bb-75@gated-at.bofh.it> |
| In reply to | #1251380 |
For both VMX and SVM, if the 2nd argument of call-back
adjust_tsc_offset() is the host TSC, then adjust_tsc_offset() will scale
it first. This patch moves this common TSC scaling logic to its caller
adjust_tsc_offset_host() and rename the call-back adjust_tsc_offset() to
adjust_tsc_offset_guest().
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
arch/x86/include/asm/kvm_host.h | 15 +--------------
arch/x86/kvm/svm.c | 10 ++--------
arch/x86/kvm/vmx.c | 4 ++--
include/linux/kvm_host.h | 16 ++++++++++++++++
4 files changed, 21 insertions(+), 24 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d5e820b..b70cebb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -845,7 +845,7 @@ struct kvm_x86_ops {
int (*get_lpage_level)(void);
bool (*rdtscp_supported)(void);
bool (*invpcid_supported)(void);
- void (*adjust_tsc_offset)(struct kvm_vcpu *vcpu, s64 adjustment, bool host);
+ void (*adjust_tsc_offset_guest)(struct kvm_vcpu *vcpu, s64 adjustment);
void (*set_tdp_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
@@ -920,19 +920,6 @@ struct kvm_arch_async_pf {
bool direct_map;
};
-extern struct kvm_x86_ops *kvm_x86_ops;
-
-static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu,
- s64 adjustment)
-{
- kvm_x86_ops->adjust_tsc_offset(vcpu, adjustment, false);
-}
-
-static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment)
-{
- kvm_x86_ops->adjust_tsc_offset(vcpu, adjustment, true);
-}
-
int kvm_mmu_module_init(void);
void kvm_mmu_module_exit(void);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 481fdd3..9cfc02a 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -984,16 +984,10 @@ static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
}
-static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool host)
+static void svm_adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, s64 adjustment)
{
struct vcpu_svm *svm = to_svm(vcpu);
- if (host) {
- if (vcpu->arch.tsc_scaling_ratio != TSC_RATIO_DEFAULT)
- WARN_ON(adjustment < 0);
- adjustment = kvm_scale_tsc(vcpu, (u64)adjustment);
- }
-
svm->vmcb->control.tsc_offset += adjustment;
if (is_guest_mode(vcpu))
svm->nested.hsave->control.tsc_offset += adjustment;
@@ -4361,7 +4355,7 @@ static struct kvm_x86_ops svm_x86_ops = {
.read_tsc_offset = svm_read_tsc_offset,
.write_tsc_offset = svm_write_tsc_offset,
- .adjust_tsc_offset = svm_adjust_tsc_offset,
+ .adjust_tsc_offset_guest = svm_adjust_tsc_offset_guest,
.read_l1_tsc = svm_read_l1_tsc,
.set_tdp_cr3 = set_tdp_cr3,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 7896395..1f72480 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2413,7 +2413,7 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
}
}
-static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool host)
+static void vmx_adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, s64 adjustment)
{
u64 offset = vmcs_read64(TSC_OFFSET);
@@ -10809,7 +10809,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
.read_tsc_offset = vmx_read_tsc_offset,
.write_tsc_offset = vmx_write_tsc_offset,
- .adjust_tsc_offset = vmx_adjust_tsc_offset,
+ .adjust_tsc_offset_guest = vmx_adjust_tsc_offset_guest,
.read_l1_tsc = vmx_read_l1_tsc,
.set_tdp_cr3 = vmx_set_cr3,
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 3556148..95a6bf2 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1186,4 +1186,20 @@ int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq,
u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc);
+extern struct kvm_x86_ops *kvm_x86_ops;
+
+static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu,
+ s64 adjustment)
+{
+ kvm_x86_ops->adjust_tsc_offset_guest(vcpu, adjustment);
+}
+
+static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment)
+{
+ if (vcpu->arch.tsc_scaling_ratio != kvm_default_tsc_scaling_ratio)
+ WARN_ON(adjustment < 0);
+ adjustment = kvm_scale_tsc(vcpu, (u64) adjustment);
+ kvm_x86_ops->adjust_tsc_offset_guest(vcpu, adjustment);
+}
+
#endif
--
2.4.8
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-20 10:00 +0200 |
| Subject | [PATCH v2 11/12] KVM: VMX: Use a scaled host TSC for guest readings of MSR_IA32_TSC |
| Message-ID | <qlzZU-5Mu-3@gated-at.bofh.it> |
| In reply to | #1251380 |
This patch makes kvm-intel to return a scaled host TSC plus the TSC
offset when handling guest readings to MSR_IA32_TSC.
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
arch/x86/kvm/vmx.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index c241ff3..a02b59c 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2372,15 +2372,16 @@ static void setup_msrs(struct vcpu_vmx *vmx)
/*
* reads and returns guest's timestamp counter "register"
- * guest_tsc = host_tsc + tsc_offset -- 21.3
+ * guest_tsc = (host_tsc * tsc multiplier) >> 48 + tsc_offset
+ * -- Intel TSC Scaling for Virtualization White Paper, sec 1.3
*/
-static u64 guest_read_tsc(void)
+static u64 guest_read_tsc(struct kvm_vcpu *vcpu)
{
u64 host_tsc, tsc_offset;
host_tsc = rdtsc();
tsc_offset = vmcs_read64(TSC_OFFSET);
- return host_tsc + tsc_offset;
+ return kvm_scale_tsc(vcpu, host_tsc) + tsc_offset;
}
/*
@@ -2772,7 +2773,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_EFER:
return kvm_get_msr_common(vcpu, msr_info);
case MSR_IA32_TSC:
- msr_info->data = guest_read_tsc();
+ msr_info->data = guest_read_tsc(vcpu);
break;
case MSR_IA32_SYSENTER_CS:
msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
--
2.4.8
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-20 10:00 +0200 |
| Subject | [PATCH v2 01/12] KVM: x86: Collect information for setting TSC scaling ratio |
| Message-ID | <qlzZV-5Mu-23@gated-at.bofh.it> |
| In reply to | #1251380 |
The number of bits of the fractional part of the 64-bit TSC scaling
ratio in VMX and SVM is different. This patch makes the architecture
code to collect the number of fractional bits and other related
information into variables that can be accessed in the common code.
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
arch/x86/include/asm/kvm_host.h | 6 ++++++
arch/x86/kvm/svm.c | 4 ++++
arch/x86/kvm/x86.c | 6 ++++++
3 files changed, 16 insertions(+)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 53deb27..0540dc8 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -990,6 +990,12 @@ extern bool kvm_has_tsc_control;
extern u32 kvm_min_guest_tsc_khz;
/* maximum supported tsc_khz for guests */
extern u32 kvm_max_guest_tsc_khz;
+/* number of bits of the fractional part of the TSC scaling ratio */
+extern u8 kvm_tsc_scaling_ratio_frac_bits;
+/* default TSC scaling ratio (= 1.0) */
+extern u64 kvm_default_tsc_scaling_ratio;
+/* maximum allowed value of TSC scaling ratio */
+extern u64 kvm_max_tsc_scaling_ratio;
enum emulation_result {
EMULATE_DONE, /* no further processing */
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index cd8659c..55f5f49 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -908,7 +908,11 @@ static __init int svm_hardware_setup(void)
max = min(0x7fffffffULL, __scale_tsc(tsc_khz, TSC_RATIO_MAX));
kvm_max_guest_tsc_khz = max;
+
+ kvm_max_tsc_scaling_ratio = TSC_RATIO_MAX;
+ kvm_tsc_scaling_ratio_frac_bits = 32;
}
+ kvm_default_tsc_scaling_ratio = TSC_RATIO_DEFAULT;
if (nested) {
printk(KERN_INFO "kvm: Nested Virtualization enabled\n");
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 9e9c226..79cbbb5 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -109,6 +109,12 @@ bool kvm_has_tsc_control;
EXPORT_SYMBOL_GPL(kvm_has_tsc_control);
u32 kvm_max_guest_tsc_khz;
EXPORT_SYMBOL_GPL(kvm_max_guest_tsc_khz);
+u8 kvm_tsc_scaling_ratio_frac_bits;
+EXPORT_SYMBOL_GPL(kvm_tsc_scaling_ratio_frac_bits);
+u64 kvm_default_tsc_scaling_ratio;
+EXPORT_SYMBOL_GPL(kvm_default_tsc_scaling_ratio);
+u64 kvm_max_tsc_scaling_ratio;
+EXPORT_SYMBOL_GPL(kvm_max_tsc_scaling_ratio);
/* tsc tolerance in parts per million - default to 1/2 of the NTP threshold */
static u32 tsc_tolerance_ppm = 250;
--
2.4.8
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-20 10:00 +0200 |
| Subject | [PATCH v2 05/12] KVM: x86: Replace call-back compute_tsc_offset() with a common function |
| Message-ID | <qlzZV-5Mu-29@gated-at.bofh.it> |
| In reply to | #1251380 |
Both VMX and SVM calculate the tsc-offset in the same way, so this
patch removes the call-back compute_tsc_offset() and replaces it with a
common function kvm_compute_tsc_offset().
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
arch/x86/include/asm/kvm_host.h | 1 -
arch/x86/kvm/svm.c | 10 ----------
arch/x86/kvm/vmx.c | 6 ------
arch/x86/kvm/x86.c | 15 ++++++++++++---
4 files changed, 12 insertions(+), 20 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index c67469b..d5e820b 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -856,7 +856,6 @@ struct kvm_x86_ops {
u64 (*read_tsc_offset)(struct kvm_vcpu *vcpu);
void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
- u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc);
u64 (*read_l1_tsc)(struct kvm_vcpu *vcpu, u64 host_tsc);
void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index a1364927..481fdd3 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1005,15 +1005,6 @@ static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool ho
mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
}
-static u64 svm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
-{
- u64 tsc;
-
- tsc = kvm_scale_tsc(vcpu, rdtsc());
-
- return target_tsc - tsc;
-}
-
static void init_vmcb(struct vcpu_svm *svm, bool init_event)
{
struct vmcb_control_area *control = &svm->vmcb->control;
@@ -4371,7 +4362,6 @@ static struct kvm_x86_ops svm_x86_ops = {
.read_tsc_offset = svm_read_tsc_offset,
.write_tsc_offset = svm_write_tsc_offset,
.adjust_tsc_offset = svm_adjust_tsc_offset,
- .compute_tsc_offset = svm_compute_tsc_offset,
.read_l1_tsc = svm_read_l1_tsc,
.set_tdp_cr3 = set_tdp_cr3,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 7f87cf6..7896395 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2426,11 +2426,6 @@ static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool ho
offset + adjustment);
}
-static u64 vmx_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
-{
- return target_tsc - rdtsc();
-}
-
static bool guest_cpuid_has_vmx(struct kvm_vcpu *vcpu)
{
struct kvm_cpuid_entry2 *best = kvm_find_cpuid_entry(vcpu, 1, 0);
@@ -10815,7 +10810,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
.read_tsc_offset = vmx_read_tsc_offset,
.write_tsc_offset = vmx_write_tsc_offset,
.adjust_tsc_offset = vmx_adjust_tsc_offset,
- .compute_tsc_offset = vmx_compute_tsc_offset,
.read_l1_tsc = vmx_read_l1_tsc,
.set_tdp_cr3 = vmx_set_cr3,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index db5ef73..75129bd 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1397,6 +1397,15 @@ u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
}
EXPORT_SYMBOL_GPL(kvm_scale_tsc);
+static u64 kvm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
+{
+ u64 tsc;
+
+ tsc = kvm_scale_tsc(vcpu, rdtsc());
+
+ return target_tsc - tsc;
+}
+
void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
{
struct kvm *kvm = vcpu->kvm;
@@ -1408,7 +1417,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
u64 data = msr->data;
raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
- offset = kvm_x86_ops->compute_tsc_offset(vcpu, data);
+ offset = kvm_compute_tsc_offset(vcpu, data);
ns = get_kernel_ns();
elapsed = ns - kvm->arch.last_tsc_nsec;
@@ -1465,7 +1474,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
} else {
u64 delta = nsec_to_cycles(vcpu, elapsed);
data += delta;
- offset = kvm_x86_ops->compute_tsc_offset(vcpu, data);
+ offset = kvm_compute_tsc_offset(vcpu, data);
pr_debug("kvm: adjusted tsc offset by %llu\n", delta);
}
matched = true;
@@ -2692,7 +2701,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
if (tsc_delta < 0)
mark_tsc_unstable("KVM discovered backwards TSC");
if (check_tsc_unstable()) {
- u64 offset = kvm_x86_ops->compute_tsc_offset(vcpu,
+ u64 offset = kvm_compute_tsc_offset(vcpu,
vcpu->arch.last_guest_tsc);
kvm_x86_ops->write_tsc_offset(vcpu, offset);
vcpu->arch.tsc_catchup = 1;
--
2.4.8
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-20 10:00 +0200 |
| Subject | [PATCH v2 04/12] KVM: x86: Replace call-back set_tsc_khz() with a common function |
| Message-ID | <qlzZV-5Mu-33@gated-at.bofh.it> |
| In reply to | #1251380 |
Both VMX and SVM propagate virtual_tsc_khz in the same way, so this
patch removes the call-back set_tsc_khz() and replaces it with a common
function.
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
arch/x86/include/asm/kvm_host.h | 1 -
arch/x86/kvm/svm.c | 36 --------------------------------
arch/x86/kvm/vmx.c | 17 ---------------
arch/x86/kvm/x86.c | 46 ++++++++++++++++++++++++++++++++++++-----
include/linux/math64.h | 29 ++++++++++++++++++++++++++
5 files changed, 70 insertions(+), 59 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 1e08ad5..c67469b 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -853,7 +853,6 @@ struct kvm_x86_ops {
bool (*has_wbinvd_exit)(void);
- void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale);
u64 (*read_tsc_offset)(struct kvm_vcpu *vcpu);
void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index d347170..a1364927 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -958,41 +958,6 @@ static void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
seg->base = 0;
}
-static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
-{
- u64 ratio;
- u64 khz;
-
- /* Guest TSC same frequency as host TSC? */
- if (!scale) {
- vcpu->arch.tsc_scaling_ratio = TSC_RATIO_DEFAULT;
- return;
- }
-
- /* TSC scaling supported? */
- if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR)) {
- if (user_tsc_khz > tsc_khz) {
- vcpu->arch.tsc_catchup = 1;
- vcpu->arch.tsc_always_catchup = 1;
- } else
- WARN(1, "user requested TSC rate below hardware speed\n");
- return;
- }
-
- khz = user_tsc_khz;
-
- /* TSC scaling required - calculate ratio */
- ratio = khz << 32;
- do_div(ratio, tsc_khz);
-
- if (ratio == 0 || ratio & TSC_RATIO_RSVD) {
- WARN_ONCE(1, "Invalid TSC ratio - virtual-tsc-khz=%u\n",
- user_tsc_khz);
- return;
- }
- vcpu->arch.tsc_scaling_ratio = ratio;
-}
-
static u64 svm_read_tsc_offset(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -4403,7 +4368,6 @@ static struct kvm_x86_ops svm_x86_ops = {
.has_wbinvd_exit = svm_has_wbinvd_exit,
- .set_tsc_khz = svm_set_tsc_khz,
.read_tsc_offset = svm_read_tsc_offset,
.write_tsc_offset = svm_write_tsc_offset,
.adjust_tsc_offset = svm_adjust_tsc_offset,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 15bff51..7f87cf6 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2382,22 +2382,6 @@ static u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)
return host_tsc + tsc_offset;
}
-/*
- * Engage any workarounds for mis-matched TSC rates. Currently limited to
- * software catchup for faster rates on slower CPUs.
- */
-static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
-{
- if (!scale)
- return;
-
- if (user_tsc_khz > tsc_khz) {
- vcpu->arch.tsc_catchup = 1;
- vcpu->arch.tsc_always_catchup = 1;
- } else
- WARN(1, "user requested TSC rate below hardware speed\n");
-}
-
static u64 vmx_read_tsc_offset(struct kvm_vcpu *vcpu)
{
return vmcs_read64(TSC_OFFSET);
@@ -10828,7 +10812,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
.has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,
- .set_tsc_khz = vmx_set_tsc_khz,
.read_tsc_offset = vmx_read_tsc_offset,
.write_tsc_offset = vmx_write_tsc_offset,
.adjust_tsc_offset = vmx_adjust_tsc_offset,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 29c5781..db5ef73 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1252,7 +1252,43 @@ static u32 adjust_tsc_khz(u32 khz, s32 ppm)
return v;
}
-static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
+static int set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
+{
+ u64 ratio;
+
+ /* Guest TSC same frequency as host TSC? */
+ if (!scale) {
+ vcpu->arch.tsc_scaling_ratio = kvm_default_tsc_scaling_ratio;
+ return 0;
+ }
+
+ /* TSC scaling supported? */
+ if (!kvm_has_tsc_control) {
+ if (user_tsc_khz > tsc_khz) {
+ vcpu->arch.tsc_catchup = 1;
+ vcpu->arch.tsc_always_catchup = 1;
+ return 0;
+ } else {
+ WARN(1, "user requested TSC rate below hardware speed\n");
+ return -1;
+ }
+ }
+
+ /* TSC scaling required - calculate ratio */
+ ratio = mul_u64_u32_div(1ULL << kvm_tsc_scaling_ratio_frac_bits,
+ user_tsc_khz, tsc_khz);
+
+ if (ratio == 0 || ratio >= kvm_max_tsc_scaling_ratio) {
+ WARN_ONCE(1, "Invalid TSC scaling ratio - virtual-tsc-khz=%u\n",
+ user_tsc_khz);
+ return -1;
+ }
+
+ vcpu->arch.tsc_scaling_ratio = ratio;
+ return 0;
+}
+
+static int kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
{
u32 thresh_lo, thresh_hi;
int use_scaling = 0;
@@ -1261,7 +1297,7 @@ static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
if (this_tsc_khz == 0) {
/* set tsc_scaling_ratio to a safe value */
vcpu->arch.tsc_scaling_ratio = kvm_default_tsc_scaling_ratio;
- return;
+ return -1;
}
/* Compute a scale to convert nanoseconds in TSC cycles */
@@ -1282,7 +1318,7 @@ static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
pr_debug("kvm: requested TSC rate %u falls outside tolerance [%u,%u]\n", this_tsc_khz, thresh_lo, thresh_hi);
use_scaling = 1;
}
- kvm_x86_ops->set_tsc_khz(vcpu, this_tsc_khz, use_scaling);
+ return set_tsc_khz(vcpu, this_tsc_khz, use_scaling);
}
static u64 compute_guest_tsc(struct kvm_vcpu *vcpu, s64 kernel_ns)
@@ -3358,9 +3394,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
if (user_tsc_khz == 0)
user_tsc_khz = tsc_khz;
- kvm_set_tsc_khz(vcpu, user_tsc_khz);
+ if (!kvm_set_tsc_khz(vcpu, user_tsc_khz))
+ r = 0;
- r = 0;
goto out;
}
case KVM_GET_TSC_KHZ: {
diff --git a/include/linux/math64.h b/include/linux/math64.h
index 78aa80b..df2279c 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -233,4 +233,33 @@ static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift)
#endif
+#ifndef mul_u64_u32_div
+static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
+{
+ union {
+ u64 ll;
+ struct {
+#ifdef __BIG_ENDIAN
+ u32 high, low;
+#else
+ u32 low, high;
+#endif
+ } l;
+ } u, rl, rh;
+
+ u.ll = a;
+ rl.ll = (u64)u.l.low * mul;
+ rh.ll = (u64)u.l.high * mul + rl.l.high;
+
+ /* Bits 32-63 of the result will be in rh.l.low. */
+ rl.l.high = do_div(rh.ll, divisor);
+
+ /* Bits 0-31 of the result will be in rl.l.low. */
+ do_div(rl.ll, divisor);
+
+ rl.l.high = rh.l.low;
+ return rl.ll;
+}
+#endif /* mul_u64_u32_div */
+
#endif /* _LINUX_MATH64_H */
--
2.4.8
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Joerg Roedel <joro@8bytes.org> |
|---|---|
| Date | 2015-10-23 12:10 +0200 |
| Message-ID | <qmHsm-6Fj-1@gated-at.bofh.it> |
| In reply to | #1251380 |
On Tue, Oct 20, 2015 at 03:39:00PM +0800, Haozhong Zhang wrote: > VMX TSC scaling shares some common logics with SVM TSC ratio which > is already supported by KVM. Patch 1 ~ 8 move those common logics from > SVM code to the common code. Upon them, patch 9 ~ 12 add VMX-specific > support for VMX TSC scaling. Have you tested your changes on an AMD machine too? Joerg -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-23 14:40 +0200 |
| Message-ID | <qmJNw-1va-17@gated-at.bofh.it> |
| In reply to | #1254450 |
On Fri, Oct 23, 2015 at 12:06:50PM +0200, Joerg Roedel wrote: > On Tue, Oct 20, 2015 at 03:39:00PM +0800, Haozhong Zhang wrote: > > VMX TSC scaling shares some common logics with SVM TSC ratio which > > is already supported by KVM. Patch 1 ~ 8 move those common logics from > > SVM code to the common code. Upon them, patch 9 ~ 12 add VMX-specific > > support for VMX TSC scaling. > > Have you tested your changes on an AMD machine too? > > > Joerg > No, since I don't have AMD machines at hand. The modifications to SVM code are mostly lifting common code with VMX TSC scaling code, so it should still work on AMD machines. Haozhong -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Joerg Roedel <joro@8bytes.org> |
|---|---|
| Date | 2015-10-23 14:50 +0200 |
| Message-ID | <qmJXd-1GX-25@gated-at.bofh.it> |
| In reply to | #1254546 |
On Fri, Oct 23, 2015 at 08:32:28PM +0800, Haozhong Zhang wrote: > No, since I don't have AMD machines at hand. The modifications to SVM > code are mostly lifting common code with VMX TSC scaling code, so it > should still work on AMD machines. Well, I think it would be good if you can provide a Tested-by on AMD machines from someone who has one. Or get one yourself when changing AMD specific code, they are not that expensive :) I can do some testing when I am back from my travels, but that will not be before early November. Joerg -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Paolo Bonzini <pbonzini@redhat.com> |
|---|---|
| Date | 2015-10-23 15:00 +0200 |
| Message-ID | <qmK6S-1Sl-7@gated-at.bofh.it> |
| In reply to | #1254571 |
On 23/10/2015 14:46, Joerg Roedel wrote: >> > No, since I don't have AMD machines at hand. The modifications to SVM >> > code are mostly lifting common code with VMX TSC scaling code, so it >> > should still work on AMD machines. > Well, I think it would be good if you can provide a Tested-by on AMD > machines from someone who has one. Or get one yourself when changing AMD > specific code, they are not that expensive :) > I can do some testing when I am back from my travels, but that will not > be before early November. I have one now (mine, not just Red Hat's). :D Paolo -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-23 16:40 +0200 |
| Message-ID | <qmLFE-4cC-9@gated-at.bofh.it> |
| In reply to | #1254576 |
On Fri, Oct 23, 2015 at 02:51:06PM +0200, Paolo Bonzini wrote: > > > On 23/10/2015 14:46, Joerg Roedel wrote: > >> > No, since I don't have AMD machines at hand. The modifications to SVM > >> > code are mostly lifting common code with VMX TSC scaling code, so it > >> > should still work on AMD machines. > > Well, I think it would be good if you can provide a Tested-by on AMD > > machines from someone who has one. Or get one yourself when changing AMD > > specific code, they are not that expensive :) > > I can do some testing when I am back from my travels, but that will not > > be before early November. > > I have one now (mine, not just Red Hat's). :D > > Paolo Hi Paolo, I just posted the test instructions. It would be very appreciated if you can help to test this patchset on AMD machines (two are required). Thanks, Haozhong > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-23 15:00 +0200 |
| Message-ID | <qmK6T-1Sl-23@gated-at.bofh.it> |
| In reply to | #1254571 |
On Fri, Oct 23, 2015 at 02:46:19PM +0200, Joerg Roedel wrote: > On Fri, Oct 23, 2015 at 08:32:28PM +0800, Haozhong Zhang wrote: > > No, since I don't have AMD machines at hand. The modifications to SVM > > code are mostly lifting common code with VMX TSC scaling code, so it > > should still work on AMD machines. > > Well, I think it would be good if you can provide a Tested-by on AMD > machines from someone who has one. Or get one yourself when changing AMD > specific code, they are not that expensive :) > I can do some testing when I am back from my travels, but that will not > be before early November. > > Joerg I'll try to get a test result. And it would be very appreciated if you could test as well. Thanks! Haozhong > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Haozhong Zhang <haozhong.zhang@intel.com> |
|---|---|
| Date | 2015-10-23 16:40 +0200 |
| Message-ID | <qmLFE-4cC-31@gated-at.bofh.it> |
| In reply to | #1251380 |
[Multipart message — attachments visible in raw view] — view raw
Following is how I test this patchset. It should also apply to AMD
machines by replacing Intel with AMD and VMX TSC scaling with SVM TSC
ratio.
* Hardware Requirements
1) Two machines with Intel CPUs, called M_A and M_B below.
2) TSC frequency of CPUs on M_A is different from CPUs on M_B.
Suppose TSC frequency on M_A is f_a KHz.
3) At least CPUs on M_B support VMX TSC scaling.
* Software Requirements
1) Apply this patchset to KVM on both machines.
2) Apply QEMU patches[1] to QEMU commit 40fe17b on both machines
* Test Process
1) Start a linux guest on M_A
qemu-system-x86_64 -enable-kvm -smp 4 -cpu qemu66 -m 512 -hda linux.img
2) In guest linux, check the TSC frequency detected by Linux kernel.
e.g. search in dmeg for messages like
"tsc: Detected XYZ.ABC MHz processor" or
"tsc: Refined TSC clocksource calibration: XYZ.ABC MHz"
3) Start QEMU waiting for migration on M_B:
qemu-system-x86_64 -enable-kvm -smp 4 -cpu qemu64,load-tsc-freq -m 512 -hda linux.img -incoming tcp:0:1234
4) Migrate above VM to M_B as normal in QEMU monitor:
migrate tcp:<M_B's ip>:1234
5) After the migration, if VMX TSC scaling and this patchset work on
M_B, no messages like
"Clocksource tsc unstable (delta = xxxxx ns)"
should appear in dmesg of guest linux
6) Furthermore, users can also check whether guest TSC after the
migration increases in the same rate as before by running the
attached program test_tsc in VM:
./test_tsc N f_a
It measures the number of TSC ticks passed in N seconds, and
divides it by the expected TSC frequency f_a to get the output
result. If this patchset works, the output should be very closed
to N
[1] http://www.spinics.net/lists/kvm/msg122421.html
Thanks,
Haozhong
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web