]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/SecPeiDxeTimerLibCpu/X86TimerLib.c
Function headers in .h and .c files synchronized with spec
[mirror_edk2.git] / MdePkg / Library / SecPeiDxeTimerLibCpu / X86TimerLib.c
CommitLineData
e386b444 1/** @file\r
2 Timer Library functions built upon local APIC on IA32/x64.\r
3\r
7687d3a8 4 Copyright (c) 2006 - 2008, Intel Corporation<BR>\r
e386b444 5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
e386b444 13**/\r
14\r
f734a10a
A
15#include <Base.h>\r
16#include <Library/TimerLib.h>\r
17#include <Library/BaseLib.h>\r
18#include <Library/IoLib.h>\r
f734a10a
A
19#include <Library/PcdLib.h>\r
20\r
9cd1d1c1 21#define APIC_LVTERR 0x370\r
22#define APIC_TMICT 0x380 \r
23#define APIC_TMCCT 0x390\r
24#define APIC_TDCR 0x3e0\r
e386b444 25\r
26//\r
27// The following array is used in calculating the frequency of local APIC\r
28// timer. Refer to IA-32 developers' manual for more details.\r
29//\r
30GLOBAL_REMOVE_IF_UNREFERENCED\r
31CONST UINT8 mTimerLibLocalApicDivisor[] = {\r
32 0x02, 0x04, 0x08, 0x10,\r
33 0x02, 0x04, 0x08, 0x10,\r
34 0x20, 0x40, 0x80, 0x01,\r
35 0x20, 0x40, 0x80, 0x01\r
36};\r
37\r
38/**\r
39 Internal function to retrieve the base address of local APIC.\r
40\r
e386b444 41 @return The base address of local APIC\r
42\r
43**/\r
e386b444 44UINTN\r
42eedea9 45EFIAPI\r
e386b444 46InternalX86GetApicBase (\r
47 VOID\r
48 )\r
49{\r
50 return (UINTN)AsmMsrBitFieldRead64 (27, 12, 35) << 12;\r
51}\r
52\r
53/**\r
54 Internal function to return the frequency of the local APIC timer.\r
55\r
e386b444 56 @param ApicBase The base address of memory mapped registers of local APIC.\r
57\r
58 @return The frequency of the timer in Hz.\r
59\r
60**/\r
e386b444 61UINT32\r
42eedea9 62EFIAPI\r
e386b444 63InternalX86GetTimerFrequency (\r
64 IN UINTN ApicBase\r
65 )\r
66{\r
67 return\r
68 PcdGet32(PcdFSBClock) /\r
9cd1d1c1 69 mTimerLibLocalApicDivisor[MmioBitFieldRead32 (ApicBase + APIC_TDCR, 0, 3)];\r
e386b444 70}\r
71\r
72/**\r
73 Internal function to read the current tick counter of local APIC.\r
74\r
e386b444 75 @param ApicBase The base address of memory mapped registers of local APIC.\r
76\r
77 @return The tick counter read.\r
78\r
79**/\r
e386b444 80INT32\r
42eedea9 81EFIAPI\r
e386b444 82InternalX86GetTimerTick (\r
83 IN UINTN ApicBase\r
84 )\r
85{\r
9cd1d1c1 86 return MmioRead32 (ApicBase + APIC_TMCCT);\r
e386b444 87}\r
88\r
89/**\r
90 Stalls the CPU for at least the given number of ticks.\r
91\r
92 Stalls the CPU for at least the given number of ticks. It's invoked by\r
93 MicroSecondDelay() and NanoSecondDelay().\r
94\r
95 @param ApicBase The base address of memory mapped registers of local APIC.\r
96 @param Delay A period of time to delay in ticks.\r
97\r
98**/\r
e386b444 99VOID\r
42eedea9 100EFIAPI\r
e386b444 101InternalX86Delay (\r
102 IN UINTN ApicBase,\r
103 IN UINT32 Delay\r
104 )\r
105{\r
106 INT32 Ticks;\r
107\r
108 //\r
109 // The target timer count is calculated here\r
110 //\r
111 Ticks = InternalX86GetTimerTick (ApicBase) - Delay;\r
112\r
113 //\r
114 // Wait until time out\r
115 // Delay > 2^31 could not be handled by this function\r
116 // Timer wrap-arounds are handled correctly by this function\r
117 //\r
118 while (InternalX86GetTimerTick (ApicBase) - Ticks >= 0);\r
119}\r
120\r
121/**\r
122 Stalls the CPU for at least the given number of microseconds.\r
123\r
124 Stalls the CPU for the number of microseconds specified by MicroSeconds.\r
125\r
126 @param MicroSeconds The minimum number of microseconds to delay.\r
127\r
8cefc2ee 128 @return The value of MicroSeconds inputted.\r
e386b444 129\r
130**/\r
131UINTN\r
132EFIAPI\r
133MicroSecondDelay (\r
134 IN UINTN MicroSeconds\r
135 )\r
136{\r
137 UINTN ApicBase;\r
138\r
139 ApicBase = InternalX86GetApicBase ();\r
140 InternalX86Delay (\r
141 ApicBase,\r
142 (UINT32)DivU64x32 (\r
143 MultU64x64 (\r
144 InternalX86GetTimerFrequency (ApicBase),\r
145 MicroSeconds\r
146 ),\r
147 1000000u\r
148 )\r
149 );\r
150 return MicroSeconds;\r
151}\r
152\r
153/**\r
154 Stalls the CPU for at least the given number of nanoseconds.\r
155\r
156 Stalls the CPU for the number of nanoseconds specified by NanoSeconds.\r
157\r
158 @param NanoSeconds The minimum number of nanoseconds to delay.\r
159\r
8cefc2ee 160 @return The value of NanoSeconds inputted.\r
e386b444 161\r
162**/\r
163UINTN\r
164EFIAPI\r
165NanoSecondDelay (\r
166 IN UINTN NanoSeconds\r
167 )\r
168{\r
169 UINTN ApicBase;\r
170\r
171 ApicBase = InternalX86GetApicBase ();\r
172 InternalX86Delay (\r
173 ApicBase,\r
174 (UINT32)DivU64x32 (\r
175 MultU64x64 (\r
176 InternalX86GetTimerFrequency (ApicBase),\r
177 NanoSeconds\r
178 ),\r
179 1000000000u\r
180 )\r
181 );\r
182 return NanoSeconds;\r
183}\r
184\r
185/**\r
71871514 186 Retrieves the current value of a 64-bit free running performance counter.\r
187\r
188 The counter can either count up by 1 or count down by 1. If the physical\r
e386b444 189 performance counter counts by a larger increment, then the counter values\r
190 must be translated. The properties of the counter can be retrieved from\r
191 GetPerformanceCounterProperties().\r
192\r
193 @return The current value of the free running performance counter.\r
194\r
195**/\r
196UINT64\r
197EFIAPI\r
198GetPerformanceCounter (\r
199 VOID\r
200 )\r
201{\r
202 return (UINT64)(UINT32)InternalX86GetTimerTick (InternalX86GetApicBase ());\r
203}\r
204\r
205/**\r
206 Retrieves the 64-bit frequency in Hz and the range of performance counter\r
207 values.\r
208\r
209 If StartValue is not NULL, then the value that the performance counter starts\r
210 with immediately after is it rolls over is returned in StartValue. If\r
211 EndValue is not NULL, then the value that the performance counter end with\r
212 immediately before it rolls over is returned in EndValue. The 64-bit\r
213 frequency of the performance counter in Hz is always returned. If StartValue\r
214 is less than EndValue, then the performance counter counts up. If StartValue\r
215 is greater than EndValue, then the performance counter counts down. For\r
216 example, a 64-bit free running counter that counts up would have a StartValue\r
217 of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter\r
218 that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.\r
219\r
220 @param StartValue The value the performance counter starts with when it\r
221 rolls over.\r
222 @param EndValue The value that the performance counter ends with before\r
223 it rolls over.\r
224\r
225 @return The frequency in Hz.\r
226\r
227**/\r
228UINT64\r
229EFIAPI\r
230GetPerformanceCounterProperties (\r
231 OUT UINT64 *StartValue, OPTIONAL\r
232 OUT UINT64 *EndValue OPTIONAL\r
233 )\r
234{\r
235 UINTN ApicBase;\r
236\r
237 ApicBase = InternalX86GetApicBase ();\r
238\r
239 if (StartValue != NULL) {\r
9cd1d1c1 240 *StartValue = MmioRead32 (ApicBase + APIC_TMICT);\r
e386b444 241 }\r
242\r
243 if (EndValue != NULL) {\r
244 *EndValue = 0;\r
245 }\r
246\r
9cd1d1c1 247 return (UINT64) InternalX86GetTimerFrequency (ApicBase);\r
e386b444 248}\r