All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/10] Add VMX TSC scaling support
@ 2016-01-17 21:58 Haozhong Zhang
  2016-01-17 21:58 ` [PATCH v4 01/10] x86/hvm: Scale host TSC when setting/getting guest TSC Haozhong Zhang
                   ` (10 more replies)
  0 siblings, 11 replies; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

This patchset adds support for VMX TSC scaling feature which is
available on Intel Skylake Server 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 frequency. 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.

If the destination host supports VMX TSC scaling, this patchset allows
guest programs in a HVM container in the default TSC mode or PVRDTSCP
(native_paravirt) TSC mode to observe the same TSC frequency across
the migration.

Changes in v4:
 * v3 patch 1&2 have been committed so they are not included in v4.
 * v3 patch 11 "x86/hvm: Detect TSC scaling through hvm_funcs" is merged
   early into v4 patch 4 "x86/hvm: Collect information of TSC scaling ratio".
 * v4 patch 1 - 8 correspond to v3 patch 3 - 10.
   v4 patch 9 - 10 correspond to v3 patch 12 - 13.
 * Other changes are logged in each patch respectively.

Changes in v3:
 * v2 patch 1&2 have been merged so they do not appear in v3.
 * Patch 1 - 6 correspond to v2 patch 3 - 8. Patch 7 is new.
   Patch 8 - 13 correspond to v2 patch 9 - 14.
 * Other changes are logged in each patch respectively.

Changes in v2:
 * Remove unnecessary v1 patch 1&13.
 * Add and move all bug-fix patches to the beginning of this series.
   (Patch 1 - 6)
 * Update changes in tsc_set_info() and tsc_get_info() to make both
   functions consistent with each other. (Patch 2 - 4)
 * Move a part of scaling logic out of [vmx|svm]_set_tsc_offset().
   (Patch 7)
 * Remove redundant hvm_funcs.tsc_scaling_ratio_rsvd. (Patch 8)
 * Reimplement functions that calculate TSC ratio and scale TSC.
   (Patch 9&10)
 * Merge setting VMX TSC multiplier into patch 13.
 * Move initialing tsc_scaling_ratio in VMX ahead to
   vmx_vcpu_initialise() so as to make construct_vmcs() naturally
   use this field instead of a constant. (Patch 13)
 * Update documents related to tsc_mode.
 * Other code cleanup and style fixes.

Haozhong Zhang (10):
  x86/hvm: Scale host TSC when setting/getting guest TSC
  x86/time.c: Scale host TSC in pvclock properly
  svm: Remove redundant TSC scaling in svm_set_tsc_offset()
  x86/hvm: Collect information of TSC scaling ratio
  x86: Add functions for 64-bit integer arithmetic
  x86/hvm: Setup TSC scaling ratio
  x86/hvm: Replace architecture TSC scaling by a common function
  x86/hvm: Move saving/loading vcpu's TSC to common code
  vmx: Add VMX RDTSC(P) scaling support
  docs: Add descriptions of TSC scaling in xl.cfg and tscmode.txt

 docs/man/xl.cfg.pod.5              | 14 +++++++-
 docs/misc/tscmode.txt              | 21 ++++++++++++
 xen/arch/x86/hvm/hvm.c             | 69 ++++++++++++++++++++++++++++++++------
 xen/arch/x86/hvm/svm/svm.c         | 36 +++++++++-----------
 xen/arch/x86/hvm/vmx/vmcs.c        | 12 +++++--
 xen/arch/x86/hvm/vmx/vmx.c         | 25 +++++++++++---
 xen/arch/x86/time.c                | 38 ++++++++++++++++-----
 xen/include/asm-x86/hvm/hvm.h      | 20 +++++++++++
 xen/include/asm-x86/hvm/svm/svm.h  |  3 --
 xen/include/asm-x86/hvm/vcpu.h     |  2 ++
 xen/include/asm-x86/hvm/vmx/vmcs.h |  7 ++++
 xen/include/asm-x86/math64.h       | 47 ++++++++++++++++++++++++++
 12 files changed, 242 insertions(+), 52 deletions(-)
 create mode 100644 xen/include/asm-x86/math64.h

-- 
2.7.0

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

* [PATCH v4 01/10] x86/hvm: Scale host TSC when setting/getting guest TSC
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
@ 2016-01-17 21:58 ` Haozhong Zhang
  2016-01-18 13:39   ` Jan Beulich
  2016-01-17 21:58 ` [PATCH v4 02/10] x86/time.c: Scale host TSC in pvclock properly Haozhong Zhang
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

The existing hvm_[set|get]_guest_tsc_fixed() calculate the guest TSC by
adding the TSC offset to the host TSC. When the TSC scaling is enabled,
the host TSC should be scaled first. This patch adds the scaling logic
to those two functions.

Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
Changes in v4:
 (addressing Jan Beulich's comments)
 * Remove redundant check of cpu_has_tsc_ratio in svm_scale_tsc().
 * Move check of d->arch.vtsc in svm_scale_tsc() to callers.

 xen/arch/x86/hvm/hvm.c        | 17 +++++++----------
 xen/arch/x86/hvm/svm/svm.c    |  9 +++++++++
 xen/include/asm-x86/hvm/hvm.h |  2 ++
 3 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 21470ec..3648a44 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -60,6 +60,7 @@
 #include <asm/hvm/nestedhvm.h>
 #include <asm/hvm/event.h>
 #include <asm/hvm/vmx/vmx.h>
+#include <asm/hvm/svm/svm.h> /* for cpu_has_tsc_ratio */
 #include <asm/altp2m.h>
 #include <asm/mtrr.h>
 #include <asm/apic.h>
@@ -310,13 +311,11 @@ void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc)
         tsc = hvm_get_guest_time_fixed(v, at_tsc);
         tsc = gtime_to_gtsc(v->domain, tsc);
     }
-    else if ( at_tsc )
-    {
-        tsc = at_tsc;
-    }
     else
     {
-        tsc = rdtsc();
+        tsc = at_tsc ?: rdtsc();
+        if ( cpu_has_tsc_ratio )
+            tsc = hvm_funcs.scale_tsc(v, tsc);
     }
 
     delta_tsc = guest_tsc - tsc;
@@ -344,13 +343,11 @@ u64 hvm_get_guest_tsc_fixed(struct vcpu *v, uint64_t at_tsc)
         tsc = hvm_get_guest_time_fixed(v, at_tsc);
         tsc = gtime_to_gtsc(v->domain, tsc);
     }
-    else if ( at_tsc )
-    {
-        tsc = at_tsc;
-    }
     else
     {
-        tsc = rdtsc();
+        tsc = at_tsc ?: rdtsc();
+        if ( cpu_has_tsc_ratio )
+            tsc = hvm_funcs.scale_tsc(v, tsc);
     }
 
     return tsc + v->arch.hvm_vcpu.cache_tsc_offset;
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index a66d854..a46bc98 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -804,6 +804,13 @@ static uint64_t scale_tsc(uint64_t host_tsc, uint64_t ratio)
     return scaled_host_tsc;
 }
 
+static uint64_t svm_scale_tsc(const struct vcpu *v, uint64_t tsc)
+{
+    ASSERT(cpu_has_tsc_ratio && !v->domain->arch.vtsc);
+
+    return scale_tsc(tsc, vcpu_tsc_ratio(v));
+}
+
 static uint64_t svm_get_tsc_offset(uint64_t host_tsc, uint64_t guest_tsc,
     uint64_t ratio)
 {
@@ -2272,6 +2279,8 @@ static struct hvm_function_table __initdata svm_function_table = {
     .nhvm_vmcx_hap_enabled = nsvm_vmcb_hap_enabled,
     .nhvm_intr_blocked = nsvm_intr_blocked,
     .nhvm_hap_walk_L1_p2m = nsvm_hap_walk_L1_p2m,
+
+    .scale_tsc            = svm_scale_tsc,
 };
 
 void svm_vmexit_handler(struct cpu_user_regs *regs)
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index b9d893d..a87224b 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -212,6 +212,8 @@ struct hvm_function_table {
     void (*altp2m_vcpu_update_vmfunc_ve)(struct vcpu *v);
     bool_t (*altp2m_vcpu_emulate_ve)(struct vcpu *v);
     int (*altp2m_vcpu_emulate_vmfunc)(struct cpu_user_regs *regs);
+
+    uint64_t (*scale_tsc)(const struct vcpu *v, uint64_t tsc);
 };
 
 extern struct hvm_function_table hvm_funcs;
-- 
2.7.0

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

* [PATCH v4 02/10] x86/time.c: Scale host TSC in pvclock properly
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
  2016-01-17 21:58 ` [PATCH v4 01/10] x86/hvm: Scale host TSC when setting/getting guest TSC Haozhong Zhang
@ 2016-01-17 21:58 ` Haozhong Zhang
  2016-01-18 13:42   ` Jan Beulich
  2016-01-17 21:58 ` [PATCH v4 03/10] svm: Remove redundant TSC scaling in svm_set_tsc_offset() Haozhong Zhang
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

This patch makes the pvclock return the scaled host TSC and
corresponding scaling parameters to HVM domains if guest TSC is not
emulated and TSC scaling is enabled.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
Changes in v4:
 (addressing Jan Beulich's comments)
 * Remove unnecessary cast (u8) in __update_vcpu_system_time().

 xen/arch/x86/time.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index ec3f33e..988403a 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -815,10 +815,18 @@ static void __update_vcpu_system_time(struct vcpu *v, int force)
     }
     else
     {
-        tsc_stamp = t->local_tsc_stamp;
-
-        _u.tsc_to_system_mul = t->tsc_scale.mul_frac;
-        _u.tsc_shift         = (s8)t->tsc_scale.shift;
+        if ( has_hvm_container_domain(d) && cpu_has_tsc_ratio )
+        {
+            tsc_stamp            = hvm_funcs.scale_tsc(v, t->local_tsc_stamp);
+            _u.tsc_to_system_mul = d->arch.vtsc_to_ns.mul_frac;
+            _u.tsc_shift         = d->arch.vtsc_to_ns.shift;
+        }
+        else
+        {
+            tsc_stamp            = t->local_tsc_stamp;
+            _u.tsc_to_system_mul = t->tsc_scale.mul_frac;
+            _u.tsc_shift         = t->tsc_scale.shift;
+        }
     }
 
     _u.tsc_timestamp = tsc_stamp;
-- 
2.7.0

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

* [PATCH v4 03/10] svm: Remove redundant TSC scaling in svm_set_tsc_offset()
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
  2016-01-17 21:58 ` [PATCH v4 01/10] x86/hvm: Scale host TSC when setting/getting guest TSC Haozhong Zhang
  2016-01-17 21:58 ` [PATCH v4 02/10] x86/time.c: Scale host TSC in pvclock properly Haozhong Zhang
@ 2016-01-17 21:58 ` Haozhong Zhang
  2016-01-17 21:58 ` [PATCH v4 04/10] x86/hvm: Collect information of TSC scaling ratio Haozhong Zhang
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

Now every caller passes an already scaled offset to
svm_set_tsc_offset(), so it's not necessary to recalculate a scaled TSC
offset in svm_set_tsc_offset().

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
Changes in v4:
 (addressing Jan Beulich's comments)
 * Fix code style.

 xen/arch/x86/hvm/svm/svm.c | 20 +++++---------------
 1 file changed, 5 insertions(+), 15 deletions(-)

diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index a46bc98..953e0b5 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -823,19 +823,6 @@ static void svm_set_tsc_offset(struct vcpu *v, u64 offset, u64 at_tsc)
     struct vmcb_struct *n1vmcb, *n2vmcb;
     uint64_t n2_tsc_offset = 0;
     struct domain *d = v->domain;
-    uint64_t host_tsc, guest_tsc;
-
-    guest_tsc = hvm_get_guest_tsc_fixed(v, at_tsc);
-
-    /* Re-adjust the offset value when TSC_RATIO is available */
-    if ( cpu_has_tsc_ratio && !d->arch.vtsc )
-    {
-        if ( at_tsc )
-            host_tsc = at_tsc;
-        else
-            host_tsc = rdtsc();
-        offset = svm_get_tsc_offset(host_tsc, guest_tsc, vcpu_tsc_ratio(v));
-    }
 
     if ( !nestedhvm_enabled(d) ) {
         vmcb_set_tsc_offset(vmcb, offset);
@@ -849,10 +836,13 @@ static void svm_set_tsc_offset(struct vcpu *v, u64 offset, u64 at_tsc)
         struct nestedsvm *svm = &vcpu_nestedsvm(v);
 
         n2_tsc_offset = vmcb_get_tsc_offset(n2vmcb) -
-            vmcb_get_tsc_offset(n1vmcb);
+                        vmcb_get_tsc_offset(n1vmcb);
         if ( svm->ns_tscratio != DEFAULT_TSC_RATIO ) {
+            uint64_t guest_tsc = hvm_get_guest_tsc_fixed(v, at_tsc);
+
             n2_tsc_offset = svm_get_tsc_offset(guest_tsc,
-                guest_tsc + n2_tsc_offset, svm->ns_tscratio);
+                                               guest_tsc + n2_tsc_offset,
+                                               svm->ns_tscratio);
         }
         vmcb_set_tsc_offset(n1vmcb, offset);
     }
-- 
2.7.0

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

* [PATCH v4 04/10] x86/hvm: Collect information of TSC scaling ratio
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
                   ` (2 preceding siblings ...)
  2016-01-17 21:58 ` [PATCH v4 03/10] svm: Remove redundant TSC scaling in svm_set_tsc_offset() Haozhong Zhang
@ 2016-01-17 21:58 ` Haozhong Zhang
  2016-01-18 10:45   ` Egger, Christoph
  2016-02-05 11:41   ` Jan Beulich
  2016-01-17 21:58 ` [PATCH v4 05/10] x86: Add functions for 64-bit integer arithmetic Haozhong Zhang
                   ` (6 subsequent siblings)
  10 siblings, 2 replies; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

Both VMX TSC scaling and SVM TSC ratio use the 64-bit TSC scaling ratio,
but the number of fractional bits of the ratio is different between VMX
and SVM. This patch adds the architecture code to collect the number of
fractional bits and other related information into fields of struct
hvm_function_table so that they can be used in the common code.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
Changes in v4:
 (addressing Jan Beulich's comments in v3 patch 12)
 * Set TSC scaling parameters in hvm_funcs conditionally.
 * Remove TSC scaling parameter tsc_scaling_supported in hvm_funcs which
   can be derived from other parameters.
 (code cleanup)
 * Merge with v3 patch 11 "x86/hvm: Detect TSC scaling through hvm_funcs"
   whose work can be done early in this patch.

 xen/arch/x86/hvm/hvm.c        |  4 ++--
 xen/arch/x86/hvm/svm/svm.c    | 10 ++++++++--
 xen/arch/x86/time.c           |  9 ++++-----
 xen/include/asm-x86/hvm/hvm.h | 14 ++++++++++++++
 4 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 3648a44..6d30d8b 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -314,7 +314,7 @@ void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc)
     else
     {
         tsc = at_tsc ?: rdtsc();
-        if ( cpu_has_tsc_ratio )
+        if ( hvm_tsc_scaling_supported )
             tsc = hvm_funcs.scale_tsc(v, tsc);
     }
 
@@ -346,7 +346,7 @@ u64 hvm_get_guest_tsc_fixed(struct vcpu *v, uint64_t at_tsc)
     else
     {
         tsc = at_tsc ?: rdtsc();
-        if ( cpu_has_tsc_ratio )
+        if ( hvm_tsc_scaling_supported )
             tsc = hvm_funcs.scale_tsc(v, tsc);
     }
 
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 953e0b5..8b316a0 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1450,6 +1450,14 @@ const struct hvm_function_table * __init start_svm(void)
     if ( !cpu_has_svm_nrips )
         clear_bit(SVM_FEATURE_DECODEASSISTS, &svm_feature_flags);
 
