TianoCore EDK2 master
CpuTimerLib.c
Go to the documentation of this file.
1
9#include <Base.h>
10#include <Library/TimerLib.h>
11#include <Library/BaseLib.h>
12#include <Library/PcdLib.h>
13#include <Library/DebugLib.h>
14#include <Register/Cpuid.h>
15
16GUID mCpuCrystalFrequencyHobGuid = {
17 0xe1ec5ad0, 0x8569, 0x46bd, { 0x8d, 0xcd, 0x3b, 0x9f, 0x6f, 0x45, 0x82, 0x7a }
18};
19
28UINT64
30 VOID
31 );
32
41UINT64
43 VOID
44 )
45{
46 UINT64 TscFrequency;
47 UINT64 CoreXtalFrequency;
48 UINT32 RegEax;
49 UINT32 RegEbx;
50 UINT32 RegEcx;
51
52 //
53 // Use CPUID leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Information
54 // EBX returns 0 if not supported. ECX, if non zero, provides Core Xtal Frequency in hertz.
55 // TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX.
56 //
57 AsmCpuid (CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, NULL);
58
59 //
60 // If EAX or EBX returns 0, the XTAL ratio is not enumerated.
61 //
62 if ((RegEax == 0) || (RegEbx == 0)) {
63 ASSERT (RegEax != 0);
64 ASSERT (RegEbx != 0);
65 return 0;
66 }
67
68 //
69 // If ECX returns 0, the XTAL frequency is not enumerated.
70 // And PcdCpuCoreCrystalClockFrequency defined should base on processor series.
71 //
72 if (RegEcx == 0) {
73 CoreXtalFrequency = PcdGet64 (PcdCpuCoreCrystalClockFrequency);
74 } else {
75 CoreXtalFrequency = (UINT64)RegEcx;
76 }
77
78 //
79 // Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX
80 //
81 TscFrequency = DivU64x32 (MultU64x32 (CoreXtalFrequency, RegEbx) + (UINT64)(RegEax >> 1), RegEax);
82
83 return TscFrequency;
84}
85
95VOID
97 IN UINT64 Delay
98 )
99{
100 UINT64 Ticks;
101
102 //
103 // The target timer count is calculated here
104 //
105 Ticks = AsmReadTsc () + Delay;
106
107 //
108 // Wait until time out
109 // Timer wrap-arounds are NOT handled correctly by this function.
110 // Thus, this function must be called within 10 years of reset since
111 // Intel guarantees a minimum of 10 years before the TSC wraps.
112 //
113 while (AsmReadTsc () <= Ticks) {
114 CpuPause ();
115 }
116}
117
128UINTN
129EFIAPI
131 IN UINTN MicroSeconds
132 )
133{
135 DivU64x32 (
136 MultU64x64 (
137 MicroSeconds,
139 ),
140 1000000u
141 )
142 );
143
144 return MicroSeconds;
145}
146
157UINTN
158EFIAPI
160 IN UINTN NanoSeconds
161 )
162{
164 DivU64x32 (
165 MultU64x64 (
166 NanoSeconds,
168 ),
169 1000000000u
170 )
171 );
172
173 return NanoSeconds;
174}
175
188UINT64
189EFIAPI
191 VOID
192 )
193{
194 return AsmReadTsc ();
195}
196
220UINT64
221EFIAPI
223 OUT UINT64 *StartValue OPTIONAL,
224 OUT UINT64 *EndValue OPTIONAL
225 )
226{
227 if (StartValue != NULL) {
228 *StartValue = 0;
229 }
230
231 if (EndValue != NULL) {
232 *EndValue = 0xffffffffffffffffULL;
233 }
234
236}
237
249UINT64
250EFIAPI
252 IN UINT64 Ticks
253 )
254{
255 UINT64 Frequency;
256 UINT64 NanoSeconds;
257 UINT64 Remainder;
258 INTN Shift;
259
261
262 //
263 // Ticks
264 // Time = --------- x 1,000,000,000
265 // Frequency
266 //
267 NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);
268
269 //
270 // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.
271 // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,
272 // i.e. highest bit set in Remainder should <= 33.
273 //
274 Shift = MAX (0, HighBitSet64 (Remainder) - 33);
275 Remainder = RShiftU64 (Remainder, (UINTN)Shift);
276 Frequency = RShiftU64 (Frequency, (UINTN)Shift);
277 NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);
278
279 return NanoSeconds;
280}
UINT64 UINTN
INT64 INTN
#define NULL
Definition: Base.h:312
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define MAX(a, b)
Definition: Base.h:888
UINT64 EFIAPI AsmReadTsc(VOID)
Definition: GccInline.c:555
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
UINT64 EFIAPI MultU64x64(IN UINT64 Multiplicand, IN UINT64 Multiplier)
Definition: MultU64x64.c:27
VOID EFIAPI CpuPause(VOID)
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
INTN EFIAPI HighBitSet64(IN UINT64 Operand)
Definition: HighBitSet64.c:27
UINT64 EFIAPI GetPerformanceCounterProperties(OUT UINT64 *StartValue OPTIONAL, OUT UINT64 *EndValue OPTIONAL)
Definition: CpuTimerLib.c:222
UINT64 EFIAPI GetTimeInNanoSecond(IN UINT64 Ticks)
Definition: CpuTimerLib.c:251
UINT64 InternalGetPerformanceCounterFrequency(VOID)
VOID InternalCpuDelay(IN UINT64 Delay)
Definition: CpuTimerLib.c:96
UINT64 CpuidCoreClockCalculateTscFrequency(VOID)
Definition: CpuTimerLib.c:42
UINT64 EFIAPI GetPerformanceCounter(VOID)
Definition: CpuTimerLib.c:190
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
Definition: CpuTimerLib.c:130
UINTN EFIAPI NanoSecondDelay(IN UINTN NanoSeconds)
Definition: CpuTimerLib.c:159
#define ASSERT(Expression)
Definition: DebugLib.h:391
#define CPUID_TIME_STAMP_COUNTER
Definition: Cpuid.h:3154
UINT32 EFIAPI AsmCpuid(IN UINT32 Index, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuId.c:36
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
Definition: Base.h:213