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

Re: [win-pv-devel] [PATCH] Wallclock Time Calculation Checks Update Versions For Consistency



I tested the change on XenServer 7.1 on Windows Server 2008 R2, Windows Server 
2012, and Windows Server 2012 R2. You can run this powershell command to see 
the difference between the dom0 time and the domU time: ("OS: {0:o}`r`nXenTime: 
{1:o}" -f (Get-Date).ToUniversalTime(), 
[DateTime]::FromFileTimeUtc((Get-WmiObject -Namespace root\wmi -Class 
XenProjectXenStoreBase).XenTime))

It's off by at most a few seconds, which I have read is about the limit of 
cross-domain timekeeping accuracy in Xen.

-----Original Message-----
From: Paul Durrant [mailto:Paul.Durrant@xxxxxxxxxx] 
Sent: Monday, August 21, 2017 7:58 AM
To: Mackay, Eric <mackayem@xxxxxxxxxx>; win-pv-devel@xxxxxxxxxxxxxxxxxxxx
Subject: RE: [win-pv-devel] [PATCH] Wallclock Time Calculation Checks Update 
Versions For Consistency

> -----Original Message-----
> From: win-pv-devel [mailto:win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx] 
> On Behalf Of Eric Mackay
> Sent: 19 August 2017 01:23
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Eric Mackay <mackayem@xxxxxxxxxx>
> Subject: [win-pv-devel] [PATCH] Wallclock Time Calculation Checks 
> Update Versions For Consistency
> 
> Checking the shared_info update versions is necessary to get a 
> consistent set of values. The version is incremented once when the 
> update starts, and then incremented again after the update has 
> completed. To verify that a set of values obtained from shared_info is 
> consistent, the version must not only look at equality of versions, 
> but the version must also be even. Data can only be safely be captured 
> within the version check loop.
> 
> There is no need to use a hypercall to get the system time, since this 
> is alredy captured in the shared_info struct. A cached version of the 
> time since boot is stored in structures for each vcpu, but this has to 
> be combined with the timestamp counter and some scaling factors to get 
> the actual current time since boot.
> 
> Clock synchronization can also occur, and the dom0 will ensure that 
> the values in the shared_info and vcpu_time_info structs are kept 
> current to reflect this.
> 
> Signed-off-by: Eric Mackay <mackayem@xxxxxxxxxx>

Eric,

The change looks good to me. What sort of testing has been done on this?

  Cheers,

    Paul

> ---
>  src/xenbus/shared_info.c | 65
> ++++++++++++++++++++++++++++++++++++------------
>  1 file changed, 49 insertions(+), 16 deletions(-)
> 
> diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c index 
> d6babcf..2666f76 100644
> --- a/src/xenbus/shared_info.c
> +++ b/src/xenbus/shared_info.c
> @@ -329,6 +329,10 @@ SharedInfoEvtchnUnmask(
>      return SharedInfoTestBit(&Shared->evtchn_pending[SelectorBit],
> PortBit);
>  }
> 
> +#ifndef BooleanFlagOn
> +#define BooleanFlagOn(F,SF)   ((BOOLEAN)(((F) & (SF)) != 0))
> +#endif
> +
>  static LARGE_INTEGER
>  SharedInfoGetTime(
>      IN  PINTERFACE              Interface
> @@ -336,51 +340,80 @@ SharedInfoGetTime(  {
>      PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context;
>      shared_info_t               *Shared;
> -    ULONG                       Version;
> +    ULONG                       WcVersion;
> +    ULONG                       TimeVersion;
>      ULONGLONG                   Seconds;
>      ULONGLONG                   NanoSeconds;
> +    ULONGLONG                   Timestamp;
> +    ULONGLONG                   Tsc;
> +    ULONGLONG                   SystemTime;
> +    ULONG                       TscSystemMul;
> +    CHAR                        TscShift;
>      LARGE_INTEGER               Now;
>      TIME_FIELDS                 Time;
>      KIRQL                       Irql;
> -    NTSTATUS                    status;
> 
>      // Make sure we don't suspend
> -    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
> +    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
> 
>      Shared = Context->Shared;
> 
> +    // Loop until we can read a consistent set of values from the 
> + same update
>      do {
> -        Version = Shared->wc_version;
> +        WcVersion = Shared->wc_version;
> +        TimeVersion = Shared->vcpu_info[0].time.version;
>          KeMemoryBarrier();
> 
> +        // Wallclock time at system time zero (guest boot or resume)
>          Seconds = Shared->wc_sec;
>          NanoSeconds = Shared->wc_nsec;
> +
> +        // Cached time in nanoseconds since guest boot
> +        SystemTime = Shared->vcpu_info[0].time.system_time;
> +
> +        // Timestamp counter value when these time values were last updated
> +        Timestamp = Shared->vcpu_info[0].time.tsc_timestamp;
> +
> +        // Timestamp modifiers
> +        TscShift = Shared->vcpu_info[0].time.tsc_shift;
> +        TscSystemMul = Shared->vcpu_info[0].time.tsc_to_system_mul;
>          KeMemoryBarrier();
> -    } while (Shared->wc_version != Version);
> 
> -    // Get the number of nanoseconds since boot
> -    status = HvmGetTime(&Now);
> -    if (!NT_SUCCESS(status))
> -        Now.QuadPart = Shared->vcpu_info[0].time.system_time;
> +    // Version is incremented to indicate update in progress
> +    // LSB of version is set if update in progress
> +    // Version is incremented again once update has completed
> +    } while (Shared->wc_version != WcVersion ||
> +             Shared->vcpu_info[0].time.version != TimeVersion ||
> +             BooleanFlagOn(WcVersion, 0x1) ||
> +             BooleanFlagOn(TimeVersion, 0x1));
> +
> +    // Read counter ticks
> +    Tsc = ReadTimeStampCounter();
> 
>      KeLowerIrql(Irql);
> 
> -    Trace("WALLCLOCK: Seconds = %llu NanoSeconds = %llu\n",
> +    // Number of elapsed ticks since timestamp was captured
> +    Tsc -= Timestamp;
> +
> +    // Time in nanoseconds since boot
> +    SystemTime += ((Tsc << TscShift) * TscSystemMul) >> 32;
> +
> +    Trace("WALLCLOCK TIME AT BOOT: Seconds = %llu NanoSeconds =
> %llu\n",
>            Seconds,
>            NanoSeconds);
> 
> -    Trace("BOOT: Seconds = %llu NanoSeconds = %llu\n",
> -          Now.QuadPart / 1000000000ull,
> -          Now.QuadPart % 1000000000ull);
> +    Trace("TIME SINCE BOOT: Seconds = %llu NanoSeconds = %llu\n",
> +          SystemTime / 1000000000ull,
> +          SystemTime % 1000000000ull);
> 
>      // Convert wallclock from Unix epoch (1970) to Windows epoch (1601)
>      Seconds += 11644473600ull;
> 
>      // Add in time since host boot
> -    Seconds += Now.QuadPart / 1000000000ull;
> -    NanoSeconds += Now.QuadPart % 1000000000ull;
> +    Seconds += SystemTime / 1000000000ull;
> +    NanoSeconds += SystemTime % 1000000000ull;
> 
> -    // Converto to system time format
> +    // Convert to system time format
>      Now.QuadPart = (Seconds * 10000000ull) + (NanoSeconds / 100ull);
> 
>      RtlTimeToTimeFields(&Now, &Time);
> --
> 2.10.1.windows.1
> 
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

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