+    if ( cpu_has_tsc_ratio )
+    {
+        svm_function_table.default_tsc_scaling_ratio = DEFAULT_TSC_RATIO;
+        svm_function_table.max_tsc_scaling_ratio = ~TSC_RATIO_RSVD_BITS;
+        svm_function_table.tsc_scaling_ratio_frac_bits = 32;
+        svm_function_table.scale_tsc = svm_scale_tsc;
+    }
+
 #define P(p,s) if ( p ) { printk(" - %s\n", s); printed = 1; }
     P(cpu_has_svm_npt, "Nested Page Tables (NPT)");
     P(cpu_has_svm_lbrv, "Last Branch Record (LBR) Virtualisation");
@@ -2269,8 +2277,6 @@ static struct hvm_function_table __initdata svm_function_table = {
     .nhvm_vmcx_hap_enabled = nsvm_vmcb_hap_enabled,
     .nhvm_intr_blocked = nsvm_intr_blocked,
     .nhvm_hap_walk_L1_p2m = nsvm_hap_walk_L1_p2m,
-
-    .scale_tsc            = svm_scale_tsc,
 };
 
 void svm_vmexit_handler(struct cpu_user_regs *regs)
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index 988403a..a243bc3 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -37,7 +37,6 @@
 #include <asm/hpet.h>
 #include <io_ports.h>
 #include <asm/setup.h> /* for early_time_init */
-#include <asm/hvm/svm/svm.h> /* for cpu_has_tsc_ratio */
 #include <public/arch-x86/cpuid.h>
 
 /* opt_clocksource: Force clocksource to one of: pit, hpet, acpi. */
