All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
@ 2015-10-20  7:39 Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 01/12] KVM: x86: Collect information for setting TSC scaling ratio Haozhong Zhang
                   ` (14 more replies)
  0 siblings, 15 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

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


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v2 01/12] KVM: x86: Collect information for setting TSC scaling ratio
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 02/12] KVM: x86: Add a common TSC scaling ratio field in kvm_vcpu_arch Haozhong Zhang
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 02/12] KVM: x86: Add a common TSC scaling ratio field in kvm_vcpu_arch
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 01/12] KVM: x86: Collect information for setting TSC scaling ratio Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 03/12] KVM: x86: Add a common TSC scaling function Haozhong Zhang
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 03/12] KVM: x86: Add a common TSC scaling function
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 01/12] KVM: x86: Collect information for setting TSC scaling ratio Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 02/12] KVM: x86: Add a common TSC scaling ratio field in kvm_vcpu_arch Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 04/12] KVM: x86: Replace call-back set_tsc_khz() with a common function Haozhong Zhang
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 04/12] KVM: x86: Replace call-back set_tsc_khz() with a common function
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (2 preceding siblings ...)
  2015-10-20  7:39 ` [PATCH v2 03/12] KVM: x86: Add a common TSC scaling function Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 05/12] KVM: x86: Replace call-back compute_tsc_offset() " Haozhong Zhang
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 05/12] KVM: x86: Replace call-back compute_tsc_offset() with a common function
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (3 preceding siblings ...)
  2015-10-20  7:39 ` [PATCH v2 04/12] KVM: x86: Replace call-back set_tsc_khz() with a common function Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 06/12] KVM: x86: Move TSC scaling logic out of call-back adjust_tsc_offset() Haozhong Zhang
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 06/12] KVM: x86: Move TSC scaling logic out of call-back adjust_tsc_offset()
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (4 preceding siblings ...)
  2015-10-20  7:39 ` [PATCH v2 05/12] KVM: x86: Replace call-back compute_tsc_offset() " Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 07/12] KVM: x86: Move TSC scaling logic out of call-back read_l1_tsc() Haozhong Zhang
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 07/12] KVM: x86: Move TSC scaling logic out of call-back read_l1_tsc()
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (5 preceding siblings ...)
  2015-10-20  7:39 ` [PATCH v2 06/12] KVM: x86: Move TSC scaling logic out of call-back adjust_tsc_offset() Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 08/12] KVM: x86: Use the correct vcpu's TSC rate to compute time scale Haozhong Zhang
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

Both VMX and SVM scales the host TSC in the same way in call-back
read_l1_tsc(), so this patch moves the scaling logic from call-back
read_l1_tsc() to a common function kvm_read_l1_tsc().

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
 arch/x86/kvm/lapic.c     |  4 ++--
 arch/x86/kvm/svm.c       |  3 +--
 arch/x86/kvm/x86.c       | 11 ++++++++---
 include/linux/kvm_host.h |  1 +
 4 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 168b875..355a400 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1250,7 +1250,7 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu)
 
 	tsc_deadline = apic->lapic_timer.expired_tscdeadline;
 	apic->lapic_timer.expired_tscdeadline = 0;
-	guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, rdtsc());
+	guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
 	trace_kvm_wait_lapic_expire(vcpu->vcpu_id, guest_tsc - tsc_deadline);
 
 	/* __delay is delay_tsc whenever the hardware has TSC, thus always.  */
@@ -1318,7 +1318,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
 		local_irq_save(flags);
 
 		now = apic->lapic_timer.timer.base->get_time();
-		guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, rdtsc());
+		guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
 		if (likely(tscdeadline > guest_tsc)) {
 			ns = (tscdeadline - guest_tsc) * 1000000ULL;
 			do_div(ns, this_tsc_khz);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 9cfc02a..8e46be1 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2985,8 +2985,7 @@ static int cr8_write_interception(struct vcpu_svm *svm)
 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 +
-		kvm_scale_tsc(vcpu, host_tsc);
+	return vmcb->control.tsc_offset + host_tsc;
 }
 
 static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 75129bd..f2516bf 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1406,6 +1406,12 @@ static u64 kvm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
 	return target_tsc - tsc;
 }
 
+u64 kvm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)
+{
+	return kvm_x86_ops->read_l1_tsc(vcpu, kvm_scale_tsc(vcpu, host_tsc));
+}
+EXPORT_SYMBOL_GPL(kvm_read_l1_tsc);
+
 void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
 {
 	struct kvm *kvm = vcpu->kvm;
@@ -1729,7 +1735,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 		kernel_ns = get_kernel_ns();
 	}
 
-	tsc_timestamp = kvm_x86_ops->read_l1_tsc(v, host_tsc);
+	tsc_timestamp = kvm_read_l1_tsc(v, host_tsc);
 
 	/*
 	 * We may have to catch up the TSC to match elapsed wall clock
@@ -6532,8 +6538,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 	if (hw_breakpoint_active())
 		hw_breakpoint_restore();
 
-	vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu,
-							   rdtsc());
+	vcpu->arch.last_guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
 
 	vcpu->mode = OUTSIDE_GUEST_MODE;
 	smp_wmb();
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 95a6bf2..0d3fd3c 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1185,6 +1185,7 @@ int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq,
 #endif /* CONFIG_HAVE_KVM_IRQ_BYPASS */
 
 u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc);
+u64 kvm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc);
 
 extern struct kvm_x86_ops *kvm_x86_ops;
 
-- 
2.4.8


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 08/12] KVM: x86: Use the correct vcpu's TSC rate to compute time scale
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (6 preceding siblings ...)
  2015-10-20  7:39 ` [PATCH v2 07/12] KVM: x86: Move TSC scaling logic out of call-back read_l1_tsc() Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 09/12] KVM: VMX: Enable and initialize VMX TSC scaling Haozhong Zhang
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

