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