@@ -815,7 +814,7 @@ static void __update_vcpu_system_time(struct vcpu *v, int force)
     }
     else
     {
-        if ( has_hvm_container_domain(d) && cpu_has_tsc_ratio )
+        if ( has_hvm_container_domain(d) && hvm_tsc_scaling_supported )
         {
             tsc_stamp            = hvm_funcs.scale_tsc(v, t->local_tsc_stamp);
             _u.tsc_to_system_mul = d->arch.vtsc_to_ns.mul_frac;
@@ -1758,7 +1757,7 @@ void tsc_get_info(struct domain *d, uint32_t *tsc_mode,
                   uint32_t *incarnation)
 {
     bool_t enable_tsc_scaling = has_hvm_container_domain(d) &&
-                                cpu_has_tsc_ratio && !d->arch.vtsc;
+                                hvm_tsc_scaling_supported && !d->arch.vtsc;
 
     *incarnation = d->arch.incarnation;
     *tsc_mode = d->arch.tsc_mode;
@@ -1865,7 +1864,7 @@ void tsc_set_info(struct domain *d,
          */
         if ( tsc_mode == TSC_MODE_DEFAULT && host_tsc_is_safe() &&
              (has_hvm_container_domain(d) ?
-              d->arch.tsc_khz == cpu_khz || cpu_has_tsc_ratio :
+              d->arch.tsc_khz == cpu_khz || hvm_tsc_scaling_supported :
               incarnation == 0) )
         {
     case TSC_MODE_NEVER_EMULATE:
@@ -1879,7 +1878,7 @@ void tsc_set_info(struct domain *d,
         d->arch.vtsc = !boot_cpu_has(X86_FEATURE_RDTSCP) ||
                        !host_tsc_is_safe();
         enable_tsc_scaling = has_hvm_container_domain(d) &&
-                             cpu_has_tsc_ratio && !d->arch.vtsc;
+                             hvm_tsc_scaling_supported && !d->arch.vtsc;
         d->arch.tsc_khz = (enable_tsc_scaling && gtsc_khz) ? gtsc_khz : cpu_khz;
         set_time_scale(&d->arch.vtsc_to_ns, d->arch.tsc_khz * 1000 );
         d->arch.ns_to_vtsc = scale_reciprocal(d->arch.vtsc_to_ns);
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index a87224b..79ea59e 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -100,6 +100,17 @@ struct hvm_function_table {
     unsigned int hap_capabilities;
 
     /*
+     * Parameters of hardware-assisted TSC scaling, which are valid only when
+     * the hardware feature is available.
+     */
+    /* number of bits of the fractional part of TSC scaling ratio */
+    uint8_t  tsc_scaling_ratio_frac_bits;
+    /* default TSC scaling ratio (no scaling) */
+    uint64_t default_tsc_scaling_ratio;
+    /* maximum-allowed TSC scaling ratio */
+    uint64_t max_tsc_scaling_ratio;
+
+    /*
      * Initialise/destroy HVM domain/vcpu resources
      */
     int  (*domain_initialise)(struct domain *d);
@@ -213,6 +224,7 @@ struct hvm_function_table {
     bool_t (*altp2m_vcpu_emulate_ve)(struct vcpu *v);
     int (*altp2m_vcpu_emulate_vmfunc)(struct cpu_user_regs *regs);
 
+    /* Valid only when hardware-assisted TSC scaling is available */
     uint64_t (*scale_tsc)(const struct vcpu *v, uint64_t tsc);
 };
 
@@ -249,6 +261,8 @@ void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc);
 u64 hvm_get_guest_tsc_fixed(struct vcpu *v, u64 at_tsc);
 #define hvm_get_guest_tsc(v) hvm_get_guest_tsc_fixed(v, 0)
 
+#define hvm_tsc_scaling_supported (!!hvm_funcs.default_tsc_scaling_ratio)
+
 int hvm_set_mode(struct vcpu *v, int mode);
 void hvm_init_guest_time(struct domain *d);
 void hvm_set_guest_time(struct vcpu *v, u64 guest_time);
-- 
2.7.0

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

* [PATCH v4 05/10] x86: Add functions for 64-bit integer arithmetic
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
                   ` (3 preceding siblings ...)
  2016-01-17 21:58 ` [PATCH v4 04/10] x86/hvm: Collect information of TSC scaling ratio Haozhong Zhang
@ 2016-01-17 21:58 ` Haozhong Zhang
  2016-02-05 13:36   ` Jan Beulich
  2016-01-17 21:58 ` [PATCH v4 06/10] x86/hvm: Setup TSC scaling ratio Haozhong Zhang
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

This patch adds several functions to take multiplication, division and
shifting involving 64-bit integers.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
Changes in v4:
 (addressing Jan Beulich's comments)
 * Rewrite mul_u64_u64_shr() in assembly.

 xen/include/asm-x86/math64.h | 47 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 xen/include/asm-x86/math64.h

diff --git a/xen/include/asm-x86/math64.h b/xen/include/asm-x86/math64.h
new file mode 100644
index 0000000..2ddec62
--- /dev/null
+++ b/xen/include/asm-x86/math64.h
@@ -0,0 +1,47 @@
+#ifndef __X86_MATH64
+#define __X86_MATH64
+
+/*
+ * (a * mul) / divisor
+ *
+ * This function is derived from Linux kernel
+ * (mul_u64_u32_div() in include/linux/math64.h)
+ */
+static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
+{
+    union {
+        u64 ll;
+        struct {
+            u32 low, high;
+        } 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;
+}
+
+/*
+ * (a * mul) >> n
+ */
+static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int n)
+{
+    u64 hi, lo;
+
+    asm volatile ( "mulq %2; shrdq %1,%0"
+                   : "=a" (lo), "=d" (hi)
+                   : "rm" (mul), "0" (a), "c" (n) );
+
+    return lo;
+}
+
+#endif
-- 
2.7.0

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

* [PATCH v4 06/10] x86/hvm: Setup TSC scaling ratio
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
                   ` (4 preceding siblings ...)
  2016-01-17 21:58 ` [PATCH v4 05/10] x86: Add functions for 64-bit integer arithmetic Haozhong Zhang
@ 2016-01-17 21:58 ` Haozhong Zhang
  2016-02-05 13:54   ` Jan Beulich
  2016-01-17 21:58 ` [PATCH v4 07/10] x86/hvm: Replace architecture TSC scaling by a common function Haozhong Zhang
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

This patch adds a field tsc_scaling_ratio in struct hvm_vcpu to
record the TSC scaling ratio, and sets it up when tsc_set_info() is
called for a vcpu or when a vcpu is restored or reset.

Before applying the TSC scaling ratio to CPU, we check its validity in
tsc_set_info(). If an invalid ratio is given, we will leave the default
value in tsc_scaling_ratio (i.e. ratio = 1) and setup guest TSC as if no
TSC scaling is used:
* For TSC_MODE_FAULT,
  - if a user-specified TSC frequency is given, we will set the guest
    TSC frequency to it; otherwise, we set it to the host TSC frequency.
  - if guest TSC frequency does not equal to host TSC frequency, we will
    emulate guest TSC (i.e. d->arch.vtsc is set to 1). In both cases,
    guest TSC runs in the guest TSC frequency.
* For TSC_MODE_PVRDTSCP,
  - we set the guest TSC frequency to the host TSC frequency.
  - guest rdtsc is executed natively in the host TSC frequency as
    before.
  - if rdtscp is not available to guest, it will be emulated; otherwise,
    it will be executed natively. In both cases, guest rdtscp gets TSC
    in the host TSC frequency as before.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
Changes in v4:
 (addressing Boris Ostrovsky's comments)
 * Factor out common code in hvm_validate_tsc_scaling_ratio() and
   hvm_setup_tsc_scaling()
   - replace bool_t hvm_validate_tsc_scaling_ratio(u32 gtsc_khz) with
     u64 hvm_get_tsc_scaling_ratio(u32 gtsc_khz) which returns 0 if TSC 
     scaling is not available or gtsc_khz is bogus.
 (addressing Jan Beulich's comments) 
 * Move adding setup_tsc_scaling in hvm_funcs to patch 9 where it is
   first used.

 xen/arch/x86/hvm/hvm.c            | 35 +++++++++++++++++++++++++++++++++++
 xen/arch/x86/hvm/svm/svm.c        |  6 ++++--
 xen/arch/x86/time.c               | 19 ++++++++++++++++---
 xen/include/asm-x86/hvm/hvm.h     |  3 +++
 xen/include/asm-x86/hvm/svm/svm.h |  3 ---
 xen/include/asm-x86/hvm/vcpu.h    |  2 ++
 6 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 6d30d8b..64a7760 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -65,6 +65,7 @@
 #include <asm/mtrr.h>
 #include <asm/apic.h>
 #include <asm/vm_event.h>
+#include <asm/math64.h>
 #include <public/sched.h>
 #include <public/hvm/ioreq.h>
 #include <public/version.h>
@@ -301,6 +302,34 @@ int hvm_set_guest_pat(struct vcpu *v, u64 guest_pat)
     return 1;
 }
 
+/*
+ * Get the ratio to scale host TSC frequency to gtsc_khz. zero will be
+ * returned if TSC scaling is unavailable or ratio cannot be handled
+ * by host CPU. Otherwise, a non-zero ratio will be returned.
+ */
+u64 hvm_get_tsc_scaling_ratio(u32 gtsc_khz)
+{
+    u64 ratio;
+
+    if ( !hvm_tsc_scaling_supported )
+        return 0;
+
+    /*
+     * The multiplication of the first two terms may overflow a 64-bit
+     * integer, so use mul_u64_u32_div() instead to keep precision.
+     */
+    ratio = mul_u64_u32_div(1ULL << hvm_funcs.tsc_scaling_ratio_frac_bits,
+                            gtsc_khz, cpu_khz);
+
+    return ratio > hvm_funcs.max_tsc_scaling_ratio ? 0 : ratio;
+}
+
+void hvm_setup_tsc_scaling(struct vcpu *v)
+{
+    v->arch.hvm_vcpu.tsc_scaling_ratio =
+        hvm_get_tsc_scaling_ratio(v->domain->arch.tsc_khz);
+}
+
 void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc)
 {
     uint64_t tsc;
@@ -2026,6 +2055,9 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
     if ( hvm_funcs.load_cpu_ctxt(v, &ctxt) < 0 )
         return -EINVAL;
 
+    if ( hvm_tsc_scaling_supported && !d->arch.vtsc )
+        hvm_setup_tsc_scaling(v);
+
     v->arch.hvm_vcpu.msr_tsc_aux = ctxt.msr_tsc_aux;
 
     seg.limit = ctxt.idtr_limit;
@@ -5504,6 +5536,9 @@ void hvm_vcpu_reset_state(struct vcpu *v, uint16_t cs, uint16_t ip)
     hvm_set_segment_register(v, x86_seg_gdtr, &reg);
     hvm_set_segment_register(v, x86_seg_idtr, &reg);
 
+    if ( hvm_tsc_scaling_supported && !d->arch.vtsc )
+        hvm_setup_tsc_scaling(v);
+
     /* Sync AP's TSC with BSP's. */
     v->arch.hvm_vcpu.cache_tsc_offset =
         v->domain->vcpu[0]->arch.hvm_vcpu.cache_tsc_offset;
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 8b316a0..17bce5c 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -808,7 +808,7 @@ static uint64_t svm_scale_tsc(const struct vcpu *v, uint64_t tsc)
 {
     ASSERT(cpu_has_tsc_ratio && !v->domain->arch.vtsc);
 
-    return scale_tsc(tsc, vcpu_tsc_ratio(v));
+    return scale_tsc(tsc, v->arch.hvm_vcpu.tsc_scaling_ratio);
 }
 
 static uint64_t svm_get_tsc_offset(uint64_t host_tsc, uint64_t guest_tsc,
@@ -985,7 +985,7 @@ static inline void svm_tsc_ratio_save(struct vcpu *v)
 static inline void svm_tsc_ratio_load(struct vcpu *v)
 {
     if ( cpu_has_tsc_ratio && !v->domain->arch.vtsc ) 
-        wrmsrl(MSR_AMD64_TSC_RATIO, vcpu_tsc_ratio(v));
+        wrmsrl(MSR_AMD64_TSC_RATIO, v->arch.hvm_vcpu.tsc_scaling_ratio);
 }
 
 static void svm_ctxt_switch_from(struct vcpu *v)
@@ -1192,6 +1192,8 @@ static int svm_vcpu_initialise(struct vcpu *v)
 
     svm_guest_osvw_init(v);
 
+    v->arch.hvm_vcpu.tsc_scaling_ratio = DEFAULT_TSC_RATIO;
+
     return 0;
 }
 
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index a243bc3..2ce6447 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -1864,7 +1864,8 @@ void tsc_set_info(struct domain *d,
          */
         if ( tsc_mode == TSC_MODE_DEFAULT && host_tsc_is_safe() &&
              (has_hvm_container_domain(d) ?
-              d->arch.tsc_khz == cpu_khz || hvm_tsc_scaling_supported :
+              (d->arch.tsc_khz == cpu_khz ||
+               hvm_get_tsc_scaling_ratio(d->arch.tsc_khz)) :
               incarnation == 0) )
         {
     case TSC_MODE_NEVER_EMULATE:
@@ -1878,7 +1879,8 @@ void tsc_set_info(struct domain *d,
         d->arch.vtsc = !boot_cpu_has(X86_FEATURE_RDTSCP) ||
                        !host_tsc_is_safe();
         enable_tsc_scaling = has_hvm_container_domain(d) &&
-                             hvm_tsc_scaling_supported && !d->arch.vtsc;
+                             !d->arch.vtsc &&
+                             hvm_get_tsc_scaling_ratio(gtsc_khz ?: cpu_khz);
         d->arch.tsc_khz = (enable_tsc_scaling && gtsc_khz) ? gtsc_khz : cpu_khz;
         set_time_scale(&d->arch.vtsc_to_ns, d->arch.tsc_khz * 1000 );
         d->arch.ns_to_vtsc = scale_reciprocal(d->arch.vtsc_to_ns);
@@ -1897,9 +1899,20 @@ void tsc_set_info(struct domain *d,
     if ( has_hvm_container_domain(d) )
     {
         hvm_set_rdtsc_exiting(d, d->arch.vtsc);
-        if ( d->vcpu && d->vcpu[0] && incarnation == 0 )
+        if ( d->vcpu && d->vcpu[0] )
         {
             /*
+             * TSC scaling ratio on BSP is set here during domain
+             * creation, while the same TSC scaling ratio on APs will
+             * be set in hvm_vcpu_reset_state().
+             */
+            if ( hvm_tsc_scaling_supported && !d->arch.vtsc )
+                hvm_setup_tsc_scaling(d->vcpu[0]);
+
+            if ( incarnation )
+                return;
+
+            /*
              * set_tsc_offset() is called from hvm_vcpu_initialise() before
              * tsc_set_info(). New vtsc mode may require recomputing TSC
              * offset.
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 79ea59e..f2d1419 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -263,6 +263,9 @@ u64 hvm_get_guest_tsc_fixed(struct vcpu *v, u64 at_tsc);
 
 #define hvm_tsc_scaling_supported (!!hvm_funcs.default_tsc_scaling_ratio)
 
+u64 hvm_get_tsc_scaling_ratio(u32 gtsc_khz);
+void hvm_setup_tsc_scaling(struct vcpu *v);
+
 int hvm_set_mode(struct vcpu *v, int mode);
 void hvm_init_guest_time(struct domain *d);
 void hvm_set_guest_time(struct vcpu *v, u64 guest_time);
diff --git a/xen/include/asm-x86/hvm/svm/svm.h b/xen/include/asm-x86/hvm/svm/svm.h
index d60ec23..c954b7e 100644
--- a/xen/include/asm-x86/hvm/svm/svm.h
+++ b/xen/include/asm-x86/hvm/svm/svm.h
@@ -97,9 +97,6 @@ extern u32 svm_feature_flags;
 /* TSC rate */
 #define DEFAULT_TSC_RATIO       0x0000000100000000ULL
 #define TSC_RATIO_RSVD_BITS     0xffffff0000000000ULL
-#define TSC_RATIO(g_khz, h_khz) ( (((u64)(g_khz)<<32)/(u64)(h_khz)) & \
-                                  ~TSC_RATIO_RSVD_BITS )
-#define vcpu_tsc_ratio(v)       TSC_RATIO((v)->domain->arch.tsc_khz, cpu_khz)
 
 extern void svm_host_osvw_reset(void);
 extern void svm_host_osvw_init(void);
diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
index 152d9f3..901c988 100644
--- a/xen/include/asm-x86/hvm/vcpu.h
+++ b/xen/include/asm-x86/hvm/vcpu.h
@@ -175,6 +175,8 @@ struct hvm_vcpu {
     u64                 msr_tsc_adjust;
     u64                 msr_xss;
 
+    u64                 tsc_scaling_ratio;
+
     union {
         struct arch_vmx_struct vmx;
         struct arch_svm_struct svm;
-- 
2.7.0

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

* [PATCH v4 07/10] x86/hvm: Replace architecture TSC scaling by a common function
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
                   ` (5 preceding siblings ...)
  2016-01-17 21:58 ` [PATCH v4 06/10] x86/hvm: Setup TSC scaling ratio Haozhong Zhang
@ 2016-01-17 21:58 ` Haozhong Zhang
  2016-01-17 21:58 ` [PATCH v4 08/10] x86/hvm: Move saving/loading vcpu's TSC to common code Haozhong Zhang
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

This patch implements a common function hvm_scale_tsc() to scale TSC by
using TSC scaling information collected by architecture code.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com> (except the mul64 part)
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/hvm/hvm.c        | 14 ++++++++++++--
 xen/arch/x86/hvm/svm/svm.c    |  8 --------
 xen/arch/x86/time.c           |  2 +-
 xen/include/asm-x86/hvm/hvm.h |  4 +---
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 64a7760..8549dab 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -302,6 +302,16 @@ int hvm_set_guest_pat(struct vcpu *v, u64 guest_pat)
     return 1;
 }
 
+u64 hvm_scale_tsc(const struct vcpu *v, u64 tsc)
+{
+    u64 ratio = v->arch.hvm_vcpu.tsc_scaling_ratio;
+
+    if ( ratio == hvm_funcs.default_tsc_scaling_ratio )
+        return tsc;
+
+    return mul_u64_u64_shr(tsc, ratio, hvm_funcs.tsc_scaling_ratio_frac_bits);
+}
+
 /*
  * Get the ratio to scale host TSC frequency to gtsc_khz. zero will be
  * returned if TSC scaling is unavailable or ratio cannot be handled
@@ -344,7 +354,7 @@ void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc)
     {
         tsc = at_tsc ?: rdtsc();
         if ( hvm_tsc_scaling_supported )
-            tsc = hvm_funcs.scale_tsc(v, tsc);
+            tsc = hvm_scale_tsc(v, tsc);
     }
 
     delta_tsc = guest_tsc - tsc;
@@ -376,7 +386,7 @@ u64 hvm_get_guest_tsc_fixed(struct vcpu *v, uint64_t at_tsc)
     {
         tsc = at_tsc ?: rdtsc();
         if ( hvm_tsc_scaling_supported )
-            tsc = hvm_funcs.scale_tsc(v, tsc);
+            tsc = hvm_scale_tsc(v, tsc);
     }
 
     return tsc + v->arch.hvm_vcpu.cache_tsc_offset;
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 17bce5c..a4ac38c 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -804,13 +804,6 @@ static uint64_t scale_tsc(uint64_t host_tsc, uint64_t ratio)
     return scaled_host_tsc;
 }
 
-static uint64_t svm_scale_tsc(const struct vcpu *v, uint64_t tsc)
-{
-    ASSERT(cpu_has_tsc_ratio && !v->domain->arch.vtsc);
-
-    return scale_tsc(tsc, v->arch.hvm_vcpu.tsc_scaling_ratio);
-}
-
 static uint64_t svm_get_tsc_offset(uint64_t host_tsc, uint64_t guest_tsc,
     uint64_t ratio)
 {
@@ -1457,7 +1450,6 @@ const struct hvm_function_table * __init start_svm(void)
         svm_function_table.default_tsc_scaling_ratio = DEFAULT_TSC_RATIO;
         svm_function_table.max_tsc_scaling_ratio = ~TSC_RATIO_RSVD_BITS;
         svm_function_table.tsc_scaling_ratio_frac_bits = 32;
-        svm_function_table.scale_tsc = svm_scale_tsc;
     }
 
 #define P(p,s) if ( p ) { printk(" - %s\n", s); printed = 1; }
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index 2ce6447..b4a6708 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -816,7 +816,7 @@ static void __update_vcpu_system_time(struct vcpu *v, int force)
     {
         if ( has_hvm_container_domain(d) && hvm_tsc_scaling_supported )
         {
-            tsc_stamp            = hvm_funcs.scale_tsc(v, t->local_tsc_stamp);
+            tsc_stamp            = hvm_scale_tsc(v, t->local_tsc_stamp);
             _u.tsc_to_system_mul = d->arch.vtsc_to_ns.mul_frac;
             _u.tsc_shift         = d->arch.vtsc_to_ns.shift;
         }
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index f2d1419..5588b92 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -223,9 +223,6 @@ struct hvm_function_table {
     void (*altp2m_vcpu_update_vmfunc_ve)(struct vcpu *v);
     bool_t (*altp2m_vcpu_emulate_ve)(struct vcpu *v);
     int (*altp2m_vcpu_emulate_vmfunc)(struct cpu_user_regs *regs);
-
-    /* Valid only when hardware-assisted TSC scaling is available */
-    uint64_t (*scale_tsc)(const struct vcpu *v, uint64_t tsc);
 };
 
 extern struct hvm_function_table hvm_funcs;
@@ -263,6 +260,7 @@ u64 hvm_get_guest_tsc_fixed(struct vcpu *v, u64 at_tsc);
 
 #define hvm_tsc_scaling_supported (!!hvm_funcs.default_tsc_scaling_ratio)
 
+u64 hvm_scale_tsc(const struct vcpu *v, u64 tsc);
 u64 hvm_get_tsc_scaling_ratio(u32 gtsc_khz);
 void hvm_setup_tsc_scaling(struct vcpu *v);
 
-- 
2.7.0

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

* [PATCH v4 08/10] x86/hvm: Move saving/loading vcpu's TSC to common code
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
                   ` (6 preceding siblings ...)
  2016-01-17 21:58 ` [PATCH v4 07/10] x86/hvm: Replace architecture TSC scaling by a common function Haozhong Zhang
@ 2016-01-17 21:58 ` Haozhong Zhang
  2016-01-17 21:58 ` [PATCH v4 09/10] vmx: Add VMX RDTSC(P) scaling support Haozhong Zhang
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

Both VMX and SVM save/load vcpu's TSC when saving/loading vcpu's
context, so this patch moves saving/loading vcpu's TSC to the common
functions hvm_[save|load]_cpu_ctxt().

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
 xen/arch/x86/hvm/hvm.c     | 4 ++++
 xen/arch/x86/hvm/svm/svm.c | 5 -----
 xen/arch/x86/hvm/vmx/vmx.c | 5 -----
 3 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 8549dab..ddc60a7 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -1774,6 +1774,8 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
         /* Architecture-specific vmcs/vmcb bits */
         hvm_funcs.save_cpu_ctxt(v, &ctxt);
 
+        ctxt.tsc = hvm_get_guest_tsc_fixed(v, d->arch.hvm_domain.sync_tsc);
+
         ctxt.msr_tsc_aux = hvm_msr_tsc_aux(v);
 
         hvm_get_segment_register(v, x86_seg_idtr, &seg);
@@ -2070,6 +2072,8 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
 
     v->arch.hvm_vcpu.msr_tsc_aux = ctxt.msr_tsc_aux;
 
+    hvm_set_guest_tsc_fixed(v, ctxt.tsc, d->arch.hvm_domain.sync_tsc);
+
     seg.limit = ctxt.idtr_limit;
     seg.base = ctxt.idtr_base;
     hvm_set_segment_register(v, x86_seg_idtr, &seg);
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index a4ac38c..bc8843a 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -357,9 +357,6 @@ static void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
     data->msr_syscall_mask = vmcb->sfmask;
     data->msr_efer         = v->arch.hvm_vcpu.guest_efer;
     data->msr_flags        = -1ULL;
-
-    data->tsc = hvm_get_guest_tsc_fixed(v,
-                                        v->domain->arch.hvm_domain.sync_tsc);
 }
 
 
@@ -374,8 +371,6 @@ static void svm_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
     vmcb->sfmask     = data->msr_syscall_mask;
     v->arch.hvm_vcpu.guest_efer = data->msr_efer;
     svm_update_guest_efer(v);
-
-    hvm_set_guest_tsc_fixed(v, data->tsc, v->domain->arch.hvm_domain.sync_tsc);
 }
 
 static void svm_save_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt)
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 7917fb7..6285689 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -587,9 +587,6 @@ static void vmx_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
     data->msr_lstar        = guest_state->msrs[VMX_INDEX_MSR_LSTAR];
     data->msr_star         = guest_state->msrs[VMX_INDEX_MSR_STAR];
     data->msr_syscall_mask = guest_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK];
-
-    data->tsc = hvm_get_guest_tsc_fixed(v,
-                                        v->domain->arch.hvm_domain.sync_tsc);
 }
 
 static void vmx_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
@@ -604,8 +601,6 @@ static void vmx_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
 
     v->arch.hvm_vmx.cstar     = data->msr_cstar;
     v->arch.hvm_vmx.shadow_gs = data->shadow_gs;
-
-    hvm_set_guest_tsc_fixed(v, data->tsc, v->domain->arch.hvm_domain.sync_tsc);
 }
 
 
-- 
2.7.0

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

* [PATCH v4 09/10] vmx: Add VMX RDTSC(P) scaling support
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
                   ` (7 preceding siblings ...)
  2016-01-17 21:58 ` [PATCH v4 08/10] x86/hvm: Move saving/loading vcpu's TSC to common code Haozhong Zhang
@ 2016-01-17 21:58 ` Haozhong Zhang
  2016-01-19  2:55   ` [RESEND PATCH " Haozhong Zhang
  2016-01-17 21:58 ` [PATCH v4 10/10] docs: Add descriptions of TSC scaling in xl.cfg and tscmode.txt Haozhong Zhang
  2016-02-01  5:50 ` [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
  10 siblings, 1 reply; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

This patch adds the initialization and setup code for VMX TSC scaling.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Acked-by: Kevin Tian <kevin.tian@intel.com>
---
Changes in v4:
 (addressing Jan Beulich's comments)
 * Set TSC scaling parameters in hvm_funcs conditionally.

 xen/arch/x86/hvm/hvm.c             |  3 +++
 xen/arch/x86/hvm/vmx/vmcs.c        | 12 +++++++++---
 xen/arch/x86/hvm/vmx/vmx.c         | 20 ++++++++++++++++++++
 xen/include/asm-x86/hvm/hvm.h      |  3 +++
 xen/include/asm-x86/hvm/vmx/vmcs.h |  7 +++++++
 5 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ddc60a7..2469a5e 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -338,6 +338,9 @@ void hvm_setup_tsc_scaling(struct vcpu *v)
 {
     v->arch.hvm_vcpu.tsc_scaling_ratio =
         hvm_get_tsc_scaling_ratio(v->domain->arch.tsc_khz);
+
+    if ( hvm_funcs.setup_tsc_scaling )
+        hvm_funcs.setup_tsc_scaling(v);
 }
 
 void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc)
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index edd4c8d..8f16c3a 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -149,6 +149,7 @@ static void __init vmx_display_features(void)
     P(cpu_has_vmx_vmfunc, "VM Functions");
     P(cpu_has_vmx_virt_exceptions, "Virtualisation Exceptions");
     P(cpu_has_vmx_pml, "Page Modification Logging");
+    P(cpu_has_vmx_tsc_scaling, "TSC Scaling");
 #undef P
 
     if ( !printed )
@@ -242,7 +243,8 @@ static int vmx_init_vmcs_config(void)
                SECONDARY_EXEC_ENABLE_INVPCID |
                SECONDARY_EXEC_ENABLE_VM_FUNCTIONS |
                SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS |
-               SECONDARY_EXEC_XSAVES);
+               SECONDARY_EXEC_XSAVES |
+               SECONDARY_EXEC_TSC_SCALING);
         rdmsrl(MSR_IA32_VMX_MISC, _vmx_misc_cap);
         if ( _vmx_misc_cap & VMX_MISC_VMWRITE_ALL )
             opt |= SECONDARY_EXEC_ENABLE_VMCS_SHADOWING;
@@ -999,7 +1001,7 @@ static int construct_vmcs(struct vcpu *v)
     __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
 
     v->arch.hvm_vmx.exec_control = vmx_cpu_based_exec_control;
-    if ( d->arch.vtsc )
+    if ( d->arch.vtsc && !cpu_has_vmx_tsc_scaling )
         v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING;
 
     v->arch.hvm_vmx.secondary_exec_control = vmx_secondary_exec_control;
@@ -1281,6 +1283,9 @@ static int construct_vmcs(struct vcpu *v)
     if ( cpu_has_vmx_xsaves )
         __vmwrite(XSS_EXIT_BITMAP, 0);
 
+    if ( cpu_has_vmx_tsc_scaling )
+        __vmwrite(TSC_MULTIPLIER, v->arch.hvm_vcpu.tsc_scaling_ratio);
+
     vmx_vmcs_exit(v);
 
     /* PVH: paging mode is updated by arch_set_info_guest(). */
@@ -1863,7 +1868,8 @@ void vmcs_dump_vcpu(struct vcpu *v)
            vmr32(VM_EXIT_REASON), vmr(EXIT_QUALIFICATION));
     printk("IDTVectoring: info=%08x errcode=%08x\n",
            vmr32(IDT_VECTORING_INFO), vmr32(IDT_VECTORING_ERROR_CODE));
-    printk("TSC Offset = 0x%016lx\n", vmr(TSC_OFFSET));
+    printk("TSC Offset = 0x%016lx  TSC Multiplier = 0x%016lx\n",
+           vmr(TSC_OFFSET), vmr(TSC_MULTIPLIER));
     if ( (v->arch.hvm_vmx.exec_control & CPU_BASED_TPR_SHADOW) ||
          (vmx_pin_based_exec_control & PIN_BASED_POSTED_INTERRUPT) )
         printk("TPR Threshold = 0x%02x  PostedIntrVec = 0x%02x\n",
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 6285689..fa12782 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -115,6 +115,7 @@ static int vmx_vcpu_initialise(struct vcpu *v)
     v->arch.schedule_tail    = vmx_do_resume;
     v->arch.ctxt_switch_from = vmx_ctxt_switch_from;
     v->arch.ctxt_switch_to   = vmx_ctxt_switch_to;
+    v->arch.hvm_vcpu.tsc_scaling_ratio = VMX_TSC_MULTIPLIER_DEFAULT;
 
     if ( (rc = vmx_create_vmcs(v)) != 0 )
     {
@@ -1105,6 +1106,13 @@ static void vmx_handle_cd(struct vcpu *v, unsigned long value)
     }
 }
 
+static void vmx_setup_tsc_scaling(struct vcpu *v)
+{
+    vmx_vmcs_enter(v);
+    __vmwrite(TSC_MULTIPLIER, v->arch.hvm_vcpu.tsc_scaling_ratio);
+    vmx_vmcs_exit(v);
+}
+
 static void vmx_set_tsc_offset(struct vcpu *v, u64 offset, u64 at_tsc)
 {
     vmx_vmcs_enter(v);
@@ -2003,6 +2011,10 @@ static struct hvm_function_table __initdata vmx_function_table = {
     .altp2m_vcpu_update_vmfunc_ve = vmx_vcpu_update_vmfunc_ve,
     .altp2m_vcpu_emulate_ve = vmx_vcpu_emulate_ve,
     .altp2m_vcpu_emulate_vmfunc = vmx_vcpu_emulate_vmfunc,
+    .default_tsc_scaling_ratio   = VMX_TSC_MULTIPLIER_DEFAULT,
+    .max_tsc_scaling_ratio       = VMX_TSC_MULTIPLIER_MAX,
+    .tsc_scaling_ratio_frac_bits = 48,
+    .setup_tsc_scaling           = vmx_setup_tsc_scaling,
 };
 
 /* Handle VT-d posted-interrupt when VCPU is running. */
@@ -2107,6 +2119,14 @@ const struct hvm_function_table * __init start_vmx(void)
          && cpu_has_vmx_secondary_exec_control )
         vmx_function_table.pvh_supported = 1;
 
+    if ( cpu_has_vmx_tsc_scaling )
+    {
+        vmx_function_table.default_tsc_scaling_ratio = VMX_TSC_MULTIPLIER_DEFAULT;
+        vmx_function_table.max_tsc_scaling_ratio = VMX_TSC_MULTIPLIER_MAX;
+        vmx_function_table.tsc_scaling_ratio_frac_bits = 48;
+        vmx_function_table.setup_tsc_scaling = vmx_setup_tsc_scaling;
+    }
+
     setup_vmcs_dump();
 
     return &vmx_function_table;
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 5588b92..10b9457 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -223,6 +223,9 @@ struct hvm_function_table {
     void (*altp2m_vcpu_update_vmfunc_ve)(struct vcpu *v);
     bool_t (*altp2m_vcpu_emulate_ve)(struct vcpu *v);
     int (*altp2m_vcpu_emulate_vmfunc)(struct cpu_user_regs *regs);
+
+    /* Architecture function to setup TSC scaling ratio */
+    void (*setup_tsc_scaling)(struct vcpu *v);
 };
 
 extern struct hvm_function_table hvm_funcs;
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h
index d1496b8..fdece44 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -236,6 +236,7 @@ extern u32 vmx_vmentry_control;
 #define SECONDARY_EXEC_ENABLE_PML               0x00020000
 #define SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS   0x00040000
 #define SECONDARY_EXEC_XSAVES                   0x00100000
+#define SECONDARY_EXEC_TSC_SCALING              0x02000000
 extern u32 vmx_secondary_exec_control;
 
 #define VMX_EPT_EXEC_ONLY_SUPPORTED                         0x00000001
@@ -258,6 +259,9 @@ extern u64 vmx_ept_vpid_cap;
 #define VMX_MISC_CR3_TARGET                     0x01ff0000
 #define VMX_MISC_VMWRITE_ALL                    0x20000000
 
+#define VMX_TSC_MULTIPLIER_DEFAULT              0x0001000000000000ULL
+#define VMX_TSC_MULTIPLIER_MAX                  0xffffffffffffffffULL
+
 #define cpu_has_wbinvd_exiting \
     (vmx_secondary_exec_control & SECONDARY_EXEC_WBINVD_EXITING)
 #define cpu_has_vmx_virtualize_apic_accesses \
@@ -303,6 +307,8 @@ extern u64 vmx_ept_vpid_cap;
     (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_PML)
 #define cpu_has_vmx_xsaves \
     (vmx_secondary_exec_control & SECONDARY_EXEC_XSAVES)
+#define cpu_has_vmx_tsc_scaling \
+    (vmx_secondary_exec_control & SECONDARY_EXEC_TSC_SCALING)
 
 #define VMCS_RID_TYPE_MASK              0x80000000
 
@@ -378,6 +384,7 @@ enum vmcs_field {
     VMWRITE_BITMAP                  = 0x00002028,
     VIRT_EXCEPTION_INFO             = 0x0000202a,
     XSS_EXIT_BITMAP                 = 0x0000202c,
+    TSC_MULTIPLIER                  = 0x00002032,
     GUEST_PHYSICAL_ADDRESS          = 0x00002400,
     VMCS_LINK_POINTER               = 0x00002800,
     GUEST_IA32_DEBUGCTL             = 0x00002802,
-- 
2.7.0

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

* [PATCH v4 10/10] docs: Add descriptions of TSC scaling in xl.cfg and tscmode.txt
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
                   ` (8 preceding siblings ...)
  2016-01-17 21:58 ` [PATCH v4 09/10] vmx: Add VMX RDTSC(P) scaling support Haozhong Zhang
@ 2016-01-17 21:58 ` Haozhong Zhang
  2016-02-01  5:50 ` [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
  10 siblings, 0 replies; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-17 21:58 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Haozhong Zhang, Keir Fraser, Suravee Suthikulpanit,
	Andrew Cooper, Aravind Gopalakrishnan, Jun Nakajima

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
 docs/man/xl.cfg.pod.5 | 14 +++++++++++++-
 docs/misc/tscmode.txt | 21 +++++++++++++++++++++
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index 8899f75..47aea0a 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -1313,9 +1313,17 @@ deprecated. Options are:
 
 =item B<"default">
 
-Guest rdtsc/p executed natively when monotonicity can be guaranteed
+Guest rdtsc/p is executed natively when monotonicity can be guaranteed
 and emulated otherwise (with frequency scaled if necessary).
 
+If a HVM container in B<default> TSC mode is created on a host that
+provides constant host TSC, its guest TSC frequency will be the same
+as the host. If it is later migrated to another host that provide
+constant host TSC and supports Intel VMX TSC scaling/AMD SVM TSC
+ratio, its guest TSC frequency will be the same before and after
+migration, and guest rdtsc/p will be executed natively as well after
+migration.
+
 =item B<"always_emulate">
 
 Guest rdtsc/p always emulated at 1GHz (kernel and user). Guest rdtsc/p
@@ -1337,6 +1345,10 @@ determine when a restore/migration has occurred and assumes guest
 obtains/uses pvclock-like mechanism to adjust for monotonicity and
 frequency changes.
 
+If a HVM container in B<native_paravirt> TSC mode can execute both guest
+rdtsc and guest rdtscp natively, then the guest TSC frequency will be
+determined in the similar way to that of B<default> TSC mode.
+
 =back
 
 Please see F<docs/misc/tscmode.txt> for more information on this option.
diff --git a/docs/misc/tscmode.txt b/docs/misc/tscmode.txt
index e8c84e8..01ee060 100644
--- a/docs/misc/tscmode.txt
+++ b/docs/misc/tscmode.txt
@@ -297,3 +297,24 @@ and also much faster than nearly all OS-provided time mechanisms.
 While pvrtscp is too complex for most apps, certain enterprise
 TSC-sensitive high-TSC-frequency apps may find it useful to
 obtain a significant performance gain.
+
+Hardware TSC Scaling
+
+Intel VMX TSC scaling and AMD SVM TSC ratio allow the guest TSC read
+by guest rdtsc/p increasing in a different frequency than the host
+TSC frequency.
+
+If a HVM container in default TSC mode (tsc_mode=0) or PVRDTSCP mode
+(tsc_mode=3) is created on a host that provides constant TSC, its
+guest TSC frequency will be the same as the host. If it is later
+migrated to another host that provides constant TSC and supports Intel
+VMX TSC scaling/AMD SVM TSC ratio, its guest TSC frequency will be the
+same before and after migration.
+
+For above HVM container in default TSC mode (tsc_mode=0), if above
+hosts support rdtscp, both guest rdtsc and rdtscp instructions will be
+executed natively before and after migration.
+
+For above HVM container in PVRDTSCP mode (tsc_mode=3), if the
+destination host does not support rdtscp, the guest rdtscp instruction
+will be emulated with the guest TSC frequency.
-- 
2.7.0

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

* Re: [PATCH v4 04/10] x86/hvm: Collect information of TSC scaling ratio
  2016-01-17 21:58 ` [PATCH v4 04/10] x86/hvm: Collect information of TSC scaling ratio Haozhong Zhang
@ 2016-01-18 10:45   ` Egger, Christoph
  2016-01-19  3:19     ` Haozhong Zhang
  2016-02-05 11:41   ` Jan Beulich
  1 sibling, 1 reply; 32+ messages in thread
From: Egger, Christoph @ 2016-01-18 10:45 UTC (permalink / raw)
  To: Haozhong Zhang, xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Jun Nakajima, Andrew Cooper, Keir Fraser, Aravind Gopalakrishnan,
	Suravee Suthikulpanit

On 17/01/16 22:58, Haozhong Zhang wrote:
> Both VMX TSC scaling and SVM TSC ratio use the 64-bit TSC scaling ratio,
> but the number of fractional bits of the ratio is different between VMX
> and SVM. This patch adds the architecture code to collect the number of
> fractional bits and other related information into fields of struct
> hvm_function_table so that they can be used in the common code.
> 
> Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> ---
> Changes in v4:
>  (addressing Jan Beulich's comments in v3 patch 12)
>  * Set TSC scaling parameters in hvm_funcs conditionally.
>  * Remove TSC scaling parameter tsc_scaling_supported in hvm_funcs which
>    can be derived from other parameters.
>  (code cleanup)
>  * Merge with v3 patch 11 "x86/hvm: Detect TSC scaling through hvm_funcs"
>    whose work can be done early in this patch.
> 
>  xen/arch/x86/hvm/hvm.c        |  4 ++--
>  xen/arch/x86/hvm/svm/svm.c    | 10 ++++++++--
>  xen/arch/x86/time.c           |  9 ++++-----
>  xen/include/asm-x86/hvm/hvm.h | 14 ++++++++++++++
>  4 files changed, 28 insertions(+), 9 deletions(-)
> 
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 3648a44..6d30d8b 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -314,7 +314,7 @@ void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc)
>      else
>      {
>          tsc = at_tsc ?: rdtsc();
> -        if ( cpu_has_tsc_ratio )
> +        if ( hvm_tsc_scaling_supported )
>              tsc = hvm_funcs.scale_tsc(v, tsc);
>      }
>  
> @@ -346,7 +346,7 @@ u64 hvm_get_guest_tsc_fixed(struct vcpu *v, uint64_t at_tsc)
>      else
>      {
>          tsc = at_tsc ?: rdtsc();
> -        if ( cpu_has_tsc_ratio )
> +        if ( hvm_tsc_scaling_supported )
>              tsc = hvm_funcs.scale_tsc(v, tsc);
>      }
>  
> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> index 953e0b5..8b316a0 100644
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -1450,6 +1450,14 @@ const struct hvm_function_table * __init start_svm(void)
>      if ( !cpu_has_svm_nrips )
>          clear_bit(SVM_FEATURE_DECODEASSISTS, &svm_feature_flags);
>  
> +    if ( cpu_has_tsc_ratio )
> +    {
> +        svm_function_table.default_tsc_scaling_ratio = DEFAULT_TSC_RATIO;
> +        svm_function_table.max_tsc_scaling_ratio = ~TSC_RATIO_RSVD_BITS;
> +        svm_function_table.tsc_scaling_ratio_frac_bits = 32;
> +        svm_function_table.scale_tsc = svm_scale_tsc;
> +    }
> +
>  #define P(p,s) if ( p ) { printk(" - %s\n", s); printed = 1; }
>      P(cpu_has_svm_npt, "Nested Page Tables (NPT)");
>      P(cpu_has_svm_lbrv, "Last Branch Record (LBR) Virtualisation");
> @@ -2269,8 +2277,6 @@ static struct hvm_function_table __initdata svm_function_table = {
>      .nhvm_vmcx_hap_enabled = nsvm_vmcb_hap_enabled,
>      .nhvm_intr_blocked = nsvm_intr_blocked,
>      .nhvm_hap_walk_L1_p2m = nsvm_hap_walk_L1_p2m,
> -
> -    .scale_tsc            = svm_scale_tsc,
>  };
>  
>  void svm_vmexit_handler(struct cpu_user_regs *regs)
> diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
> index 988403a..a243bc3 100644
> --- a/xen/arch/x86/time.c
> +++ b/xen/arch/x86/time.c
> @@ -37,7 +37,6 @@
>  #include <asm/hpet.h>
>  #include <io_ports.h>
>  #include <asm/setup.h> /* for early_time_init */
> -#include <asm/hvm/svm/svm.h> /* for cpu_has_tsc_ratio */
>  #include <public/arch-x86/cpuid.h>
>  
>  /* opt_clocksource: Force clocksource to one of: pit, hpet, acpi. */
> @@ -815,7 +814,7 @@ static void __update_vcpu_system_time(struct vcpu *v, int force)
>      }
>      else
>      {
> -        if ( has_hvm_container_domain(d) && cpu_has_tsc_ratio )
> +        if ( has_hvm_container_domain(d) && hvm_tsc_scaling_supported )
>          {
>              tsc_stamp            = hvm_funcs.scale_tsc(v, t->local_tsc_stamp);
>              _u.tsc_to_system_mul = d->arch.vtsc_to_ns.mul_frac;
> @@ -1758,7 +1757,7 @@ void tsc_get_info(struct domain *d, uint32_t *tsc_mode,
>                    uint32_t *incarnation)
>  {
>      bool_t enable_tsc_scaling = has_hvm_container_domain(d) &&
> -                                cpu_has_tsc_ratio && !d->arch.vtsc;
> +                                hvm_tsc_scaling_supported && !d->arch.vtsc;
>  
>      *incarnation = d->arch.incarnation;
>      *tsc_mode = d->arch.tsc_mode;
> @@ -1865,7 +1864,7 @@ void tsc_set_info(struct domain *d,
>           */
>          if ( tsc_mode == TSC_MODE_DEFAULT && host_tsc_is_safe() &&
>               (has_hvm_container_domain(d) ?
> -              d->arch.tsc_khz == cpu_khz || cpu_has_tsc_ratio :
> +              d->arch.tsc_khz == cpu_khz || hvm_tsc_scaling_supported :
>                incarnation == 0) )

cpu_khz varies not only across different machines with exact same
CPU and same nominal cpu frequency it even differs across a reboot.
This breaks migration when you migrate forth and back. This is a
long-standing issue, no blocker to this patch.

>          {
>      case TSC_MODE_NEVER_EMULATE:
> @@ -1879,7 +1878,7 @@ void tsc_set_info(struct domain *d,
>          d->arch.vtsc = !boot_cpu_has(X86_FEATURE_RDTSCP) ||
>                         !host_tsc_is_safe();
>          enable_tsc_scaling = has_hvm_container_domain(d) &&
> -                             cpu_has_tsc_ratio && !d->arch.vtsc;
> +                             hvm_tsc_scaling_supported && !d->arch.vtsc;
>          d->arch.tsc_khz = (enable_tsc_scaling && gtsc_khz) ? gtsc_khz : cpu_khz;
>          set_time_scale(&d->arch.vtsc_to_ns, d->arch.tsc_khz * 1000 );
>          d->arch.ns_to_vtsc = scale_reciprocal(d->arch.vtsc_to_ns);
> diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
> index a87224b..79ea59e 100644
> --- a/xen/include/asm-x86/hvm/hvm.h
> +++ b/xen/include/asm-x86/hvm/hvm.h
> @@ -100,6 +100,17 @@ struct hvm_function_table {
>      unsigned int hap_capabilities;
>  
>      /*
> +     * Parameters of hardware-assisted TSC scaling, which are valid only when
> +     * the hardware feature is available.
> +     */
> +    /* number of bits of the fractional part of TSC scaling ratio */
> +    uint8_t  tsc_scaling_ratio_frac_bits;
> +    /* default TSC scaling ratio (no scaling) */
> +    uint64_t default_tsc_scaling_ratio;
> +    /* maximum-allowed TSC scaling ratio */
> +    uint64_t max_tsc_scaling_ratio;
> +
> +    /*
>       * Initialise/destroy HVM domain/vcpu resources
>       */
>      int  (*domain_initialise)(struct domain *d);
> @@ -213,6 +224,7 @@ struct hvm_function_table {
>      bool_t (*altp2m_vcpu_emulate_ve)(struct vcpu *v);
>      int (*altp2m_vcpu_emulate_vmfunc)(struct cpu_user_regs *regs);
>  
> +    /* Valid only when hardware-assisted TSC scaling is available */
>      uint64_t (*scale_tsc)(const struct vcpu *v, uint64_t tsc);
>  };
>  
> @@ -249,6 +261,8 @@ void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc);
>  u64 hvm_get_guest_tsc_fixed(struct vcpu *v, u64 at_tsc);
>  #define hvm_get_guest_tsc(v) hvm_get_guest_tsc_fixed(v, 0)
>  
> +#define hvm_tsc_scaling_supported (!!hvm_funcs.default_tsc_scaling_ratio)
> +
>  int hvm_set_mode(struct vcpu *v, int mode);
>  void hvm_init_guest_time(struct domain *d);
>  void hvm_set_guest_time(struct vcpu *v, u64 guest_time);
> 

Amazon Development Center Germany GmbH
Berlin - Dresden - Aachen
main office: Krausenstr. 38, 10117 Berlin
Geschaeftsfuehrer: Dr. Ralf Herbrich, Christian Schlaeger
Ust-ID: DE289237879
Eingetragen am Amtsgericht Charlottenburg HRB 149173 B

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

* Re: [PATCH v4 01/10] x86/hvm: Scale host TSC when setting/getting guest TSC
  2016-01-17 21:58 ` [PATCH v4 01/10] x86/hvm: Scale host TSC when setting/getting guest TSC Haozhong Zhang
@ 2016-01-18 13:39   ` Jan Beulich
  2016-01-19  0:17     ` Haozhong Zhang
  2016-01-19 14:27     ` Boris Ostrovsky
  0 siblings, 2 replies; 32+ messages in thread
From: Jan Beulich @ 2016-01-18 13:39 UTC (permalink / raw)
  To: Haozhong Zhang, Boris Ostrovsky
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima

>>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> The existing hvm_[set|get]_guest_tsc_fixed() calculate the guest TSC by
> adding the TSC offset to the host TSC. When the TSC scaling is enabled,
> the host TSC should be scaled first. This patch adds the scaling logic
> to those two functions.
> 
> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> ---
> Changes in v4:
>  (addressing Jan Beulich's comments)
>  * Remove redundant check of cpu_has_tsc_ratio in svm_scale_tsc().

This would better have caused Boris' R-b tag to get dropped, or
at least I don't recall him having offered it to stay despite the
change. Boris - can you confirm one way or the other?

>  * Move check of d->arch.vtsc in svm_scale_tsc() to callers.

No d->arch.vtsc instances appear anywhere in this patch, so the
wording is confusing. Indeed the two callers already check this (or
really sit on suitable "else" paths), so at least the patch is correct.

Jan

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

* Re: [PATCH v4 02/10] x86/time.c: Scale host TSC in pvclock properly
  2016-01-17 21:58 ` [PATCH v4 02/10] x86/time.c: Scale host TSC in pvclock properly Haozhong Zhang
@ 2016-01-18 13:42   ` Jan Beulich
  2016-01-19  0:29     ` Haozhong Zhang
  0 siblings, 1 reply; 32+ messages in thread
From: Jan Beulich @ 2016-01-18 13:42 UTC (permalink / raw)
  To: Haozhong Zhang
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

>>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> This patch makes the pvclock return the scaled host TSC and
> corresponding scaling parameters to HVM domains if guest TSC is not
> emulated and TSC scaling is enabled.
> 
> Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>

This doesn't look to be dependent on patch 1, and I would have
gone apply it right away if that had been stated anywhere
explicitly.

Jan

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

* Re: [PATCH v4 01/10] x86/hvm: Scale host TSC when setting/getting guest TSC
  2016-01-18 13:39   ` Jan Beulich
@ 2016-01-19  0:17     ` Haozhong Zhang
  2016-01-19 14:27     ` Boris Ostrovsky
  1 sibling, 0 replies; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-19  0:17 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

On 01/18/16 06:39, Jan Beulich wrote:
> >>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> > The existing hvm_[set|get]_guest_tsc_fixed() calculate the guest TSC by
> > adding the TSC offset to the host TSC. When the TSC scaling is enabled,
> > the host TSC should be scaled first. This patch adds the scaling logic
> > to those two functions.
> > 
> > Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> > Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> > ---
> > Changes in v4:
> >  (addressing Jan Beulich's comments)
> >  * Remove redundant check of cpu_has_tsc_ratio in svm_scale_tsc().
> 
> This would better have caused Boris' R-b tag to get dropped, or
> at least I don't recall him having offered it to stay despite the
> change. Boris - can you confirm one way or the other?
>
> >  * Move check of d->arch.vtsc in svm_scale_tsc() to callers.
> 
> No d->arch.vtsc instances appear anywhere in this patch, so the
> wording is confusing. Indeed the two callers already check this (or
> really sit on suitable "else" paths), so at least the patch is correct.
>

Sorry for the confusion. It should be "Remove check of d->arch.vtsc in
svm_scale_tsc() as it has been checked by callers."

Haozhong

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

* Re: [PATCH v4 02/10] x86/time.c: Scale host TSC in pvclock properly
  2016-01-18 13:42   ` Jan Beulich
@ 2016-01-19  0:29     ` Haozhong Zhang
  0 siblings, 0 replies; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-19  0:29 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

On 01/18/16 06:42, Jan Beulich wrote:
> >>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> > This patch makes the pvclock return the scaled host TSC and
> > corresponding scaling parameters to HVM domains if guest TSC is not
> > emulated and TSC scaling is enabled.
> > 
> > Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> 
> This doesn't look to be dependent on patch 1, and I would have
> gone apply it right away if that had been stated anywhere
> explicitly.
>

This one uses hvm_funcs.scale_tsc() added in patch 1.

Haozhong

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

* [RESEND PATCH v4 09/10] vmx: Add VMX RDTSC(P) scaling support
  2016-01-17 21:58 ` [PATCH v4 09/10] vmx: Add VMX RDTSC(P) scaling support Haozhong Zhang
@ 2016-01-19  2:55   ` Haozhong Zhang
  2016-02-05 14:06     ` Jan Beulich
  0 siblings, 1 reply; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-19  2:55 UTC (permalink / raw)
  To: xen-devel, Jan Beulich, Boris Ostrovsky, Kevin Tian
  Cc: Jun Nakajima, Andrew Cooper, Keir Fraser, Aravind Gopalakrishnan,
	Suravee Suthikulpanit

This patch adds the initialization and setup code for VMX TSC scaling.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
Acked-by: Kevin Tian <kevin.tian@intel.com>
---
I forgot to remove the hardcoded TSC scaling parameters in 
vmx_function_table. Resend this patch with them removed.

Changes in v4:
 (addressing Jan Beulich's comments)
 * Set TSC scaling parameters in hvm_funcs conditionally.

 xen/arch/x86/hvm/hvm.c             |  3 +++
 xen/arch/x86/hvm/vmx/vmcs.c        | 12 +++++++++---
 xen/arch/x86/hvm/vmx/vmx.c         | 16 ++++++++++++++++
 xen/include/asm-x86/hvm/hvm.h      |  3 +++
 xen/include/asm-x86/hvm/vmx/vmcs.h |  7 +++++++
 5 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ddc60a7..2469a5e 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -338,6 +338,9 @@ void hvm_setup_tsc_scaling(struct vcpu *v)
 {
     v->arch.hvm_vcpu.tsc_scaling_ratio =
         hvm_get_tsc_scaling_ratio(v->domain->arch.tsc_khz);
+
+    if ( hvm_funcs.setup_tsc_scaling )
+        hvm_funcs.setup_tsc_scaling(v);
 }
 
 void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc)
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index edd4c8d..8f16c3a 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -149,6 +149,7 @@ static void __init vmx_display_features(void)
     P(cpu_has_vmx_vmfunc, "VM Functions");
     P(cpu_has_vmx_virt_exceptions, "Virtualisation Exceptions");
     P(cpu_has_vmx_pml, "Page Modification Logging");
+    P(cpu_has_vmx_tsc_scaling, "TSC Scaling");
 #undef P
 
     if ( !printed )
@@ -242,7 +243,8 @@ static int vmx_init_vmcs_config(void)
                SECONDARY_EXEC_ENABLE_INVPCID |
                SECONDARY_EXEC_ENABLE_VM_FUNCTIONS |
                SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS |
-               SECONDARY_EXEC_XSAVES);
+               SECONDARY_EXEC_XSAVES |
+               SECONDARY_EXEC_TSC_SCALING);
         rdmsrl(MSR_IA32_VMX_MISC, _vmx_misc_cap);
         if ( _vmx_misc_cap & VMX_MISC_VMWRITE_ALL )
             opt |= SECONDARY_EXEC_ENABLE_VMCS_SHADOWING;
@@ -999,7 +1001,7 @@ static int construct_vmcs(struct vcpu *v)
     __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
 
     v->arch.hvm_vmx.exec_control = vmx_cpu_based_exec_control;
-    if ( d->arch.vtsc )
+    if ( d->arch.vtsc && !cpu_has_vmx_tsc_scaling )
         v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING;
 
     v->arch.hvm_vmx.secondary_exec_control = vmx_secondary_exec_control;
@@ -1281,6 +1283,9 @@ static int construct_vmcs(struct vcpu *v)
     if ( cpu_has_vmx_xsaves )
         __vmwrite(XSS_EXIT_BITMAP, 0);
 
+    if ( cpu_has_vmx_tsc_scaling )
+        __vmwrite(TSC_MULTIPLIER, v->arch.hvm_vcpu.tsc_scaling_ratio);
+
     vmx_vmcs_exit(v);
 
     /* PVH: paging mode is updated by arch_set_info_guest(). */
@@ -1863,7 +1868,8 @@ void vmcs_dump_vcpu(struct vcpu *v)
            vmr32(VM_EXIT_REASON), vmr(EXIT_QUALIFICATION));
     printk("IDTVectoring: info=%08x errcode=%08x\n",
            vmr32(IDT_VECTORING_INFO), vmr32(IDT_VECTORING_ERROR_CODE));
-    printk("TSC Offset = 0x%016lx\n", vmr(TSC_OFFSET));
+    printk("TSC Offset = 0x%016lx  TSC Multiplier = 0x%016lx\n",
+           vmr(TSC_OFFSET), vmr(TSC_MULTIPLIER));
     if ( (v->arch.hvm_vmx.exec_control & CPU_BASED_TPR_SHADOW) ||
          (vmx_pin_based_exec_control & PIN_BASED_POSTED_INTERRUPT) )
         printk("TPR Threshold = 0x%02x  PostedIntrVec = 0x%02x\n",
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 6285689..1ad1f83 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -115,6 +115,7 @@ static int vmx_vcpu_initialise(struct vcpu *v)
     v->arch.schedule_tail    = vmx_do_resume;
     v->arch.ctxt_switch_from = vmx_ctxt_switch_from;
     v->arch.ctxt_switch_to   = vmx_ctxt_switch_to;
+    v->arch.hvm_vcpu.tsc_scaling_ratio = VMX_TSC_MULTIPLIER_DEFAULT;
 
     if ( (rc = vmx_create_vmcs(v)) != 0 )
     {
@@ -1105,6 +1106,13 @@ static void vmx_handle_cd(struct vcpu *v, unsigned long value)
     }
 }
 
+static void vmx_setup_tsc_scaling(struct vcpu *v)
+{
+    vmx_vmcs_enter(v);
+    __vmwrite(TSC_MULTIPLIER, v->arch.hvm_vcpu.tsc_scaling_ratio);
+    vmx_vmcs_exit(v);
+}
+
 static void vmx_set_tsc_offset(struct vcpu *v, u64 offset, u64 at_tsc)
 {
     vmx_vmcs_enter(v);
@@ -2107,6 +2115,14 @@ const struct hvm_function_table * __init start_vmx(void)
          && cpu_has_vmx_secondary_exec_control )
         vmx_function_table.pvh_supported = 1;
 
+    if ( cpu_has_vmx_tsc_scaling )
+    {
+        vmx_function_table.default_tsc_scaling_ratio = VMX_TSC_MULTIPLIER_DEFAULT;
+        vmx_function_table.max_tsc_scaling_ratio = VMX_TSC_MULTIPLIER_MAX;
+        vmx_function_table.tsc_scaling_ratio_frac_bits = 48;
+        vmx_function_table.setup_tsc_scaling = vmx_setup_tsc_scaling;
+    }
+
     setup_vmcs_dump();
 
     return &vmx_function_table;
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 5588b92..10b9457 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -223,6 +223,9 @@ struct hvm_function_table {
     void (*altp2m_vcpu_update_vmfunc_ve)(struct vcpu *v);
     bool_t (*altp2m_vcpu_emulate_ve)(struct vcpu *v);
     int (*altp2m_vcpu_emulate_vmfunc)(struct cpu_user_regs *regs);
+
+    /* Architecture function to setup TSC scaling ratio */
+    void (*setup_tsc_scaling)(struct vcpu *v);
 };
 
 extern struct hvm_function_table hvm_funcs;
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h
index d1496b8..fdece44 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -236,6 +236,7 @@ extern u32 vmx_vmentry_control;
 #define SECONDARY_EXEC_ENABLE_PML               0x00020000
 #define SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS   0x00040000
 #define SECONDARY_EXEC_XSAVES                   0x00100000
+#define SECONDARY_EXEC_TSC_SCALING              0x02000000
 extern u32 vmx_secondary_exec_control;
 
 #define VMX_EPT_EXEC_ONLY_SUPPORTED                         0x00000001
@@ -258,6 +259,9 @@ extern u64 vmx_ept_vpid_cap;
 #define VMX_MISC_CR3_TARGET                     0x01ff0000
 #define VMX_MISC_VMWRITE_ALL                    0x20000000
 
+#define VMX_TSC_MULTIPLIER_DEFAULT              0x0001000000000000ULL
+#define VMX_TSC_MULTIPLIER_MAX                  0xffffffffffffffffULL
+
 #define cpu_has_wbinvd_exiting \
     (vmx_secondary_exec_control & SECONDARY_EXEC_WBINVD_EXITING)
 #define cpu_has_vmx_virtualize_apic_accesses \
@@ -303,6 +307,8 @@ extern u64 vmx_ept_vpid_cap;
     (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_PML)
 #define cpu_has_vmx_xsaves \
     (vmx_secondary_exec_control & SECONDARY_EXEC_XSAVES)
+#define cpu_has_vmx_tsc_scaling \
+    (vmx_secondary_exec_control & SECONDARY_EXEC_TSC_SCALING)
 
 #define VMCS_RID_TYPE_MASK              0x80000000
 
@@ -378,6 +384,7 @@ enum vmcs_field {
     VMWRITE_BITMAP                  = 0x00002028,
     VIRT_EXCEPTION_INFO             = 0x0000202a,
     XSS_EXIT_BITMAP                 = 0x0000202c,
+    TSC_MULTIPLIER                  = 0x00002032,
     GUEST_PHYSICAL_ADDRESS          = 0x00002400,
     VMCS_LINK_POINTER               = 0x00002800,
     GUEST_IA32_DEBUGCTL             = 0x00002802,
-- 
2.4.8

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

* Re: [PATCH v4 04/10] x86/hvm: Collect information of TSC scaling ratio
  2016-01-18 10:45   ` Egger, Christoph
@ 2016-01-19  3:19     ` Haozhong Zhang
  0 siblings, 0 replies; 32+ messages in thread
From: Haozhong Zhang @ 2016-01-19  3:19 UTC (permalink / raw)
  To: Egger, Christoph
  Cc: Kevin Tian, Keir Fraser, Jan Beulich, Jun Nakajima,
	Andrew Cooper, xen-devel, Aravind Gopalakrishnan,
	Suravee Suthikulpanit, Boris Ostrovsky

On 01/18/16 11:45, Egger, Christoph wrote:
> On 17/01/16 22:58, Haozhong Zhang wrote:
> > Both VMX TSC scaling and SVM TSC ratio use the 64-bit TSC scaling ratio,
> > but the number of fractional bits of the ratio is different between VMX
> > and SVM. This patch adds the architecture code to collect the number of
> > fractional bits and other related information into fields of struct
> > hvm_function_table so that they can be used in the common code.
> > 
> > Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> > Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> > Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> > ---
> > Changes in v4:
> >  (addressing Jan Beulich's comments in v3 patch 12)
> >  * Set TSC scaling parameters in hvm_funcs conditionally.
> >  * Remove TSC scaling parameter tsc_scaling_supported in hvm_funcs which
> >    can be derived from other parameters.
> >  (code cleanup)
> >  * Merge with v3 patch 11 "x86/hvm: Detect TSC scaling through hvm_funcs"
> >    whose work can be done early in this patch.
> > 
> >  xen/arch/x86/hvm/hvm.c        |  4 ++--
> >  xen/arch/x86/hvm/svm/svm.c    | 10 ++++++++--
> >  xen/arch/x86/time.c           |  9 ++++-----
> >  xen/include/asm-x86/hvm/hvm.h | 14 ++++++++++++++
> >  4 files changed, 28 insertions(+), 9 deletions(-)
> > 
> > diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> > index 3648a44..6d30d8b 100644
> > --- a/xen/arch/x86/hvm/hvm.c
> > +++ b/xen/arch/x86/hvm/hvm.c
> > @@ -314,7 +314,7 @@ void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc)
> >      else
> >      {
> >          tsc = at_tsc ?: rdtsc();
> > -        if ( cpu_has_tsc_ratio )
> > +        if ( hvm_tsc_scaling_supported )
> >              tsc = hvm_funcs.scale_tsc(v, tsc);
> >      }
> >  
> > @@ -346,7 +346,7 @@ u64 hvm_get_guest_tsc_fixed(struct vcpu *v, uint64_t at_tsc)
> >      else
> >      {
> >          tsc = at_tsc ?: rdtsc();
> > -        if ( cpu_has_tsc_ratio )
> > +        if ( hvm_tsc_scaling_supported )
> >              tsc = hvm_funcs.scale_tsc(v, tsc);
> >      }
> >  
> > diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> > index 953e0b5..8b316a0 100644
> > --- a/xen/arch/x86/hvm/svm/svm.c
> > +++ b/xen/arch/x86/hvm/svm/svm.c
> > @@ -1450,6 +1450,14 @@ const struct hvm_function_table * __init start_svm(void)
> >      if ( !cpu_has_svm_nrips )
> >          clear_bit(SVM_FEATURE_DECODEASSISTS, &svm_feature_flags);
> >  
> > +    if ( cpu_has_tsc_ratio )
> > +    {
> > +        svm_function_table.default_tsc_scaling_ratio = DEFAULT_TSC_RATIO;
> > +        svm_function_table.max_tsc_scaling_ratio = ~TSC_RATIO_RSVD_BITS;
> > +        svm_function_table.tsc_scaling_ratio_frac_bits = 32;
> > +        svm_function_table.scale_tsc = svm_scale_tsc;
> > +    }
> > +
> >  #define P(p,s) if ( p ) { printk(" - %s\n", s); printed = 1; }
> >      P(cpu_has_svm_npt, "Nested Page Tables (NPT)");
> >      P(cpu_has_svm_lbrv, "Last Branch Record (LBR) Virtualisation");
> > @@ -2269,8 +2277,6 @@ static struct hvm_function_table __initdata svm_function_table = {
> >      .nhvm_vmcx_hap_enabled = nsvm_vmcb_hap_enabled,
> >      .nhvm_intr_blocked = nsvm_intr_blocked,
> >      .nhvm_hap_walk_L1_p2m = nsvm_hap_walk_L1_p2m,
> > -
> > -    .scale_tsc            = svm_scale_tsc,
> >  };
> >  
> >  void svm_vmexit_handler(struct cpu_user_regs *regs)
> > diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
> > index 988403a..a243bc3 100644
> > --- a/xen/arch/x86/time.c
> > +++ b/xen/arch/x86/time.c
> > @@ -37,7 +37,6 @@
> >  #include <asm/hpet.h>
> >  #include <io_ports.h>
> >  #include <asm/setup.h> /* for early_time_init */
> > -#include <asm/hvm/svm/svm.h> /* for cpu_has_tsc_ratio */
> >  #include <public/arch-x86/cpuid.h>
> >  
> >  /* opt_clocksource: Force clocksource to one of: pit, hpet, acpi. */
> > @@ -815,7 +814,7 @@ static void __update_vcpu_system_time(struct vcpu *v, int force)
> >      }
> >      else
> >      {
> > -        if ( has_hvm_container_domain(d) && cpu_has_tsc_ratio )
> > +        if ( has_hvm_container_domain(d) && hvm_tsc_scaling_supported )
> >          {
> >              tsc_stamp            = hvm_funcs.scale_tsc(v, t->local_tsc_stamp);
> >              _u.tsc_to_system_mul = d->arch.vtsc_to_ns.mul_frac;
> > @@ -1758,7 +1757,7 @@ void tsc_get_info(struct domain *d, uint32_t *tsc_mode,
> >                    uint32_t *incarnation)
> >  {
> >      bool_t enable_tsc_scaling = has_hvm_container_domain(d) &&
> > -                                cpu_has_tsc_ratio && !d->arch.vtsc;
> > +                                hvm_tsc_scaling_supported && !d->arch.vtsc;
> >  
> >      *incarnation = d->arch.incarnation;
> >      *tsc_mode = d->arch.tsc_mode;
> > @@ -1865,7 +1864,7 @@ void tsc_set_info(struct domain *d,
> >           */
> >          if ( tsc_mode == TSC_MODE_DEFAULT && host_tsc_is_safe() &&
> >               (has_hvm_container_domain(d) ?
> > -              d->arch.tsc_khz == cpu_khz || cpu_has_tsc_ratio :
> > +              d->arch.tsc_khz == cpu_khz || hvm_tsc_scaling_supported :
> >                incarnation == 0) )
> 
> cpu_khz varies not only across different machines with exact same
> CPU and same nominal cpu frequency it even differs across a reboot.
> This breaks migration when you migrate forth and back. This is a
> long-standing issue, no blocker to this patch.
>

If cpu_khz is changed after host reboots and a VM is later migrated
back to this host, it will be just like a normal migration. That is,
(1) if the host supports TSC scaling, then TSC scaling will enable
    the VM still using the original cpu_khz;
(2) otherwise, TSC emulation will take effect and make VM still gets
    TSC in the original cpu_khz.

Haozhong

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

* Re: [PATCH v4 01/10] x86/hvm: Scale host TSC when setting/getting guest TSC
  2016-01-18 13:39   ` Jan Beulich
  2016-01-19  0:17     ` Haozhong Zhang
@ 2016-01-19 14:27     ` Boris Ostrovsky
  1 sibling, 0 replies; 32+ messages in thread
From: Boris Ostrovsky @ 2016-01-19 14:27 UTC (permalink / raw)
  To: Jan Beulich, Haozhong Zhang
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima

On 01/18/2016 08:39 AM, Jan Beulich wrote:
>>>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
>> The existing hvm_[set|get]_guest_tsc_fixed() calculate the guest TSC by
>> adding the TSC offset to the host TSC. When the TSC scaling is enabled,
>> the host TSC should be scaled first. This patch adds the scaling logic
>> to those two functions.
>>
>> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
>> Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
>> ---
>> Changes in v4:
>>   (addressing Jan Beulich's comments)
>>   * Remove redundant check of cpu_has_tsc_ratio in svm_scale_tsc().
> This would better have caused Boris' R-b tag to get dropped, or
> at least I don't recall him having offered it to stay despite the
> change. Boris - can you confirm one way or the other?

Yes, that's fine, my tag still stands.

-boris

>
>>   * Move check of d->arch.vtsc in svm_scale_tsc() to callers.
> No d->arch.vtsc instances appear anywhere in this patch, so the
> wording is confusing. Indeed the two callers already check this (or
> really sit on suitable "else" paths), so at least the patch is correct.
>
> Jan
>

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

* Re: [PATCH v4 00/10] Add VMX TSC scaling support
  2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
                   ` (9 preceding siblings ...)
  2016-01-17 21:58 ` [PATCH v4 10/10] docs: Add descriptions of TSC scaling in xl.cfg and tscmode.txt Haozhong Zhang
@ 2016-02-01  5:50 ` Haozhong Zhang
  2016-02-01  7:54   ` Jan Beulich
  10 siblings, 1 reply; 32+ messages in thread
From: Haozhong Zhang @ 2016-02-01  5:50 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Kevin Tian, Keir Fraser, Jun Nakajima, Andrew Cooper, xen-devel,
	Aravind Gopalakrishnan, Suravee Suthikulpanit, Boris Ostrovsky

Hi Jan,

On 01/18/16 05:58, Haozhong Zhang wrote:
> This patchset adds support for VMX TSC scaling feature which is
> available on Intel Skylake Server 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 frequency. 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.
> 
> If the destination host supports VMX TSC scaling, this patchset allows
> guest programs in a HVM container in the default TSC mode or PVRDTSCP
> (native_paravirt) TSC mode to observe the same TSC frequency across
> the migration.
> 
> Changes in v4:
>  * v3 patch 1&2 have been committed so they are not included in v4.
>  * v3 patch 11 "x86/hvm: Detect TSC scaling through hvm_funcs" is merged
>    early into v4 patch 4 "x86/hvm: Collect information of TSC scaling ratio".
>  * v4 patch 1 - 8 correspond to v3 patch 3 - 10.
>    v4 patch 9 - 10 correspond to v3 patch 12 - 13.
>  * Other changes are logged in each patch respectively.
> 
> Changes in v3:
>  * v2 patch 1&2 have been merged so they do not appear in v3.
>  * Patch 1 - 6 correspond to v2 patch 3 - 8. Patch 7 is new.
>    Patch 8 - 13 correspond to v2 patch 9 - 14.
>  * Other changes are logged in each patch respectively.
> 
> Changes in v2:
>  * Remove unnecessary v1 patch 1&13.
>  * Add and move all bug-fix patches to the beginning of this series.
>    (Patch 1 - 6)
>  * Update changes in tsc_set_info() and tsc_get_info() to make both
>    functions consistent with each other. (Patch 2 - 4)
>  * Move a part of scaling logic out of [vmx|svm]_set_tsc_offset().
>    (Patch 7)
>  * Remove redundant hvm_funcs.tsc_scaling_ratio_rsvd. (Patch 8)
>  * Reimplement functions that calculate TSC ratio and scale TSC.
>    (Patch 9&10)
>  * Merge setting VMX TSC multiplier into patch 13.
>  * Move initialing tsc_scaling_ratio in VMX ahead to
>    vmx_vcpu_initialise() so as to make construct_vmcs() naturally
>    use this field instead of a constant. (Patch 13)
>  * Update documents related to tsc_mode.
>  * Other code cleanup and style fixes.
> 
> Haozhong Zhang (10):
>   x86/hvm: Scale host TSC when setting/getting guest TSC
>   x86/time.c: Scale host TSC in pvclock properly
>   svm: Remove redundant TSC scaling in svm_set_tsc_offset()
>   x86/hvm: Collect information of TSC scaling ratio
>   x86: Add functions for 64-bit integer arithmetic
>   x86/hvm: Setup TSC scaling ratio
>   x86/hvm: Replace architecture TSC scaling by a common function
>   x86/hvm: Move saving/loading vcpu's TSC to common code
>   vmx: Add VMX RDTSC(P) scaling support
>   docs: Add descriptions of TSC scaling in xl.cfg and tscmode.txt
> 
>  docs/man/xl.cfg.pod.5              | 14 +++++++-
>  docs/misc/tscmode.txt              | 21 ++++++++++++
>  xen/arch/x86/hvm/hvm.c             | 69 ++++++++++++++++++++++++++++++++------
>  xen/arch/x86/hvm/svm/svm.c         | 36 +++++++++-----------
>  xen/arch/x86/hvm/vmx/vmcs.c        | 12 +++++--
>  xen/arch/x86/hvm/vmx/vmx.c         | 25 +++++++++++---
>  xen/arch/x86/time.c                | 38 ++++++++++++++++-----
>  xen/include/asm-x86/hvm/hvm.h      | 20 +++++++++++
>  xen/include/asm-x86/hvm/svm/svm.h  |  3 --
>  xen/include/asm-x86/hvm/vcpu.h     |  2 ++
>  xen/include/asm-x86/hvm/vmx/vmcs.h |  7 ++++
>  xen/include/asm-x86/math64.h       | 47 ++++++++++++++++++++++++++
>  12 files changed, 242 insertions(+), 52 deletions(-)
>  create mode 100644 xen/include/asm-x86/math64.h
> 
> -- 
> 2.7.0
> 

I notice that the first three of this patch series have been
committed. Any comments on other ones?

Thanks,
Haozhong

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

* Re: [PATCH v4 00/10] Add VMX TSC scaling support
  2016-02-01  5:50 ` [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
@ 2016-02-01  7:54   ` Jan Beulich
  0 siblings, 0 replies; 32+ messages in thread
From: Jan Beulich @ 2016-02-01  7:54 UTC (permalink / raw)
  To: Haozhong Zhang
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

>>> On 01.02.16 at 06:50, <haozhong.zhang@intel.com> wrote:
> I notice that the first three of this patch series have been
> committed. Any comments on other ones?

They haven't been forgotten, but I didn't get around to look at
(and perhaps commit) them yet.

Jan

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

* Re: [PATCH v4 04/10] x86/hvm: Collect information of TSC scaling ratio
  2016-01-17 21:58 ` [PATCH v4 04/10] x86/hvm: Collect information of TSC scaling ratio Haozhong Zhang
  2016-01-18 10:45   ` Egger, Christoph
@ 2016-02-05 11:41   ` Jan Beulich
  2016-02-16  7:59     ` Zhang, Haozhong
  1 sibling, 1 reply; 32+ messages in thread
From: Jan Beulich @ 2016-02-05 11:41 UTC (permalink / raw)
  To: Haozhong Zhang
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

>>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> Both VMX TSC scaling and SVM TSC ratio use the 64-bit TSC scaling ratio,
> but the number of fractional bits of the ratio is different between VMX
> and SVM. This patch adds the architecture code to collect the number of
> fractional bits and other related information into fields of struct
> hvm_function_table so that they can be used in the common code.
> 
> Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> ---
> Changes in v4:
>  (addressing Jan Beulich's comments in v3 patch 12)
>  * Set TSC scaling parameters in hvm_funcs conditionally.
>  * Remove TSC scaling parameter tsc_scaling_supported in hvm_funcs which
>    can be derived from other parameters.
>  (code cleanup)
>  * Merge with v3 patch 11 "x86/hvm: Detect TSC scaling through hvm_funcs"
>    whose work can be done early in this patch.

I really think this the scope of these changes should have invalidated
all earlier tags.

> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -1450,6 +1450,14 @@ const struct hvm_function_table * __init start_svm(void)
>      if ( !cpu_has_svm_nrips )
>          clear_bit(SVM_FEATURE_DECODEASSISTS, &svm_feature_flags);
>  
> +    if ( cpu_has_tsc_ratio )
> +    {
> +        svm_function_table.default_tsc_scaling_ratio = DEFAULT_TSC_RATIO;
> +        svm_function_table.max_tsc_scaling_ratio = ~TSC_RATIO_RSVD_BITS;
> +        svm_function_table.tsc_scaling_ratio_frac_bits = 32;
> +        svm_function_table.scale_tsc = svm_scale_tsc;
> +    }
> +
>  #define P(p,s) if ( p ) { printk(" - %s\n", s); printed = 1; }
>      P(cpu_has_svm_npt, "Nested Page Tables (NPT)");
>      P(cpu_has_svm_lbrv, "Last Branch Record (LBR) Virtualisation");
> @@ -2269,8 +2277,6 @@ static struct hvm_function_table __initdata svm_function_table = {
>      .nhvm_vmcx_hap_enabled = nsvm_vmcb_hap_enabled,
>      .nhvm_intr_blocked = nsvm_intr_blocked,
>      .nhvm_hap_walk_L1_p2m = nsvm_hap_walk_L1_p2m,
> -
> -    .scale_tsc            = svm_scale_tsc,
>  };

>From at the first glance purely mechanical POV this change was
unnecessary with ...

> @@ -249,6 +261,8 @@ void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc);
>  u64 hvm_get_guest_tsc_fixed(struct vcpu *v, u64 at_tsc);
>  #define hvm_get_guest_tsc(v) hvm_get_guest_tsc_fixed(v, 0)
>  
> +#define hvm_tsc_scaling_supported (!!hvm_funcs.default_tsc_scaling_ratio)

... this, but considering our general aim to avoid having NULL
callback pointers wherever possible, I think this is more than just
a mechanical concern: I'd prefer if at least the callback pointer
always be statically initialized, and ideally also two of the other
fields. Only one field should be dynamically initialized (unless -
considering the VMX code to come - static initialization is
impossible), and ideally one which, if zero, would not have any
bad consequences if used by mistake (frac_bits maybe). And
perhaps an ASSERT() should be placed inside svm_scale_tsc()
making sure the dynamically initialized field actually is initialized.

The conditional here would then check _all_ fields which either
vendor's code leaves uninitialized (i.e. the VMX patch may then
add to the above).

Jan

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

* Re: [PATCH v4 05/10] x86: Add functions for 64-bit integer arithmetic
  2016-01-17 21:58 ` [PATCH v4 05/10] x86: Add functions for 64-bit integer arithmetic Haozhong Zhang
@ 2016-02-05 13:36   ` Jan Beulich
  2016-02-16  9:02     ` Zhang, Haozhong
  0 siblings, 1 reply; 32+ messages in thread
From: Jan Beulich @ 2016-02-05 13:36 UTC (permalink / raw)
  To: Haozhong Zhang
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

>>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> This patch adds several functions to take multiplication, division and
> shifting involving 64-bit integers.
> 
> Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> ---
> Changes in v4:
>  (addressing Jan Beulich's comments)
>  * Rewrite mul_u64_u64_shr() in assembly.

Thanks, but it puzzles me that the other one didn't get converted
as well. Anyway, I'm not going to make this a requirement, since
at least it appears to match Linux'es variant.

> +static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int n)
> +{
> +    u64 hi, lo;
> +
> +    asm volatile ( "mulq %2; shrdq %1,%0"
> +                   : "=a" (lo), "=d" (hi)
> +                   : "rm" (mul), "0" (a), "c" (n) );

SHRD formally is a 3-operand instruction, and the fact that gas'
AT&T syntax supports a 2-operand "alias" is, well, odd. Please
let's use the specification mandated 3-operand form properly,
to avoid surprises with e.g. clang.

Jan

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

* Re: [PATCH v4 06/10] x86/hvm: Setup TSC scaling ratio
  2016-01-17 21:58 ` [PATCH v4 06/10] x86/hvm: Setup TSC scaling ratio Haozhong Zhang
@ 2016-02-05 13:54   ` Jan Beulich
  2016-02-16  9:44     ` Zhang, Haozhong
  0 siblings, 1 reply; 32+ messages in thread
From: Jan Beulich @ 2016-02-05 13:54 UTC (permalink / raw)
  To: Haozhong Zhang
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

>>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> +u64 hvm_get_tsc_scaling_ratio(u32 gtsc_khz)
> +{
> +    u64 ratio;
> +
> +    if ( !hvm_tsc_scaling_supported )
> +        return 0;
> +
> +    /*
> +     * The multiplication of the first two terms may overflow a 64-bit
> +     * integer, so use mul_u64_u32_div() instead to keep precision.
> +     */
> +    ratio = mul_u64_u32_div(1ULL << hvm_funcs.tsc_scaling_ratio_frac_bits,
> +                            gtsc_khz, cpu_khz);

Is this the only use for this new math64 function? If so, I don't
see the point of adding that function, because (leaving limited
significant bits aside) the above simply is

(gtsc_khz << hvm_funcs.tsc_scaling_ratio_frac_bits) / cpu_khz

which can be had without any multiplication. Personally, if indeed
the only use I'd favor converting the above to inline assembly
here instead of adding that helper function (just like we have a
number of asm()-s in x86/time.c for similar reasons).

> +void hvm_setup_tsc_scaling(struct vcpu *v)
> +{
> +    v->arch.hvm_vcpu.tsc_scaling_ratio =
> +        hvm_get_tsc_scaling_ratio(v->domain->arch.tsc_khz);
> +}

So why again is this per-vCPU setup of per-vCPU state when it
only depends on a per-domain input? If this was per-domain, its
setup could be where it belongs - in arch_hvm_load().

> @@ -5504,6 +5536,9 @@ void hvm_vcpu_reset_state(struct vcpu *v, uint16_t cs, uint16_t ip)
>      hvm_set_segment_register(v, x86_seg_gdtr, &reg);
>      hvm_set_segment_register(v, x86_seg_idtr, &reg);
>  
> +    if ( hvm_tsc_scaling_supported && !d->arch.vtsc )
> +        hvm_setup_tsc_scaling(v);

Could you remind me why this is needed? What state of the guest
would have changed making this necessary? Is this perhaps just
because it's per-vCPU instead of per-domain?

Jan

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

* Re: [RESEND PATCH v4 09/10] vmx: Add VMX RDTSC(P) scaling support
  2016-01-19  2:55   ` [RESEND PATCH " Haozhong Zhang
@ 2016-02-05 14:06     ` Jan Beulich
  2016-02-16  7:59       ` Zhang, Haozhong
  0 siblings, 1 reply; 32+ messages in thread
From: Jan Beulich @ 2016-02-05 14:06 UTC (permalink / raw)
  To: Haozhong Zhang
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

>>> On 19.01.16 at 03:55, <haozhong.zhang@intel.com> wrote:
> @@ -2107,6 +2115,14 @@ const struct hvm_function_table * __init start_vmx(void)
>           && cpu_has_vmx_secondary_exec_control )
>          vmx_function_table.pvh_supported = 1;
>  
> +    if ( cpu_has_vmx_tsc_scaling )
> +    {
> +        vmx_function_table.default_tsc_scaling_ratio = VMX_TSC_MULTIPLIER_DEFAULT;
> +        vmx_function_table.max_tsc_scaling_ratio = VMX_TSC_MULTIPLIER_MAX;
> +        vmx_function_table.tsc_scaling_ratio_frac_bits = 48;
> +        vmx_function_table.setup_tsc_scaling = vmx_setup_tsc_scaling;
> +    }

Same comments here as on the earlier patch - it indeed looks as if
tsc_scaling_ratio_frac_bits would be the ideal field to dynamically
initialize, as it being zero will not yield any bad behavior afaict.

Also please consider making all fields together a sub-structure
of struct hvm_function_table, such that the above would become

        vmx_function_table.tsc_scaling.default_ratio = VMX_TSC_MULTIPLIER_DEFAULT;
        vmx_function_table.tsc_scaling.max_ratio = VMX_TSC_MULTIPLIER_MAX;
        vmx_function_table.tsc_scaling.ratio_frac_bits = 48;
        vmx_function_table.tsc_scaling.setup = vmx_setup_tsc_scaling;

keeping everything nicely together.

> @@ -258,6 +259,9 @@ extern u64 vmx_ept_vpid_cap;
>  #define VMX_MISC_CR3_TARGET                     0x01ff0000
>  #define VMX_MISC_VMWRITE_ALL                    0x20000000
>  
> +#define VMX_TSC_MULTIPLIER_DEFAULT              0x0001000000000000ULL

Considering this and the respective SVM value - do we really
need the separate field in struct hvm_function_table? Both are
1ULL << tsc_scaling.ratio_frac_bits after all.

Jan

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

* Re: [PATCH v4 04/10] x86/hvm: Collect information of TSC scaling ratio
  2016-02-05 11:41   ` Jan Beulich
@ 2016-02-16  7:59     ` Zhang, Haozhong
  0 siblings, 0 replies; 32+ messages in thread
From: Zhang, Haozhong @ 2016-02-16  7:59 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tian, Kevin, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Nakajima, Jun,
	Boris Ostrovsky

On 02/05/16 19:41, Jan Beulich wrote:
> >>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> > Both VMX TSC scaling and SVM TSC ratio use the 64-bit TSC scaling ratio,
> > but the number of fractional bits of the ratio is different between VMX
> > and SVM. This patch adds the architecture code to collect the number of
> > fractional bits and other related information into fields of struct
> > hvm_function_table so that they can be used in the common code.
> > 
> > Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> > Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> > Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> > ---
> > Changes in v4:
> >  (addressing Jan Beulich's comments in v3 patch 12)
> >  * Set TSC scaling parameters in hvm_funcs conditionally.
> >  * Remove TSC scaling parameter tsc_scaling_supported in hvm_funcs which
> >    can be derived from other parameters.
> >  (code cleanup)
> >  * Merge with v3 patch 11 "x86/hvm: Detect TSC scaling through hvm_funcs"
> >    whose work can be done early in this patch.
> 
> I really think this the scope of these changes should have invalidated
> all earlier tags.
>

I'll remove all R-b tags.

> > --- a/xen/arch/x86/hvm/svm/svm.c
> > +++ b/xen/arch/x86/hvm/svm/svm.c
> > @@ -1450,6 +1450,14 @@ const struct hvm_function_table * __init start_svm(void)
> >      if ( !cpu_has_svm_nrips )
> >          clear_bit(SVM_FEATURE_DECODEASSISTS, &svm_feature_flags);
> >  
> > +    if ( cpu_has_tsc_ratio )
> > +    {
> > +        svm_function_table.default_tsc_scaling_ratio = DEFAULT_TSC_RATIO;
> > +        svm_function_table.max_tsc_scaling_ratio = ~TSC_RATIO_RSVD_BITS;
> > +        svm_function_table.tsc_scaling_ratio_frac_bits = 32;
> > +        svm_function_table.scale_tsc = svm_scale_tsc;
> > +    }
> > +
> >  #define P(p,s) if ( p ) { printk(" - %s\n", s); printed = 1; }
> >      P(cpu_has_svm_npt, "Nested Page Tables (NPT)");
> >      P(cpu_has_svm_lbrv, "Last Branch Record (LBR) Virtualisation");
> > @@ -2269,8 +2277,6 @@ static struct hvm_function_table __initdata svm_function_table = {
> >      .nhvm_vmcx_hap_enabled = nsvm_vmcb_hap_enabled,
> >      .nhvm_intr_blocked = nsvm_intr_blocked,
> >      .nhvm_hap_walk_L1_p2m = nsvm_hap_walk_L1_p2m,
> > -
> > -    .scale_tsc            = svm_scale_tsc,
> >  };
> 
> From at the first glance purely mechanical POV this change was
> unnecessary with ...
> 
> > @@ -249,6 +261,8 @@ void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc);
> >  u64 hvm_get_guest_tsc_fixed(struct vcpu *v, u64 at_tsc);
> >  #define hvm_get_guest_tsc(v) hvm_get_guest_tsc_fixed(v, 0)
> >  
> > +#define hvm_tsc_scaling_supported (!!hvm_funcs.default_tsc_scaling_ratio)
> 
> ... this, but considering our general aim to avoid having NULL
> callback pointers wherever possible, I think this is more than just
> a mechanical concern: I'd prefer if at least the callback pointer
> always be statically initialized, and ideally also two of the other
> fields. Only one field should be dynamically initialized (unless -
> considering the VMX code to come - static initialization is
> impossible), and ideally one which, if zero, would not have any
> bad consequences if used by mistake (frac_bits maybe). And
> perhaps an ASSERT() should be placed inside svm_scale_tsc()
> making sure the dynamically initialized field actually is initialized.
>

Combined with your comments for patch 9, I'll leave only
tsc_scaling_ratio_frac_bits to be dynamically initialized.

> The conditional here would then check _all_ fields which either
> vendor's code leaves uninitialized (i.e. the VMX patch may then
> add to the above).
>

so it would be
    #define hvm_tsc_scaling_supported (!!hvm_funcs.tsc_scaling_ratio_frac_bits)


Thanks,
Haozhong

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

* Re: [RESEND PATCH v4 09/10] vmx: Add VMX RDTSC(P) scaling support
  2016-02-05 14:06     ` Jan Beulich
@ 2016-02-16  7:59       ` Zhang, Haozhong
  0 siblings, 0 replies; 32+ messages in thread
From: Zhang, Haozhong @ 2016-02-16  7:59 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tian, Kevin, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Nakajima, Jun,
	Boris Ostrovsky

On 02/05/16 22:06, Jan Beulich wrote:
> >>> On 19.01.16 at 03:55, <haozhong.zhang@intel.com> wrote:
> > @@ -2107,6 +2115,14 @@ const struct hvm_function_table * __init start_vmx(void)
> >           && cpu_has_vmx_secondary_exec_control )
> >          vmx_function_table.pvh_supported = 1;
> >  
> > +    if ( cpu_has_vmx_tsc_scaling )
> > +    {
> > +        vmx_function_table.default_tsc_scaling_ratio = VMX_TSC_MULTIPLIER_DEFAULT;
> > +        vmx_function_table.max_tsc_scaling_ratio = VMX_TSC_MULTIPLIER_MAX;
> > +        vmx_function_table.tsc_scaling_ratio_frac_bits = 48;
> > +        vmx_function_table.setup_tsc_scaling = vmx_setup_tsc_scaling;
> > +    }
> 
> Same comments here as on the earlier patch - it indeed looks as if
> tsc_scaling_ratio_frac_bits would be the ideal field to dynamically
> initialize, as it being zero will not yield any bad behavior afaict.
>

Yes, I'll make changes similar to my reply under patch 4.

> Also please consider making all fields together a sub-structure
> of struct hvm_function_table, such that the above would become
> 
>         vmx_function_table.tsc_scaling.default_ratio = VMX_TSC_MULTIPLIER_DEFAULT;
>         vmx_function_table.tsc_scaling.max_ratio = VMX_TSC_MULTIPLIER_MAX;
>         vmx_function_table.tsc_scaling.ratio_frac_bits = 48;
>         vmx_function_table.tsc_scaling.setup = vmx_setup_tsc_scaling;
> 
> keeping everything nicely together.
>

OK, I'll put them in a sub-structure by the earlier patch that
introduces those fields.

> > @@ -258,6 +259,9 @@ extern u64 vmx_ept_vpid_cap;
> >  #define VMX_MISC_CR3_TARGET                     0x01ff0000
> >  #define VMX_MISC_VMWRITE_ALL                    0x20000000
> >  
> > +#define VMX_TSC_MULTIPLIER_DEFAULT              0x0001000000000000ULL
> 
> Considering this and the respective SVM value - do we really
> need the separate field in struct hvm_function_table? Both are
> 1ULL << tsc_scaling.ratio_frac_bits after all.
>

I'll remove VMX_TSC_MULTIPLIER_DEFAULT and DEFAULT_TSC_RATIO (for SVM),
and use ratio_frac_bits to initialize default_ratio.

Thanks,
Haozhong

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

* Re: [PATCH v4 05/10] x86: Add functions for 64-bit integer arithmetic
  2016-02-05 13:36   ` Jan Beulich
@ 2016-02-16  9:02     ` Zhang, Haozhong
  2016-02-16  9:39       ` Jan Beulich
  0 siblings, 1 reply; 32+ messages in thread
From: Zhang, Haozhong @ 2016-02-16  9:02 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tian, Kevin, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Nakajima, Jun,
	Boris Ostrovsky

On 02/05/16 21:36, Jan Beulich wrote:
> >>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> > This patch adds several functions to take multiplication, division and
> > shifting involving 64-bit integers.
> > 
> > Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> > Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> > ---
> > Changes in v4:
> >  (addressing Jan Beulich's comments)
> >  * Rewrite mul_u64_u64_shr() in assembly.
> 
> Thanks, but it puzzles me that the other one didn't get converted
> as well. Anyway, I'm not going to make this a requirement, since
> at least it appears to match Linux'es variant.
>

I can't remember why I didn't rewrite mul_u64_u32_div(), especially when
it can be easily implemented as

static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
{
    u64 quotient, remainder;
    
    asm volatile ( "mulq %3; divq %4"
                   : "=a" (quotient), "=d" (remainder)
                   : "0" (a), "rm" ((u64) mul), "c" ((u64) divisor) );

    return quotient;
}

I'll modify it in the next version.

> > +static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int n)
> > +{
> > +    u64 hi, lo;
> > +
> > +    asm volatile ( "mulq %2; shrdq %1,%0"
> > +                   : "=a" (lo), "=d" (hi)
> > +                   : "rm" (mul), "0" (a), "c" (n) );
> 
> SHRD formally is a 3-operand instruction, and the fact that gas'
> AT&T syntax supports a 2-operand "alias" is, well, odd. Please
> let's use the specification mandated 3-operand form properly,
> to avoid surprises with e.g. clang.
>

OK, I'll change it to the 3-operand form.

Haozhong

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

* Re: [PATCH v4 05/10] x86: Add functions for 64-bit integer arithmetic
  2016-02-16  9:02     ` Zhang, Haozhong
@ 2016-02-16  9:39       ` Jan Beulich
  2016-02-16  9:57         ` Haozhong Zhang
  0 siblings, 1 reply; 32+ messages in thread
From: Jan Beulich @ 2016-02-16  9:39 UTC (permalink / raw)
  To: Haozhong Zhang
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

>>> On 16.02.16 at 10:02, <haozhong.zhang@intel.com> wrote:
> On 02/05/16 21:36, Jan Beulich wrote:
>> >>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
>> > This patch adds several functions to take multiplication, division and
>> > shifting involving 64-bit integers.
>> > 
>> > Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
>> > Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
>> > ---
>> > Changes in v4:
>> >  (addressing Jan Beulich's comments)
>> >  * Rewrite mul_u64_u64_shr() in assembly.
>> 
>> Thanks, but it puzzles me that the other one didn't get converted
>> as well. Anyway, I'm not going to make this a requirement, since
>> at least it appears to match Linux'es variant.
>>
> 
> I can't remember why I didn't rewrite mul_u64_u32_div(), especially when
> it can be easily implemented as
> 
> static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
> {
>     u64 quotient, remainder;
>     
>     asm volatile ( "mulq %3; divq %4"
>                    : "=a" (quotient), "=d" (remainder)
>                    : "0" (a), "rm" ((u64) mul), "c" ((u64) divisor) );
> 
>     return quotient;
> }
> 
> I'll modify it in the next version.

Looks better, but the constraints aren't right (needing =& for
both outputs, and "c" being too narrow). But iirc the question
was anyway whether to better have even lower overhead inline
assembly and single point of use.

Jan

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

* Re: [PATCH v4 06/10] x86/hvm: Setup TSC scaling ratio
  2016-02-05 13:54   ` Jan Beulich
@ 2016-02-16  9:44     ` Zhang, Haozhong
  2016-02-16 10:12       ` Jan Beulich
  0 siblings, 1 reply; 32+ messages in thread
From: Zhang, Haozhong @ 2016-02-16  9:44 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tian, Kevin, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Nakajima, Jun,
	Boris Ostrovsky

On 02/05/16 21:54, Jan Beulich wrote:
> >>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> > +u64 hvm_get_tsc_scaling_ratio(u32 gtsc_khz)
> > +{
> > +    u64 ratio;
> > +
> > +    if ( !hvm_tsc_scaling_supported )
> > +        return 0;
> > +
> > +    /*
> > +     * The multiplication of the first two terms may overflow a 64-bit
> > +     * integer, so use mul_u64_u32_div() instead to keep precision.
> > +     */
> > +    ratio = mul_u64_u32_div(1ULL << hvm_funcs.tsc_scaling_ratio_frac_bits,
> > +                            gtsc_khz, cpu_khz);
> 
> Is this the only use for this new math64 function? If so, I don't
> see the point of adding that function, because (leaving limited
> significant bits aside) the above simply is
> 
> (gtsc_khz << hvm_funcs.tsc_scaling_ratio_frac_bits) / cpu_khz
> 
> which can be had without any multiplication. Personally, if indeed
> the only use I'd favor converting the above to inline assembly
> here instead of adding that helper function (just like we have a
> number of asm()-s in x86/time.c for similar reasons).
>

OK, I'll rewrite it as asm(). mul_u64_u32_div() will not be used any
more and will be removed.

I'll also inline another math64 function mul_u64_u64_shr() in its single
caller hvm_scale_tsc(). Then the math64 patch will be dropped in the
next version.

> > +void hvm_setup_tsc_scaling(struct vcpu *v)
> > +{
> > +    v->arch.hvm_vcpu.tsc_scaling_ratio =
> > +        hvm_get_tsc_scaling_ratio(v->domain->arch.tsc_khz);
> > +}
> 
> So why again is this per-vCPU setup of per-vCPU state when it
> only depends on a per-domain input? If this was per-domain, its
> setup could be where it belongs - in arch_hvm_load().
>

It's a per-domain state. I'll the state to x86's struct arch_domain
where other TSC fields are (or struct hvm_domain, because this is only
used for HVM?).

Then it will be setup in tsc_set_info() after guest tsc frequency is
determined.

> > @@ -5504,6 +5536,9 @@ void hvm_vcpu_reset_state(struct vcpu *v, uint16_t cs, uint16_t ip)
> >      hvm_set_segment_register(v, x86_seg_gdtr, &reg);
> >      hvm_set_segment_register(v, x86_seg_idtr, &reg);
> >  
> > +    if ( hvm_tsc_scaling_supported && !d->arch.vtsc )
> > +        hvm_setup_tsc_scaling(v);
> 
> Could you remind me why this is needed? What state of the guest
> would have changed making this necessary? Is this perhaps just
> because it's per-vCPU instead of per-domain?
> 
> Jan
> 

Yes, just because I mistakenly made it per-vcpu. So it will be not
necessary in this patch after tsc_scaling_ratio become per-domain.

Haozhong

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

* Re: [PATCH v4 05/10] x86: Add functions for 64-bit integer arithmetic
  2016-02-16  9:39       ` Jan Beulich
@ 2016-02-16  9:57         ` Haozhong Zhang
  0 siblings, 0 replies; 32+ messages in thread
From: Haozhong Zhang @ 2016-02-16  9:57 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

On 02/16/16 02:39, Jan Beulich wrote:
> >>> On 16.02.16 at 10:02, <haozhong.zhang@intel.com> wrote:
> > On 02/05/16 21:36, Jan Beulich wrote:
> >> >>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
> >> > This patch adds several functions to take multiplication, division and
> >> > shifting involving 64-bit integers.
> >> > 
> >> > Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
> >> > Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> >> > ---
> >> > Changes in v4:
> >> >  (addressing Jan Beulich's comments)
> >> >  * Rewrite mul_u64_u64_shr() in assembly.
> >> 
> >> Thanks, but it puzzles me that the other one didn't get converted
> >> as well. Anyway, I'm not going to make this a requirement, since
> >> at least it appears to match Linux'es variant.
> >>
> > 
> > I can't remember why I didn't rewrite mul_u64_u32_div(), especially when
> > it can be easily implemented as
> > 
> > static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
> > {
> >     u64 quotient, remainder;
> >     
> >     asm volatile ( "mulq %3; divq %4"
> >                    : "=a" (quotient), "=d" (remainder)
> >                    : "0" (a), "rm" ((u64) mul), "c" ((u64) divisor) );
> > 
> >     return quotient;
> > }
> > 
> > I'll modify it in the next version.
> 
> Looks better, but the constraints aren't right (needing =& for
> both outputs, and "c" being too narrow). But iirc the question
> was anyway whether to better have even lower overhead inline
> assembly and single point of use.
>

Thank you for pointing out the constraint error! And indeed every
function in this patch is used at single point. In my reply to your
comments for patch 6, I'll modify and inline them at their use points.

Haozhong

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

* Re: [PATCH v4 06/10] x86/hvm: Setup TSC scaling ratio
  2016-02-16  9:44     ` Zhang, Haozhong
@ 2016-02-16 10:12       ` Jan Beulich
  0 siblings, 0 replies; 32+ messages in thread
From: Jan Beulich @ 2016-02-16 10:12 UTC (permalink / raw)
  To: Haozhong Zhang
  Cc: Kevin Tian, Keir Fraser, Suravee Suthikulpanit, Andrew Cooper,
	xen-devel, Aravind Gopalakrishnan, Jun Nakajima, Boris Ostrovsky

>>> On 16.02.16 at 10:44, <haozhong.zhang@intel.com> wrote:
> On 02/05/16 21:54, Jan Beulich wrote:
>> >>> On 17.01.16 at 22:58, <haozhong.zhang@intel.com> wrote:
>> > +void hvm_setup_tsc_scaling(struct vcpu *v)
>> > +{
>> > +    v->arch.hvm_vcpu.tsc_scaling_ratio =
>> > +        hvm_get_tsc_scaling_ratio(v->domain->arch.tsc_khz);
>> > +}
>> 
>> So why again is this per-vCPU setup of per-vCPU state when it
>> only depends on a per-domain input? If this was per-domain, its
>> setup could be where it belongs - in arch_hvm_load().
>>
> 
> It's a per-domain state. I'll the state to x86's struct arch_domain
> where other TSC fields are (or struct hvm_domain, because this is only
> used for HVM?).

struct hvm_domain please.

Jan

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

end of thread, other threads:[~2016-02-16 10:12 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-17 21:58 [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
2016-01-17 21:58 ` [PATCH v4 01/10] x86/hvm: Scale host TSC when setting/getting guest TSC Haozhong Zhang
2016-01-18 13:39   ` Jan Beulich
2016-01-19  0:17     ` Haozhong Zhang
2016-01-19 14:27     ` Boris Ostrovsky
2016-01-17 21:58 ` [PATCH v4 02/10] x86/time.c: Scale host TSC in pvclock properly Haozhong Zhang
2016-01-18 13:42   ` Jan Beulich
2016-01-19  0:29     ` Haozhong Zhang
2016-01-17 21:58 ` [PATCH v4 03/10] svm: Remove redundant TSC scaling in svm_set_tsc_offset() Haozhong Zhang
2016-01-17 21:58 ` [PATCH v4 04/10] x86/hvm: Collect information of TSC scaling ratio Haozhong Zhang
2016-01-18 10:45   ` Egger, Christoph
2016-01-19  3:19     ` Haozhong Zhang
2016-02-05 11:41   ` Jan Beulich
2016-02-16  7:59     ` Zhang, Haozhong
2016-01-17 21:58 ` [PATCH v4 05/10] x86: Add functions for 64-bit integer arithmetic Haozhong Zhang
2016-02-05 13:36   ` Jan Beulich
2016-02-16  9:02     ` Zhang, Haozhong
2016-02-16  9:39       ` Jan Beulich
2016-02-16  9:57         ` Haozhong Zhang
2016-01-17 21:58 ` [PATCH v4 06/10] x86/hvm: Setup TSC scaling ratio Haozhong Zhang
2016-02-05 13:54   ` Jan Beulich
2016-02-16  9:44     ` Zhang, Haozhong
2016-02-16 10:12       ` Jan Beulich
2016-01-17 21:58 ` [PATCH v4 07/10] x86/hvm: Replace architecture TSC scaling by a common function Haozhong Zhang
2016-01-17 21:58 ` [PATCH v4 08/10] x86/hvm: Move saving/loading vcpu's TSC to common code Haozhong Zhang
2016-01-17 21:58 ` [PATCH v4 09/10] vmx: Add VMX RDTSC(P) scaling support Haozhong Zhang
2016-01-19  2:55   ` [RESEND PATCH " Haozhong Zhang
2016-02-05 14:06     ` Jan Beulich
2016-02-16  7:59       ` Zhang, Haozhong
2016-01-17 21:58 ` [PATCH v4 10/10] docs: Add descriptions of TSC scaling in xl.cfg and tscmode.txt Haozhong Zhang
2016-02-01  5:50 ` [PATCH v4 00/10] Add VMX TSC scaling support Haozhong Zhang
2016-02-01  7:54   ` Jan Beulich

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.