References: bsc#1026236

# Commit 4fc380ac0077ecd6b0e0013ca7ca977cb7361662
# Date 2017-03-20 09:27:35 +0100
# Author Boris Ostrovsky <boris.ostrovsky@oracle.com>
# Committer Jan Beulich <jbeulich@suse.com>
x86/time: don't use virtual TSC if host and guest frequencies are equal

Commit 82713ec8d2 ("x86: use native RDTSC(P) execution when guest and
host frequencies are the same") left out optimization for PV guests
when host and guest run at the same frequency.

For such a case we should be able not to use virtual TSC regardless
of whether we are runing before or after a migration (i.e. regardless
of incarnation value).

Suggested-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
[jb: retain parts of the original comment]
Reviewed-by: Jan Beulich <jbeulich@suse.com>

# Commit 9614f0246688d1e4cee4d6bec47894b6e289c721
# Date 2017-03-30 15:12:25 +0200
# Author Boris Ostrovsky <boris.ostrovsky@oracle.com>
# Committer Jan Beulich <jbeulich@suse.com>
docs: update xen-tscmode.pod.7 to reflect default TSC mode changes

A number of changes have been made to how we determine whether TSC
is emulated (e.g. commit 4fc380ac0077 ("x86/time: don't use virtual TSC
if host and guest frequencies are equal")).

Update the man page to reflect those changes

Suggested-by: Olaf Hering <olaf@aepfle.de>
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>

--- a/docs/misc/tscmode.txt
+++ b/docs/misc/tscmode.txt
@@ -168,12 +168,12 @@ The default mode (tsc_mode==0) checks TS
 hardware on which the virtual machine is launched.  If it is
 TSC-safe, rdtsc will execute at hardware speed; if it is not, rdtsc
 will be emulated.  Once a virtual machine is save/restored or migrated,
-however, there are two possibilities:  For a paravirtualized (PV) domain,
-TSC will always be emulated.  For a fully-virtualized (HVM) domain,
-TSC remains native IF the source physical machine and target physical machine
-have the same TSC frequency; else TSC is emulated.  Note that, though
-emulated, the "apparent" TSC frequency will be the TSC frequency
-of the initial physical machine, even after migration.
+however, there are two possibilities: TSC remains native IF the source
+physical machine and target physical machine have the same TSC frequency
+(or, for HVM/PVH guests, if TSC scaling support is available); else TSC
+is emulated.  Note that, though emulated, the "apparent" TSC frequency
+will be the TSC frequency of the initial physical machine, even after
+migration.
 
 For environments where both TSC-safeness AND highest performance
 even across migration is a requirement, application code can be specially
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -1924,17 +1924,18 @@ void tsc_set_info(struct domain *d,
         d->arch.vtsc_offset = get_s_time() - elapsed_nsec;
         d->arch.tsc_khz = gtsc_khz ?: cpu_khz;
         set_time_scale(&d->arch.vtsc_to_ns, d->arch.tsc_khz * 1000);
+
         /*
-         * In default mode use native TSC if the host has safe TSC and:
-         *  HVM/PVH: host and guest frequencies are the same (either
-         *           "naturally" or via TSC scaling)
-         *  PV: guest has not migrated yet (and thus arch.tsc_khz == cpu_khz)
+         * In default mode use native TSC if the host has safe TSC and
+         * host and guest frequencies are the same (either "naturally" or
+         * - for HVM/PVH - via TSC scaling).
+         * When a guest is created, gtsc_khz is passed in as zero, making
+         * d->arch.tsc_khz == cpu_khz. Thus no need to check incarnation.
          */
         if ( tsc_mode == TSC_MODE_DEFAULT && host_tsc_is_safe() &&
-             (has_hvm_container_domain(d) ?
-              (d->arch.tsc_khz == cpu_khz ||
-               hvm_get_tsc_scaling_ratio(d->arch.tsc_khz)) :
-              incarnation == 0) )
+             (d->arch.tsc_khz == cpu_khz ||
+              (has_hvm_container_domain(d) &&
+               hvm_get_tsc_scaling_ratio(d->arch.tsc_khz))) )
         {
     case TSC_MODE_NEVER_EMULATE:
             d->arch.vtsc = 0;