This patch makes KVM use virtual_tsc_khz rather than the host TSC rate
as vcpu's TSC rate to compute the time scale if TSC scaling is enabled.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
 arch/x86/kvm/x86.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f2516bf..d5690a3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1698,7 +1698,7 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)
 
 static int kvm_guest_time_update(struct kvm_vcpu *v)
 {
-	unsigned long flags, this_tsc_khz;
+	unsigned long flags, this_tsc_khz, tgt_tsc_khz;
 	struct kvm_vcpu_arch *vcpu = &v->arch;
 	struct kvm_arch *ka = &v->kvm->arch;
 	s64 kernel_ns;
@@ -1761,7 +1761,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 		return 0;
 
 	if (unlikely(vcpu->hw_tsc_khz != this_tsc_khz)) {
-		kvm_get_time_scale(NSEC_PER_SEC / 1000, this_tsc_khz,
+		tgt_tsc_khz = kvm_has_tsc_control ?
+			vcpu->virtual_tsc_khz : this_tsc_khz;
+		kvm_get_time_scale(NSEC_PER_SEC / 1000, tgt_tsc_khz,
 				   &vcpu->hv_clock.tsc_shift,
 				   &vcpu->hv_clock.tsc_to_system_mul);
 		vcpu->hw_tsc_khz = this_tsc_khz;
-- 
2.4.8


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 09/12] KVM: VMX: Enable and initialize VMX TSC scaling
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (7 preceding siblings ...)
  2015-10-20  7:39 ` [PATCH v2 08/12] KVM: x86: Use the correct vcpu's TSC rate to compute time scale Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 10/12] KVM: VMX: Setup TSC scaling ratio when a vcpu is loaded Haozhong Zhang
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 10/12] KVM: VMX: Setup TSC scaling ratio when a vcpu is loaded
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (8 preceding siblings ...)
  2015-10-20  7:39 ` [PATCH v2 09/12] KVM: VMX: Enable and initialize VMX TSC scaling Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 11/12] KVM: VMX: Use a scaled host TSC for guest readings of MSR_IA32_TSC Haozhong Zhang
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

This patch makes kvm-intel module to load TSC scaling ratio into TSC
multiplier field of VMCS when a vcpu is loaded, so that TSC scaling
ratio can take effect if VMX TSC scaling is enabled.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
 arch/x86/kvm/vmx.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index a86f790..c241ff3 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2062,6 +2062,12 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
 		rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
 		vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
+
+		/* Setup TSC multiplier */
+		if (cpu_has_vmx_tsc_scaling())
+			vmcs_write64(TSC_MULTIPLIER,
+				     vcpu->arch.tsc_scaling_ratio);
+
 		vmx->loaded_vmcs->cpu = cpu;
 	}
 
-- 
2.4.8


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 11/12] KVM: VMX: Use a scaled host TSC for guest readings of MSR_IA32_TSC
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (9 preceding siblings ...)
  2015-10-20  7:39 ` [PATCH v2 10/12] KVM: VMX: Setup TSC scaling ratio when a vcpu is loaded Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-20  7:39 ` [PATCH v2 12/12] KVM: VMX: Dump TSC multiplier in dump_vmcs() Haozhong Zhang
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v2 12/12] KVM: VMX: Dump TSC multiplier in dump_vmcs()
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (10 preceding siblings ...)
  2015-10-20  7:39 ` [PATCH v2 11/12] KVM: VMX: Use a scaled host TSC for guest readings of MSR_IA32_TSC Haozhong Zhang
@ 2015-10-20  7:39 ` Haozhong Zhang
  2015-10-23 10:06 ` [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Joerg Roedel
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-20  7:39 UTC (permalink / raw)
  To: kvm
  Cc: Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong,
	mdontu, Kai Huang, Andy Lutomirski, linux-kernel, Haozhong Zhang

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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (11 preceding siblings ...)
  2015-10-20  7:39 ` [PATCH v2 12/12] KVM: VMX: Dump TSC multiplier in dump_vmcs() Haozhong Zhang
@ 2015-10-23 10:06 ` Joerg Roedel
  2015-10-23 12:32   ` Haozhong Zhang
  2015-10-23 14:31 ` Haozhong Zhang
  2015-11-06 10:49 ` Paolo Bonzini
  14 siblings, 1 reply; 24+ messages in thread
From: Joerg Roedel @ 2015-10-23 10:06 UTC (permalink / raw)
  To: Haozhong Zhang
  Cc: kvm, Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Wanpeng Li, Xiao Guangrong, mdontu,
	Kai Huang, Andy Lutomirski, linux-kernel

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


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-10-23 10:06 ` [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Joerg Roedel
@ 2015-10-23 12:32   ` Haozhong Zhang
  2015-10-23 12:46     ` Joerg Roedel
  0 siblings, 1 reply; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-23 12:32 UTC (permalink / raw)
  To: Joerg Roedel
  Cc: kvm, Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Wanpeng Li, Xiao Guangrong, mdontu,
	Kai Huang, Andy Lutomirski, linux-kernel

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

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-10-23 12:32   ` Haozhong Zhang
@ 2015-10-23 12:46     ` Joerg Roedel
  2015-10-23 12:51       ` Paolo Bonzini
  2015-10-23 12:55       ` Haozhong Zhang
  0 siblings, 2 replies; 24+ messages in thread
From: Joerg Roedel @ 2015-10-23 12:46 UTC (permalink / raw)
  To: kvm, Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Wanpeng Li, Xiao Guangrong, mdontu,
	Kai Huang, Andy Lutomirski, linux-kernel

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

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-10-23 12:46     ` Joerg Roedel
@ 2015-10-23 12:51       ` Paolo Bonzini
  2015-10-23 14:37         ` Haozhong Zhang
  2015-10-23 12:55       ` Haozhong Zhang
  1 sibling, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2015-10-23 12:51 UTC (permalink / raw)
  To: Joerg Roedel, kvm, Gleb Natapov, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Wanpeng Li, Xiao Guangrong, mdontu,
	Kai Huang, Andy Lutomirski, linux-kernel



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

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-10-23 12:46     ` Joerg Roedel
  2015-10-23 12:51       ` Paolo Bonzini
@ 2015-10-23 12:55       ` Haozhong Zhang
  1 sibling, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-23 12:55 UTC (permalink / raw)
  To: Joerg Roedel
  Cc: kvm, Gleb Natapov, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Wanpeng Li, Xiao Guangrong, mdontu,
	Kai Huang, Andy Lutomirski, linux-kernel

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

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (12 preceding siblings ...)
  2015-10-23 10:06 ` [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Joerg Roedel
@ 2015-10-23 14:31 ` Haozhong Zhang
  2015-11-06 10:49 ` Paolo Bonzini
  14 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-23 14:31 UTC (permalink / raw)
  To: kvm, Paolo Bonzini, Joerg Roedel
  Cc: Gleb Natapov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86,
	Joerg Roedel, Wanpeng Li, Xiao Guangrong, mdontu, Kai Huang,
	Andy Lutomirski, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1842 bytes --]

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

[-- Attachment #2: test_tsc.c --]
[-- Type: text/plain, Size: 809 bytes --]

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>

static inline uint64_t rdtsc(void)
{
        uint32_t lo, hi;
        asm volatile("lfence; rdtsc" : "=a" (lo), "=d" (hi));
        return (uint64_t)hi << 32 | lo;
}

int main(int argc, char **argv)
{
        uint64_t tsc0, tsc1;
        int ns, tsc_khz;
        double delta;

        if (argc < 2) {
                printf("Usage: %s <nr_seconds> <tsc_khz>\n", argv[0]);
                return -1;
        }

        if ((ns = atoi(argv[1])) <= 0)
                return -1;
        if ((tsc_khz = atoi(argv[2])) <= 0)
                return -1;

        tsc0 = rdtsc();
        sleep(ns);
        tsc1 = rdtsc();

        delta = tsc1 - tsc0;
        printf("Passed %lf s\n", delta / (tsc_khz * 1000.0));

        return 0;
}

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-10-23 12:51       ` Paolo Bonzini
@ 2015-10-23 14:37         ` Haozhong Zhang
  0 siblings, 0 replies; 24+ messages in thread
From: Haozhong Zhang @ 2015-10-23 14:37 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Joerg Roedel, kvm, Gleb Natapov, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Wanpeng Li, Xiao Guangrong, mdontu,
	Kai Huang, Andy Lutomirski, linux-kernel

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

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
                   ` (13 preceding siblings ...)
  2015-10-23 14:31 ` Haozhong Zhang
@ 2015-11-06 10:49 ` Paolo Bonzini
  2015-11-06 12:42   ` Haozhong Zhang
  14 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2015-11-06 10:49 UTC (permalink / raw)
  To: Haozhong Zhang, kvm
  Cc: Gleb Natapov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86,
	Joerg Roedel, Wanpeng Li, Xiao Guangrong, mdontu, Kai Huang,
	Andy Lutomirski, linux-kernel



On 20/10/2015 09:39, Haozhong Zhang wrote:
> 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>

Thanks for the patches.  There are a couple changes that I can do myself:

1) kvm_default_tsc_scaling_ratio can be initialized in
kvm_arch_hardware_setup, since it's just 1ULL <<
kvm_tsc_scaling_ratio_frac_bits

2) things that you are adding to include/linux/kvm_host.h should instead
go in arch/x86/include/linux/kvm_host.h

That's it.  I'll commit it as soon as I test on AMD (today hopefully).

Paolo

> 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(-)
> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-11-06 10:49 ` Paolo Bonzini
@ 2015-11-06 12:42   ` Haozhong Zhang
  2015-11-06 20:40     ` Paolo Bonzini
  0 siblings, 1 reply; 24+ messages in thread
From: Haozhong Zhang @ 2015-11-06 12:42 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: kvm, Gleb Natapov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong, mdontu, Kai Huang,
	Andy Lutomirski, linux-kernel

On 11/06/15 11:49, Paolo Bonzini wrote:
> 
> 
> On 20/10/2015 09:39, Haozhong Zhang wrote:
> > 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>
> 
> Thanks for the patches.  There are a couple changes that I can do myself:
> 
> 1) kvm_default_tsc_scaling_ratio can be initialized in
> kvm_arch_hardware_setup, since it's just 1ULL <<
> kvm_tsc_scaling_ratio_frac_bits
>
Agree

> 2) things that you are adding to include/linux/kvm_host.h should instead
> go in arch/x86/include/linux/kvm_host.h
>
Agree, because they are x86 specific.

> That's it.  I'll commit it as soon as I test on AMD (today hopefully).
>

Thanks,
Haozhong

