ReactOS  0.4.15-dev-2700-g4b4ffa9
tsc.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS HAL
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: hal/halx86/apic/tsc.c
5  * PURPOSE: HAL Routines for TSC handling
6  * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <hal.h>
12 #include "tsc.h"
13 #define NDEBUG
14 #include <debug.h>
15 
17 
21 
22 #define RTC_MODE 6 /* Mode 6 is 1024 Hz */
23 #define SAMPLE_FREQENCY ((32768 << 1) >> RTC_MODE)
24 
25 /* PRIVATE FUNCTIONS *********************************************************/
26 
27 static
28 ULONG64
30  ULONG XMax,
31  ULONG64 *ArrayY)
32 {
33  ULONG X, SumXX;
34  ULONG64 SumXY;
35 
36  /* Calculate the sum of the squares of X */
37  SumXX = (XMax * (XMax + 1) * (2*XMax + 1)) / 6;
38 
39  /* Calculate the sum of the differences to the first value
40  weighted by x */
41  for (SumXY = 0, X = 1; X <= XMax; X++)
42  {
43  SumXY += X * (ArrayY[X] - ArrayY[0]);
44  }
45 
46  /* Account for sample frequency */
47  SumXY *= SAMPLE_FREQENCY;
48 
49  /* Return the quotient of the sums */
50  return (SumXY + (SumXX/2)) / SumXX;
51 }
52 
53 VOID
54 NTAPI
56 {
58  KIDTENTRY OldIdtEntry, *IdtPointer;
59  PKPCR Pcr = KeGetPcr();
60  UCHAR RegisterA, RegisterB;
61 
62  /* Check if the CPU supports RDTSC */
63  if (!(KeGetCurrentPrcb()->FeatureBits & KF_RDTSC))
64  {
65  KeBugCheck(HAL_INITIALIZATION_FAILED);
66  }
67 
68  /* Save flags and disable interrupts */
69  Flags = __readeflags();
70  _disable();
71 
72  /* Enable the periodic interrupt in the CMOS */
73  RegisterB = HalpReadCmos(RTC_REGISTER_B);
75 
76  /* Modify register A to RTC_MODE to get SAMPLE_FREQENCY */
77  RegisterA = HalpReadCmos(RTC_REGISTER_A);
78  RegisterA = (RegisterA & 0xF0) | RTC_MODE;
79  HalpWriteCmos(RTC_REGISTER_A, RegisterA);
80 
81  /* Save old IDT entry */
82  IdtPointer = KiGetIdtEntry(Pcr, HalpRtcClockVector);
83  OldIdtEntry = *IdtPointer;
84 
85  /* Set the calibration ISR */
87 
88  /* Reset TSC value to 0 */
90 
91  /* Enable the timer interrupt */
93 
94  /* Read register C, so that the next interrupt can happen */
96 
97  /* Wait for completion */
98  _enable();
100  _disable();
101 
102  /* Disable the periodic interrupt in the CMOS */
104 
105  /* Disable the timer interrupt */
107 
108  /* Restore old IDT entry */
109  *IdtPointer = OldIdtEntry;
110 
111  /* Calculate an average, using simplified linear regression */
114 
115  /* Restore flags */
117 
118 }
119 
120 VOID
121 NTAPI
123 {
124  // Timer interrupt is now active
125 
127 
128  KeGetPcr()->StallScaleFactor = (ULONG)(HalpCpuClockFrequency.QuadPart / 1000000);
129 }
130 
131 /* PUBLIC FUNCTIONS ***********************************************************/
132 
134 NTAPI
136  OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
137 {
139 
140  /* Make sure it's calibrated */
142 
143  /* Does the caller want the frequency? */
144  if (PerformanceFrequency)
145  {
146  /* Return tsc frequency */
147  *PerformanceFrequency = HalpCpuClockFrequency;
148  }
149 
150  /* Return the current value */
151  Result.QuadPart = __rdtsc();
152  return Result;
153 }
154 
155 VOID
156 NTAPI
158 {
159  ULONG64 StartTime, EndTime;
160 
161  /* Get the initial time */
162  StartTime = __rdtsc();
163 
164  /* Calculate the ending time */
165  EndTime = StartTime + KeGetPcr()->StallScaleFactor * MicroSeconds;
166 
167  /* Loop until time is elapsed */
168  while (__rdtsc() < EndTime);
169 }
170 
171 VOID
172 NTAPI
174  IN volatile PLONG Count,
175  IN ULONGLONG NewCount)
176 {
178  ASSERT(FALSE);
179 }
180 
#define INITIAL_STALL_COUNT
Definition: processor.c:22
#define IN
Definition: typedefs.h:39
VOID FORCEINLINE HalpWriteCmos(IN UCHAR Reg, IN UCHAR Value)
Definition: cmos.c:35
BOOLEAN NTAPI HalEnableSystemInterrupt(IN ULONG Vector, IN KIRQL Irql, IN KINTERRUPT_MODE InterruptMode)
Definition: pic.c:295
VOID NTAPI HalpInitializeTsc(VOID)
Definition: tsc.c:55
#define RTC_MODE
Definition: tsc.c:22
#define _ReadWriteBarrier()
Definition: intrin_arm.h:36
VOID NTAPI KeStallExecutionProcessor(ULONG MicroSeconds)
Definition: tsc.c:157
UCHAR HalpRtcClockVector
Definition: tsc.c:20
void __cdecl _enable(void)
Definition: intrin_arm.h:373
#define KF_RDTSC
Definition: ketypes.h:144
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
PPC_QUAL unsigned long long __rdtsc(void)
Definition: intrin_ppc.h:688
#define MSR_RDTSC
Definition: tsc.h:6
VOID NTAPI HalCalibratePerformanceCounter(IN volatile PLONG Count, IN ULONGLONG NewCount)
Definition: tsc.c:173
Definition: ke.h:289
static LARGE_INTEGER StartTime
Definition: sys_arch.c:18
#define SAMPLE_FREQENCY
Definition: tsc.c:23
#define KeGetPcr()
Definition: ke.h:26
UCHAR TscCalibrationPhase
Definition: tsc.c:18
VOID NTAPI HalDisableSystemInterrupt(IN ULONG Vector, IN KIRQL Irql)
Definition: pic.c:309
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CLOCK_LEVEL
#define RTC_REG_B_PI
Definition: halhw.h:16
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1675
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1427
#define NUM_SAMPLES
Definition: tsc.h:5
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
UCHAR FORCEINLINE HalpReadCmos(IN UCHAR Reg)
Definition: cmos.c:24
int Count
Definition: noreturn.cpp:7
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ASSERT(a)
Definition: mode.c:44
uint64_t ULONGLONG
Definition: typedefs.h:67
#define RTC_REGISTER_B
Definition: halp.h:17
void __cdecl TscCalibrationISR(void)
unsigned __int64 ULONG64
Definition: imports.h:198
unsigned char UCHAR
Definition: xmlstorage.h:181
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1670
#define RTC_REGISTER_C
Definition: halhw.h:17
PPC_QUAL void __writemsr(const unsigned long Value)
Definition: intrin_ppc.h:748
FORCEINLINE VOID KeRegisterInterruptHandler(IN ULONG Vector, IN PVOID Handler)
Definition: ke.h:297
ULONG64 TscCalibrationArray[NUM_SAMPLES]
Definition: tsc.c:19
#define KiGetIdtEntry(Pcr, Vector)
Definition: tsc.h:17
#define RTC_REGISTER_A
Definition: xboxrtc.c:21
#define OUT
Definition: typedefs.h:40
void __cdecl _disable(void)
Definition: intrin_arm.h:365
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:115
LARGE_INTEGER NTAPI KeQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
Definition: tsc.c:135
LARGE_INTEGER HalpCpuClockFrequency
Definition: tsc.c:16
static ULONG64 DoLinearRegression(ULONG XMax, ULONG64 *ArrayY)
Definition: tsc.c:29
VOID NTAPI HalpCalibrateStallExecution(VOID)
Definition: tsc.c:122
signed int * PLONG
Definition: retypes.h:5
#define X(b, s)
LONGLONG QuadPart
Definition: typedefs.h:114
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68