TianoCore EDK2 master
X86TimerLib.c
Go to the documentation of this file.
1
11#include <Base.h>
12#include <Library/TimerLib.h>
13#include <Library/BaseLib.h>
14#include <Library/PcdLib.h>
15#include <Library/DebugLib.h>
17
24UINT32
25EFIAPI
27 VOID
28 )
29{
30 UINTN Divisor;
31
32 GetApicTimerState (&Divisor, NULL, NULL);
33 return PcdGet32 (PcdFSBClock) / (UINT32)Divisor;
34}
35
48VOID
49EFIAPI
51 IN UINT32 Delay
52 )
53{
54 INT32 Ticks;
55 UINT32 Times;
56 UINT32 InitCount;
57 UINT32 StartTick;
58
59 //
60 // In case Delay is too larger, separate it into several small delay slot.
61 // Devided Delay by half value of Init Count is to avoid Delay close to
62 // the Init Count, timeout maybe missing if the time consuming between 2
63 // GetApicTimerCurrentCount() invoking is larger than the time gap between
64 // Delay and the Init Count.
65 //
66 InitCount = GetApicTimerInitCount ();
67 ASSERT (InitCount != 0);
68 Times = Delay / (InitCount / 2);
69 Delay = Delay % (InitCount / 2);
70
71 //
72 // Get Start Tick and do delay
73 //
74 StartTick = GetApicTimerCurrentCount ();
75 do {
76 //
77 // Wait until time out by Delay value
78 //
79 do {
80 CpuPause ();
81 //
82 // Get Ticks from Start to Current.
83 //
84 Ticks = StartTick - GetApicTimerCurrentCount ();
85 //
86 // Ticks < 0 means Timer wrap-arounds happens.
87 //
88 if (Ticks < 0) {
89 Ticks += InitCount;
90 }
91 } while ((UINT32)Ticks < Delay);
92
93 //
94 // Update StartTick and Delay for next delay slot
95 //
96 StartTick -= (StartTick > Delay) ? Delay : (Delay - InitCount);
97 Delay = InitCount / 2;
98 } while (Times-- > 0);
99}
100
111UINTN
112EFIAPI
114 IN UINTN MicroSeconds
115 )
116{
118 (UINT32)DivU64x32 (
119 MultU64x64 (
121 MicroSeconds
122 ),
123 1000000u
124 )
125 );
126 return MicroSeconds;
127}
128
139UINTN
140EFIAPI
142 IN UINTN NanoSeconds
143 )
144{
146 (UINT32)DivU64x32 (
147 MultU64x64 (
149 NanoSeconds
150 ),
151 1000000000u
152 )
153 );
154 return NanoSeconds;
155}
156
168UINT64
169EFIAPI
171 VOID
172 )
173{
174 return (UINT64)GetApicTimerCurrentCount ();
175}
176
200UINT64
201EFIAPI
203 OUT UINT64 *StartValue OPTIONAL,
204 OUT UINT64 *EndValue OPTIONAL
205 )
206{
207 if (StartValue != NULL) {
208 *StartValue = (UINT64)GetApicTimerInitCount ();
209 }
210
211 if (EndValue != NULL) {
212 *EndValue = 0;
213 }
214
215 return (UINT64)InternalX86GetTimerFrequency ();
216}
217
229UINT64
230EFIAPI
232 IN UINT64 Ticks
233 )
234{
235 UINT64 Frequency;
236 UINT64 NanoSeconds;
237 UINT64 Remainder;
238 INTN Shift;
239
241
242 //
243 // Ticks
244 // Time = --------- x 1,000,000,000
245 // Frequency
246 //
247 NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);
248
249 //
250 // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.
251 // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,
252 // i.e. highest bit set in Remainder should <= 33.
253 //
254 Shift = MAX (0, HighBitSet64 (Remainder) - 33);
255 Remainder = RShiftU64 (Remainder, (UINTN)Shift);
256 Frequency = RShiftU64 (Frequency, (UINTN)Shift);
257 NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);
258
259 return NanoSeconds;
260}
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 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
#define ASSERT(Expression)
Definition: DebugLib.h:391
VOID EFIAPI GetApicTimerState(OUT UINTN *DivideValue OPTIONAL, OUT BOOLEAN *PeriodicMode OPTIONAL, OUT UINT8 *Vector OPTIONAL)
Definition: BaseXApicLib.c:774
UINT32 EFIAPI GetApicTimerInitCount(VOID)
Definition: BaseXApicLib.c:682
UINT32 EFIAPI GetApicTimerCurrentCount(VOID)
Definition: BaseXApicLib.c:696
UINT64 EFIAPI GetPerformanceCounterProperties(OUT UINT64 *StartValue OPTIONAL, OUT UINT64 *EndValue OPTIONAL)
Definition: X86TimerLib.c:307
UINT64 EFIAPI GetTimeInNanoSecond(IN UINT64 Ticks)
Definition: X86TimerLib.c:340
UINT32 EFIAPI InternalX86GetTimerFrequency(IN UINTN ApicBase)
Definition: X86TimerLib.c:89
VOID EFIAPI InternalX86Delay(IN UINTN ApicBase, IN UINT32 Delay)
Definition: X86TimerLib.c:146
UINT64 EFIAPI GetPerformanceCounter(VOID)
Definition: X86TimerLib.c:275
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
Definition: X86TimerLib.c:210
UINTN EFIAPI NanoSecondDelay(IN UINTN NanoSeconds)
Definition: X86TimerLib.c:242
#define PcdGet32(TokenName)
Definition: PcdLib.h:362