|
[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 |