[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH] Sample 'RealTimeIsUniversal' at boot time...
...and report via the XENBUS_SHARED_INFO GetTime method The DWORD registry value: HKLM\System\CurrentControlSet\Control\TimeZoneInformation\RealTimeIsUniversal determines whether Windows programs the RTC in local time or UTC. If the value is zero or missing (which is the default) then the RTC will be programmed in local time, otherwise it will be programmed in UTC. Since the emulated RTC and the Xen wall-clock are kept in sync, it is necessary to know which mode Windows is operating in to correctly interpret the wall-clock value. This patch checks the registry value on boot (it is necessary to reboot after modifying it for it to take effect) and reports the RTC operating mode along-side the Xen wall-clock in a updated GetTime method in version 3 of the XENBUS_SHARED_INFO interface. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- include/revision.h | 3 +- include/shared_info_interface.h | 36 +++++++++++++++--- include/xen.h | 6 +++ src/xen/system.c | 66 ++++++++++++++++++++++++++++++++ src/xenbus/shared_info.c | 84 +++++++++++++++++++++++++++++++---------- 5 files changed, 169 insertions(+), 26 deletions(-) diff --git a/include/revision.h b/include/revision.h index 28ee461..b214152 100644 --- a/include/revision.h +++ b/include/revision.h @@ -55,6 +55,7 @@ DEFINE_REVISION(0x09000002, 1, 2, 7, 1, 2, 1, 1, 2, 1, 1, 1), \ DEFINE_REVISION(0x09000003, 1, 2, 8, 1, 2, 1, 1, 2, 1, 1, 1), \ DEFINE_REVISION(0x09000004, 1, 2, 8, 1, 2, 1, 1, 3, 1, 1, 1), \ - DEFINE_REVISION(0x09000005, 1, 2, 8, 1, 2, 1, 2, 4, 1, 1, 1) + DEFINE_REVISION(0x09000005, 1, 2, 8, 1, 2, 1, 2, 4, 1, 1, 1), \ + DEFINE_REVISION(0x09000006, 1, 3, 8, 1, 2, 1, 2, 4, 1, 1, 1) #endif // _REVISION_H diff --git a/include/shared_info_interface.h b/include/shared_info_interface.h index a0613ce..f99bcb6 100644 --- a/include/shared_info_interface.h +++ b/include/shared_info_interface.h @@ -113,15 +113,23 @@ typedef BOOLEAN IN ULONG Port ); +typedef LARGE_INTEGER +(*XENBUS_SHARED_INFO_GET_TIME_V2)( + IN PINTERFACE Interface + ); + /*! \typedef XENBUS_SHARED_INFO_GET_TIME - \brief Return the wallclock time from the shared info + \brief Retrieve the wallclock time from the shared info \param Interface The interface header - \return The wallclock time in units of 100ns + \param Time The wallclock time + \param Local Set, on return, if the wallclock is in local time */ -typedef LARGE_INTEGER +typedef VOID (*XENBUS_SHARED_INFO_GET_TIME)( - IN PINTERFACE Interface + IN PINTERFACE Interface, + OUT PLARGE_INTEGER Time, + OUT PBOOLEAN Local ); // {7E73C34F-1640-4649-A8F3-263BC930A004} @@ -141,10 +149,26 @@ struct _XENBUS_SHARED_INFO_INTERFACE_V2 { XENBUS_SHARED_INFO_EVTCHN_ACK SharedInfoEvtchnAck; XENBUS_SHARED_INFO_EVTCHN_MASK SharedInfoEvtchnMask; XENBUS_SHARED_INFO_EVTCHN_UNMASK SharedInfoEvtchnUnmask; + XENBUS_SHARED_INFO_GET_TIME_V2 SharedInfoGetTimeVersion2; +}; + +/*! \struct _XENBUS_SHARED_INFO_INTERFACE_V3 + \brief SHARED_INFO interface version 3 + \ingroup interfaces +*/ +struct _XENBUS_SHARED_INFO_INTERFACE_V3 { + INTERFACE Interface; + XENBUS_SHARED_INFO_ACQUIRE SharedInfoAcquire; + XENBUS_SHARED_INFO_RELEASE SharedInfoRelease; + XENBUS_SHARED_INFO_UPCALL_PENDING SharedInfoUpcallPending; + XENBUS_SHARED_INFO_EVTCHN_POLL SharedInfoEvtchnPoll; + XENBUS_SHARED_INFO_EVTCHN_ACK SharedInfoEvtchnAck; + XENBUS_SHARED_INFO_EVTCHN_MASK SharedInfoEvtchnMask; + XENBUS_SHARED_INFO_EVTCHN_UNMASK SharedInfoEvtchnUnmask; XENBUS_SHARED_INFO_GET_TIME SharedInfoGetTime; }; -typedef struct _XENBUS_SHARED_INFO_INTERFACE_V2 XENBUS_SHARED_INFO_INTERFACE, *PXENBUS_SHARED_INFO_INTERFACE; +typedef struct _XENBUS_SHARED_INFO_INTERFACE_V3 XENBUS_SHARED_INFO_INTERFACE, *PXENBUS_SHARED_INFO_INTERFACE; /*! \def XENBUS_SHARED_INFO \brief Macro at assist in method invocation @@ -155,6 +179,6 @@ typedef struct _XENBUS_SHARED_INFO_INTERFACE_V2 XENBUS_SHARED_INFO_INTERFACE, *P #endif // _WINDLL #define XENBUS_SHARED_INFO_INTERFACE_VERSION_MIN 2 -#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX 2 +#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX 3 #endif // _XENBUS_SHARED_INFO_H diff --git a/include/xen.h b/include/xen.h index edfadc9..171fa4e 100644 --- a/include/xen.h +++ b/include/xen.h @@ -458,4 +458,10 @@ SystemMaximumPhysicalAddress( VOID ); +XEN_API +BOOLEAN +SystemRealTimeIsUniversal( + VOID + ); + #endif // _XEN_H diff --git a/src/xen/system.c b/src/xen/system.c index a7b46d1..45fe3b6 100644 --- a/src/xen/system.c +++ b/src/xen/system.c @@ -63,6 +63,7 @@ typedef struct _SYSTEM_CONTEXT { PVOID PowerStateHandle; PVOID ProcessorChangeHandle; PHYSICAL_ADDRESS MaximumPhysicalAddress; + BOOLEAN RealTimeIsUniversal; } SYSTEM_CONTEXT, *PSYSTEM_CONTEXT; static SYSTEM_CONTEXT SystemContext; @@ -912,6 +913,51 @@ SystemDeregisterPowerStateCallback( Context->PowerStateHandle = NULL; } +static NTSTATUS +SystemGetTimeInformation( + VOID + ) +{ + PSYSTEM_CONTEXT Context = &SystemContext; + UNICODE_STRING Unicode; + HANDLE Key; + ULONG RealTimeIsUniversal; + NTSTATUS status; + + RtlInitUnicodeString(&Unicode, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation"); + + status = RegistryOpenKey(NULL, &Unicode, KEY_READ, &Key); + if (!NT_SUCCESS(status)) + goto fail1; + + status = RegistryQueryDwordValue(Key, "RealTimeIsUniversal", + &RealTimeIsUniversal); + if (!NT_SUCCESS(status)) { + if (status != STATUS_OBJECT_NAME_NOT_FOUND) + goto fail2; + + RealTimeIsUniversal = 0; + } + + Context->RealTimeIsUniversal = RealTimeIsUniversal ? TRUE : FALSE; + + Info("%s\n", Context->RealTimeIsUniversal ? "TRUE" : "FALSE"); + + RegistryCloseKey(Key); + + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + + RegistryCloseKey(Key); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + NTSTATUS SystemInitialize( VOID @@ -951,8 +997,17 @@ SystemInitialize( if (!NT_SUCCESS(status)) goto fail7; + status = SystemGetTimeInformation(); + if (!NT_SUCCESS(status)) + goto fail8; + return STATUS_SUCCESS; +fail8: + Error("fail8\n"); + + SystemDeregisterPowerStateCallback(); + fail7: Error("fail7\n"); @@ -1038,6 +1093,17 @@ SystemMaximumPhysicalAddress( return Context->MaximumPhysicalAddress; } +XEN_API +BOOLEAN +SystemRealTimeIsUniversal( + VOID + ) +{ + PSYSTEM_CONTEXT Context = &SystemContext; + + return Context->RealTimeIsUniversal; +} + VOID SystemTeardown( VOID diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c index adae7ff..a95318c 100644 --- a/src/xenbus/shared_info.c +++ b/src/xenbus/shared_info.c @@ -309,11 +309,15 @@ SharedInfoEvtchnUnmask( return SharedInfoTestBit(&Shared->evtchn_pending[SelectorBit], PortBit); } -static LARGE_INTEGER +static VOID SharedInfoGetTime( - IN PINTERFACE Interface + IN PINTERFACE Interface, + OUT PLARGE_INTEGER Time, + OUT PBOOLEAN Local ) { +#define NS_PER_S 1000000000ull + PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context; shared_info_t *Shared; ULONG WcVersion; @@ -325,8 +329,7 @@ SharedInfoGetTime( ULONGLONG SystemTime; ULONG TscSystemMul; CHAR TscShift; - LARGE_INTEGER Now; - TIME_FIELDS Time; + TIME_FIELDS TimeFields; KIRQL Irql; // Make sure we don't suspend @@ -379,30 +382,44 @@ SharedInfoGetTime( NanoSeconds); Trace("TIME SINCE BOOT: Seconds = %llu NanoSeconds = %llu\n", - SystemTime / 1000000000ull, - SystemTime % 1000000000ull); + SystemTime / NS_PER_S, + SystemTime % NS_PER_S); // Convert wallclock from Unix epoch (1970) to Windows epoch (1601) Seconds += 11644473600ull; // Add in time since host boot - Seconds += SystemTime / 1000000000ull; - NanoSeconds += SystemTime % 1000000000ull; + Seconds += SystemTime / NS_PER_S; + NanoSeconds += SystemTime % NS_PER_S; - // Convert to system time format - Now.QuadPart = (Seconds * 10000000ull) + (NanoSeconds / 100ull); + Time->QuadPart = ((Seconds * NS_PER_S) + NanoSeconds) / 100; - RtlTimeToTimeFields(&Now, &Time); + RtlTimeToTimeFields(Time, &TimeFields); Trace("TOD: %04u/%02u/%02u %02u:%02u:%02u\n", - Time.Year, - Time.Month, - Time.Day, - Time.Hour, - Time.Minute, - Time.Second); - - return Now; + TimeFields.Year, + TimeFields.Month, + TimeFields.Day, + TimeFields.Hour, + TimeFields.Minute, + TimeFields.Second); + + if ( Local ) + *Local = !SystemRealTimeIsUniversal(); + +#undef NS_PER_S +} + +static LARGE_INTEGER +SharedInfoGetTimeVersion2( + IN PINTERFACE Interface + ) +{ + LARGE_INTEGER Time; + + SharedInfoGetTime(Interface, &Time, NULL); + + return Time; } static VOID @@ -672,6 +689,18 @@ static struct _XENBUS_SHARED_INFO_INTERFACE_V2 SharedInfoInterfaceVersion2 = { SharedInfoEvtchnAck, SharedInfoEvtchnMask, SharedInfoEvtchnUnmask, + SharedInfoGetTimeVersion2 +}; + +static struct _XENBUS_SHARED_INFO_INTERFACE_V3 SharedInfoInterfaceVersion3 = { + { sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V3), 3, NULL, NULL, NULL }, + SharedInfoAcquire, + SharedInfoRelease, + SharedInfoUpcallPending, + SharedInfoEvtchnPoll, + SharedInfoEvtchnAck, + SharedInfoEvtchnMask, + SharedInfoEvtchnUnmask, SharedInfoGetTime }; @@ -749,6 +778,23 @@ SharedInfoGetInterface( status = STATUS_SUCCESS; break; } + case 3: { + struct _XENBUS_SHARED_INFO_INTERFACE_V3 *SharedInfoInterface; + + SharedInfoInterface = (struct _XENBUS_SHARED_INFO_INTERFACE_V3 *)Interface; + + status = STATUS_BUFFER_OVERFLOW; + if (Size < sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V3)) + break; + + *SharedInfoInterface = SharedInfoInterfaceVersion3; + + ASSERT3U(Interface->Version, ==, Version); + Interface->Context = Context; + + status = STATUS_SUCCESS; + break; + } default: status = STATUS_NOT_SUPPORTED; break; -- 2.5.3 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |