VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.c@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 6.4 KB
Line 
1/** @file
2 ACPI Timer implements one instance of Timer Library.
3
4 Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include <PiPei.h>
10#include <Library/TimerLib.h>
11#include <Library/BaseLib.h>
12#include <Library/IoLib.h>
13#include <Library/HobLib.h>
14#include <Library/DebugLib.h>
15
16#include <Guid/AcpiBoardInfoGuid.h>
17#include <IndustryStandard/Acpi.h>
18
19#define ACPI_TIMER_COUNT_SIZE BIT24
20
21UINTN mPmTimerReg = 0;
22
23/**
24 The constructor function enables ACPI IO space.
25
26 If ACPI I/O space not enabled, this function will enable it.
27 It will always return RETURN_SUCCESS.
28
29 @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
30
31**/
32RETURN_STATUS
33EFIAPI
34AcpiTimerLibConstructor (
35 VOID
36 )
37{
38 EFI_HOB_GUID_TYPE *GuidHob;
39 ACPI_BOARD_INFO *pAcpiBoardInfo;
40
41 //
42 // Find the acpi board information guid hob
43 //
44 GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
45 ASSERT (GuidHob != NULL);
46
47 pAcpiBoardInfo = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob);
48
49 mPmTimerReg = (UINTN)pAcpiBoardInfo->PmTimerRegBase;
50 ASSERT (pAcpiBoardInfo->PmTimerRegBase != 0);
51
52 return EFI_SUCCESS;
53}
54
55/**
56 Internal function to read the current tick counter of ACPI.
57
58 Internal function to read the current tick counter of ACPI.
59
60 @return The tick counter read.
61
62**/
63UINT32
64InternalAcpiGetTimerTick (
65 VOID
66 )
67{
68 if (mPmTimerReg == 0) {
69 AcpiTimerLibConstructor ();
70 }
71
72 return IoRead32 (mPmTimerReg);
73}
74
75/**
76 Stalls the CPU for at least the given number of ticks.
77
78 Stalls the CPU for at least the given number of ticks. It's invoked by
79 MicroSecondDelay() and NanoSecondDelay().
80
81 @param Delay A period of time to delay in ticks.
82
83**/
84VOID
85InternalAcpiDelay (
86 IN UINT32 Delay
87 )
88{
89 UINT32 Ticks;
90 UINT32 Times;
91
92 Times = Delay >> 22;
93 Delay &= BIT22 - 1;
94 do {
95 //
96 // The target timer count is calculated here
97 //
98 Ticks = InternalAcpiGetTimerTick () + Delay;
99 Delay = BIT22;
100 //
101 // Wait until time out
102 // Delay >= 2^23 could not be handled by this function
103 // Timer wrap-arounds are handled correctly by this function
104 //
105 while (((Ticks - InternalAcpiGetTimerTick ()) & BIT23) == 0) {
106 CpuPause ();
107 }
108 } while (Times-- > 0);
109}
110
111/**
112 Stalls the CPU for at least the given number of microseconds.
113
114 Stalls the CPU for the number of microseconds specified by MicroSeconds.
115
116 @param MicroSeconds The minimum number of microseconds to delay.
117
118 @return MicroSeconds
119
120**/
121UINTN
122EFIAPI
123MicroSecondDelay (
124 IN UINTN MicroSeconds
125 )
126{
127 InternalAcpiDelay (
128 (UINT32)DivU64x32 (
129 MultU64x32 (
130 MicroSeconds,
131 ACPI_TIMER_FREQUENCY
132 ),
133 1000000u
134 )
135 );
136 return MicroSeconds;
137}
138
139/**
140 Stalls the CPU for at least the given number of nanoseconds.
141
142 Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
143
144 @param NanoSeconds The minimum number of nanoseconds to delay.
145
146 @return NanoSeconds
147
148**/
149UINTN
150EFIAPI
151NanoSecondDelay (
152 IN UINTN NanoSeconds
153 )
154{
155 InternalAcpiDelay (
156 (UINT32)DivU64x32 (
157 MultU64x32 (
158 NanoSeconds,
159 ACPI_TIMER_FREQUENCY
160 ),
161 1000000000u
162 )
163 );
164 return NanoSeconds;
165}
166
167/**
168 Retrieves the current value of a 64-bit free running performance counter.
169
170 Retrieves the current value of a 64-bit free running performance counter. The
171 counter can either count up by 1 or count down by 1. If the physical
172 performance counter counts by a larger increment, then the counter values
173 must be translated. The properties of the counter can be retrieved from
174 GetPerformanceCounterProperties().
175
176 @return The current value of the free running performance counter.
177
178**/
179UINT64
180EFIAPI
181GetPerformanceCounter (
182 VOID
183 )
184{
185 return (UINT64)InternalAcpiGetTimerTick ();
186}
187
188/**
189 Retrieves the 64-bit frequency in Hz and the range of performance counter
190 values.
191
192 If StartValue is not NULL, then the value that the performance counter starts
193 with immediately after is it rolls over is returned in StartValue. If
194 EndValue is not NULL, then the value that the performance counter end with
195 immediately before it rolls over is returned in EndValue. The 64-bit
196 frequency of the performance counter in Hz is always returned. If StartValue
197 is less than EndValue, then the performance counter counts up. If StartValue
198 is greater than EndValue, then the performance counter counts down. For
199 example, a 64-bit free running counter that counts up would have a StartValue
200 of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
201 that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
202
203 @param StartValue The value the performance counter starts with when it
204 rolls over.
205 @param EndValue The value that the performance counter ends with before
206 it rolls over.
207
208 @return The frequency in Hz.
209
210**/
211UINT64
212EFIAPI
213GetPerformanceCounterProperties (
214 OUT UINT64 *StartValue OPTIONAL,
215 OUT UINT64 *EndValue OPTIONAL
216 )
217{
218 if (StartValue != NULL) {
219 *StartValue = 0;
220 }
221
222 if (EndValue != NULL) {
223 *EndValue = ACPI_TIMER_COUNT_SIZE - 1;
224 }
225
226 return ACPI_TIMER_FREQUENCY;
227}
228
229/**
230 Converts elapsed ticks of performance counter to time in nanoseconds.
231
232 This function converts the elapsed ticks of running performance counter to
233 time value in unit of nanoseconds.
234
235 @param Ticks The number of elapsed ticks of running performance counter.
236
237 @return The elapsed time in nanoseconds.
238
239**/
240UINT64
241EFIAPI
242GetTimeInNanoSecond (
243 IN UINT64 Ticks
244 )
245{
246 UINT64 Frequency;
247 UINT64 NanoSeconds;
248 UINT64 Remainder;
249 INTN Shift;
250
251 Frequency = GetPerformanceCounterProperties (NULL, NULL);
252
253 //
254 // Ticks
255 // Time = --------- x 1,000,000,000
256 // Frequency
257 //
258 NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);
259
260 //
261 // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.
262 // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,
263 // i.e. highest bit set in Remainder should <= 33.
264 //
265 Shift = MAX (0, HighBitSet64 (Remainder) - 33);
266 Remainder = RShiftU64 (Remainder, (UINTN)Shift);
267 Frequency = RShiftU64 (Frequency, (UINTN)Shift);
268 NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);
269
270 return NanoSeconds;
271}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette