[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2 31/62] x86: xen pv clock time source



On 01/12/2018 11:28 AM, Wei Liu wrote:
> It is a variant of TSC clock source.
> 
> Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx>
> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> ---
> Changes since v1:
>  - Use the mapped vcpu_info.
> ---
>  xen/arch/x86/time.c | 89 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 89 insertions(+)
> 
> diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
> index 3b654d7b7d..4cbd068d17 100644
> --- a/xen/arch/x86/time.c
> +++ b/xen/arch/x86/time.c
> @@ -29,6 +29,7 @@
>  #include <asm/mpspec.h>
>  #include <asm/processor.h>
>  #include <asm/fixmap.h>
> +#include <asm/guest.h>
>  #include <asm/mc146818rtc.h>
>  #include <asm/div64.h>
>  #include <asm/acpi.h>
> @@ -525,6 +526,91 @@ static struct platform_timesource __initdata plt_tsc =
>      .init = init_tsc,
>  };
>  
> +#ifdef CONFIG_XEN_GUEST
> +/************************************************************
> + * PLATFORM TIMER 5: XEN PV CLOCK SOURCE
> + *
> + * Xen clock source is a variant of TSC source.
> + */
> +
> +static uint64_t xen_timer_cpu_frequency(void)
> +{
> +    struct vcpu_time_info *info = &this_cpu(vcpu_info)->time;
> +    uint64_t freq;
> +
> +    freq = 1000000000ULL << 32;
> +    do_div(freq, info->tsc_to_system_mul);
> +    if ( info->tsc_shift < 0 )
> +        freq <<= -info->tsc_shift;
> +    else
> +        freq >>= info->tsc_shift;
> +
> +    return freq;
> +}
> +
> +static int64_t __init init_xen_timer(struct platform_timesource *pts)
> +{
> +    if ( !xen_guest )
> +        return 0;
> +
> +    pts->frequency = xen_timer_cpu_frequency();
> +
> +    return pts->frequency;
> +}
> +
Guests that don't have TSC_RELIABLE set in verify_tsc_reliability() you end up
evaluating this condition to true:

if ( boot_cpu_has(X86_FEATURE_CONSTANT_TSC) &&
     !boot_cpu_has(X86_FEATURE_TSC_RELIABLE) )
    time_calibration_rendezvous_fn = time_calibration_tsc_rendezvous;

And that's possibly not necessary to keep sync the TSC in sync with pvclock?

Meaning the default rendezvous function (time_calibration_std_rendezvous) might
be enough.