> Paolo
> 
> > 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(-)
> > 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-11-06 12:42   ` Haozhong Zhang
@ 2015-11-06 20:40     ` Paolo Bonzini
  2015-11-09  0:06       ` haozhong.zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2015-11-06 20:40 UTC (permalink / raw)
  To: kvm, Gleb Natapov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong, mdontu, Kai Huang,
	Andy Lutomirski, linux-kernel



On 06/11/2015 13:42, Haozhong Zhang wrote:
> On 11/06/15 11:49, Paolo Bonzini wrote:
>>
>>
>> On 20/10/2015 09:39, Haozhong Zhang wrote:
>>> 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>
>>
>> Thanks for the patches.  There are a couple changes that I can do myself:
>>
>> 1) kvm_default_tsc_scaling_ratio can be initialized in
>> kvm_arch_hardware_setup, since it's just 1ULL <<
>> kvm_tsc_scaling_ratio_frac_bits
>>
> Agree
> 
>> 2) things that you are adding to include/linux/kvm_host.h should instead
>> go in arch/x86/include/linux/kvm_host.h
>>
> Agree, because they are x86 specific.
> 
>> That's it.  I'll commit it as soon as I test on AMD (today hopefully).

It tested fine.  I'll give it a shot with the 32-bit mul_u64_u64_shr on
Monday as well, but I don't expect any issue.

Thanks, the patches are neat!

Paolo

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling
  2015-11-06 20:40     ` Paolo Bonzini
@ 2015-11-09  0:06       ` haozhong.zhang
  0 siblings, 0 replies; 24+ messages in thread
From: haozhong.zhang @ 2015-11-09  0:06 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: kvm, Gleb Natapov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	x86, Joerg Roedel, Wanpeng Li, Xiao Guangrong, mdontu, Kai Huang,
	Andy Lutomirski, linux-kernel

On 11/06/15 21:40, Paolo Bonzini wrote:
> 
> 
> On 06/11/2015 13:42, Haozhong Zhang wrote:
> > On 11/06/15 11:49, Paolo Bonzini wrote:
> >>
> >>
> >> On 20/10/2015 09:39, Haozhong Zhang wrote:
> >>> 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>
> >>
> >> Thanks for the patches.  There are a couple changes that I can do myself:
> >>
> >> 1) kvm_default_tsc_scaling_ratio can be initialized in
> >> kvm_arch_hardware_setup, since it's just 1ULL <<
> >> kvm_tsc_scaling_ratio_frac_bits
> >>
> > Agree
> > 
> >> 2) things that you are adding to include/linux/kvm_host.h should instead
> >> go in arch/x86/include/linux/kvm_host.h
> >>
> > Agree, because they are x86 specific.
> > 
> >> That's it.  I'll commit it as soon as I test on AMD (today hopefully).
> 
> It tested fine.  I'll give it a shot with the 32-bit mul_u64_u64_shr on
> Monday as well, but I don't expect any issue.
> 
> Thanks, the patches are neat!
> 
> Paolo

Thank you for the test!

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

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2015-11-09  0:06 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-20  7:39 [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 01/12] KVM: x86: Collect information for setting TSC scaling ratio Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 02/12] KVM: x86: Add a common TSC scaling ratio field in kvm_vcpu_arch Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 03/12] KVM: x86: Add a common TSC scaling function Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 04/12] KVM: x86: Replace call-back set_tsc_khz() with a common function Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 05/12] KVM: x86: Replace call-back compute_tsc_offset() " Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 06/12] KVM: x86: Move TSC scaling logic out of call-back adjust_tsc_offset() Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 07/12] KVM: x86: Move TSC scaling logic out of call-back read_l1_tsc() Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 08/12] KVM: x86: Use the correct vcpu's TSC rate to compute time scale Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 09/12] KVM: VMX: Enable and initialize VMX TSC scaling Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 10/12] KVM: VMX: Setup TSC scaling ratio when a vcpu is loaded Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 11/12] KVM: VMX: Use a scaled host TSC for guest readings of MSR_IA32_TSC Haozhong Zhang
2015-10-20  7:39 ` [PATCH v2 12/12] KVM: VMX: Dump TSC multiplier in dump_vmcs() Haozhong Zhang
2015-10-23 10:06 ` [PATCH v2 00/12] KVM: x86: add support for VMX TSC scaling Joerg Roedel
2015-10-23 12:32   ` Haozhong Zhang
2015-10-23 12:46     ` Joerg Roedel
2015-10-23 12:51       ` Paolo Bonzini
2015-10-23 14:37         ` Haozhong Zhang
2015-10-23 12:55       ` Haozhong Zhang
2015-10-23 14:31 ` Haozhong Zhang
2015-11-06 10:49 ` Paolo Bonzini
2015-11-06 12:42   ` Haozhong Zhang
2015-11-06 20:40     ` Paolo Bonzini
2015-11-09  0:06       ` haozhong.zhang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.