> +static always_inline uint64_t read_cycle(const struct vcpu_time_info *info,
> +                                         uint64_t tsc)
> +{
> +    uint64_t delta = tsc - info->tsc_timestamp;
> +    struct time_scale ts = {
> +        .shift    = info->tsc_shift,
> +        .mul_frac = info->tsc_to_system_mul,
> +    };
> +    uint64_t offset = scale_delta(delta, &ts);
> +
> +    return info->system_time + offset;
> +}
> +
> +static uint64_t read_xen_timer(void)
> +{
> +    struct vcpu_time_info *info = &this_cpu(vcpu_info)->time;
> +    uint32_t version;
> +    uint64_t ret;
> +    uint64_t last;
> +    static uint64_t last_value;
> +
> +    do {
> +        version = info->version & ~1;
> +        /* Make sure version is read before the data */
> +        smp_rmb();
> +
> +        ret = read_cycle(info, rdtsc_ordered());
> +        /* Ignore fancy flags for now */
> +

Heh :)

When the dust settles around the security issues, perhaps this patch could help
(I can formally submit it after more proper testing, but should give an
expectation on the changes).

-- >8 --
Subject: x86/time: mark pvclock as stable if supported

diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index c90524de9c..3aaa72b6bf 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -65,8 +65,12 @@ struct platform_timesource {
     s64 (*init)(struct platform_timesource *);
     void (*resume)(struct platform_timesource *);
     int counter_bits;
+    unsigned int flags;
 };

+/* Clocksource counter monotonically increases across CPUs */
+#define CLOCKSOURCE_F_STABLE    (1 << 0)
+
 static DEFINE_PER_CPU(struct cpu_time, cpu_time);

 /* Calibrate all CPUs to platform timer every EPOCH. */
@@ -533,9 +537,8 @@ static struct platform_timesource __initdata plt_tsc =
  * Xen clock source is a variant of TSC source.
  */

-static uint64_t xen_timer_cpu_frequency(void)
+static uint64_t xen_timer_cpu_frequency(struct vcpu_time_info *info)
 {
-    struct vcpu_time_info *info = &this_cpu(vcpu_info)->time;
     uint64_t freq;

     freq = 1000000000ULL << 32;
@@ -550,10 +553,20 @@ static uint64_t xen_timer_cpu_frequency(void)

 static int64_t __init init_xen_timer(struct platform_timesource *pts)
 {
+    struct vcpu_time_info *info;
+
     if ( !xen_guest )
         return 0;

-    pts->frequency = xen_timer_cpu_frequency();
+    info = &this_cpu(vcpu_info)->time;
+
+    pts->frequency = xen_timer_cpu_frequency(info);
+
+    /* Xen pvclock monotonically increases across CPUs */
+    if ( info->flags & XEN_PVCLOCK_TSC_STABLE_BIT ) {
+           pts->flags |= CLOCKSOURCE_F_STABLE;
+           printk("PV CLOCK marked as stable.\n");
+    }

     return pts->frequency;
 }
@@ -585,12 +598,14 @@ static uint64_t read_xen_timer(void)
         smp_rmb();

         ret = read_cycle(info, rdtsc_ordered());
-        /* Ignore fancy flags for now */

         /* Make sure version is reread after the data */
         smp_rmb();
     } while ( unlikely(version != info->version) );

+    if ( info->flags & XEN_PVCLOCK_TSC_STABLE_BIT )
+        return ret;
+
     /* Maintain a monotonic global value */
     do {
         last = read_atomic(&last_value);
@@ -632,6 +647,8 @@ static u64 plt_stamp64;          /* 64-bit platform counter
stamp           */
 static u64 plt_stamp;            /* hardware-width platform counter stamp   */
 static struct timer plt_overflow_timer;

+static bool clocksource_is_stable(void);
+
 static s_time_t __read_platform_stime(u64 platform_time)
 {
     u64 diff = platform_time - platform_timer_stamp;
@@ -1077,7 +1094,7 @@ static void __update_vcpu_system_time(struct vcpu *v, int
force)
      * pvclock read to check whether they can resort solely on this tuple
      * or if it further requires monotonicity checks with other vcpus.
      */
-    if ( clocksource_is_tsc() )
+    if ( clocksource_is_stable() )
         _u.flags |= XEN_PVCLOCK_TSC_STABLE_BIT;

     if ( is_hvm_domain(d) )
@@ -1564,7 +1581,7 @@ static void time_calibration(void *unused)
         .semaphore = ATOMIC_INIT(0)
     };

-    if ( clocksource_is_tsc() )
+    if ( clocksource_is_stable() )
     {
         local_irq_disable();
         r.master_stime = read_platform_stime(&r.master_tsc_stamp);
@@ -1740,6 +1757,9 @@ static int __init verify_tsc_reliability(void)
              */
             on_selected_cpus(&cpu_online_map, reset_percpu_time, NULL, 1);

+            /* TSC clocksource monotonically increases across CPUs. */
+            plt_tsc.flags |= CLOCKSOURCE_F_STABLE;
+
             /*
              * We won't do CPU Hotplug and TSC clocksource is being used which
              * means we have a reliable TSC, plus we don't sync with any other
@@ -1770,7 +1790,12 @@ static int __init verify_tsc_reliability(void)
      */
     if ( boot_cpu_has(X86_FEATURE_CONSTANT_TSC) &&
          !boot_cpu_has(X86_FEATURE_TSC_RELIABLE) )
-        time_calibration_rendezvous_fn = time_calibration_tsc_rendezvous;
+    {
+       if ( clocksource_is_stable() )
+            time_calibration_rendezvous_fn = time_calibration_nop_rendezvous;
+        else if ( plt_src.read_counter != read_xen_timer )
+            time_calibration_rendezvous_fn = time_calibration_tsc_rendezvous;
+    }

     return 0;
 }
@@ -2057,6 +2082,23 @@ bool clocksource_is_tsc(void)
     return plt_src.read_counter == read_tsc;
 }

+static bool clocksource_is_stable(void)
+{
+    struct vcpu_time_info *info;
+
+    if ( !(plt_src.flags & CLOCKSOURCE_F_STABLE) )
+        return false;
+
+    if ( plt_src.read_counter == read_tsc )
+        return true;
+
+    info = &this_cpu(vcpu_info)->time;
+    if ( !(info->flags & XEN_PVCLOCK_TSC_STABLE_BIT) )
+        return false;
+
+    return true;
+}
+
 int host_tsc_is_safe(void)
 {
     return boot_cpu_has(X86_FEATURE_TSC_RELIABLE);

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.