12803d9fa4120a858a0342032f7636573540d284
[mirror_edk2.git] / MdePkg / Library / BaseTimerLibLocalApic / Ipf / IpfTimerLib.c
1 /** @file
2 Timer Library functions built upon local APIC on IA32/x64.
3
4 @bug Should use PCD to retrieve all the constants including index of
5 the IA32_APIC_BASE MSR, the offsets of InitialCount, CorrentCount
6 and DivideConfiguration.
7
8 Copyright (c) 2006, Intel Corporation<BR>
9 All rights reserved. This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17 Module Name: IpfTimerLib.c
18
19 **/
20
21 typedef struct {
22 UINT64 Status;
23 UINT64 r9;
24 UINT64 r10;
25 UINT64 r11;
26 } PAL_PROC_RETURN;
27
28 /**
29 Performs a PAL call using static calling convention.
30
31 An internal function to perform a PAL call using static calling convention.
32
33 @param PalEntryPoint The entry point address of PAL. The address in ar.kr5
34 would be used if this parameter were NULL on input.
35 @param Arg1 The first argument of a PAL call.
36 @param Arg1 The second argument of a PAL call.
37 @param Arg1 The third argument of a PAL call.
38 @param Arg1 The fourth argument of a PAL call.
39
40 @return The values returned in r8, r9, r10 and r11.
41
42 **/
43 PAL_PROC_RETURN
44 PalCallStatic (
45 IN CONST VOID *PalEntryPoint,
46 IN UINT64 Arg1,
47 IN UINT64 Arg2,
48 IN UINT64 Arg3,
49 IN UINT64 Arg4
50 );
51
52 /**
53 Returns the current value of ar.itc.
54
55 An internal function to return the current value of ar.itc, which is the
56 timer tick on IPF.
57
58 @return The currect value of ar.itc
59
60 **/
61 INT64
62 InternalIpfReadItc (
63 VOID
64 );
65
66 /**
67 Performs a delay measured as number of ticks.
68
69 An internal function to perform a delay measured as number of ticks. It's
70 invoked by MicroSecondDelay() and NanoSecondDelay().
71
72 @param Delay Number of ticks to delay.
73
74 **/
75 STATIC
76 VOID
77 InternalIpfDelay (
78 IN INT64 Delay
79 )
80 {
81 INT64 Ticks;
82
83 //
84 // The target timer count is calculated here
85 //
86 Ticks = InternalIpfReadItc () + Delay;
87
88 //
89 // Wait until time out
90 // Delay > 2^63 could not be handled by this function
91 // Timer wrap-arounds are handled correctly by this function
92 //
93 while (Ticks - InternalIpfReadItc () >= 0);
94 }
95
96 /**
97 Stalls the CPU for at least the given number of microseconds.
98
99 Stalls the CPU for the number of microseconds specified by MicroSeconds.
100
101 @param MicroSeconds The minimum number of microseconds to delay.
102
103 @return MicroSeconds
104
105 **/
106 UINTN
107 EFIAPI
108 MicroSecondDelay (
109 IN UINTN MicroSeconds
110 )
111 {
112 InternalIpfDelay (
113 GetPerformanceCounterProperties (NULL, NULL) *
114 MicroSeconds /
115 1000000
116 );
117 return MicroSeconds;
118 }
119
120 /**
121 Stalls the CPU for at least the given number of nanoseconds.
122
123 Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
124
125 @param NanoSeconds The minimum number of nanoseconds to delay.
126
127 @return NanoSeconds
128
129 **/
130 UINTN
131 EFIAPI
132 NanoSecondDelay (
133 IN UINTN NanoSeconds
134 )
135 {
136 InternalIpfDelay (
137 GetPerformanceCounterProperties (NULL, NULL) *
138 NanoSeconds /
139 1000000000
140 );
141 return NanoSeconds;
142 }
143
144 /**
145 Retrieves the current value of a 64-bit free running performance counter.
146
147 Retrieves the current value of a 64-bit free running performance counter. The
148 counter can either count up by 1 or count down by 1. If the physical
149 performance counter counts by a larger increment, then the counter values
150 must be translated. The properties of the counter can be retrieved from
151 GetPerformanceCounterProperties().
152
153 @return The current value of the free running performance counter.
154
155 **/
156 UINT64
157 EFIAPI
158 GetPerformanceCounter (
159 VOID
160 )
161 {
162 return InternalIpfReadItc ();
163 }
164
165 /**
166 Retrieves the 64-bit frequency in Hz and the range of performance counter
167 values.
168
169 If StartValue is not NULL, then the value that the performance counter starts
170 with immediately after is it rolls over is returned in StartValue. If
171 EndValue is not NULL, then the value that the performance counter end with
172 immediately before it rolls over is returned in EndValue. The 64-bit
173 frequency of the performance counter in Hz is always returned. If StartValue
174 is less than EndValue, then the performance counter counts up. If StartValue
175 is greater than EndValue, then the performance counter counts down. For
176 example, a 64-bit free running counter that counts up would have a StartValue
177 of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
178 that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
179
180 @param StartValue The value the performance counter starts with when it
181 rolls over.
182 @param EndValue The value that the performance counter ends with before
183 it rolls over.
184
185 @return The frequency in Hz.
186
187 **/
188 UINT64
189 EFIAPI
190 GetPerformanceCounterProperties (
191 OUT UINT64 *StartValue, OPTIONAL
192 OUT UINT64 *EndValue OPTIONAL
193 )
194 {
195 PAL_PROC_RETURN PalRet;
196 UINT64 BaseFrequence;
197
198 PalRet = PalCallStatic (NULL, 13, 0, 0, 0);
199 ASSERT (PalRet.Status == 0);
200 BaseFrequence = PalRet.r9;
201
202 PalRet = PalCallStatic (NULL, 14, 0, 0, 0);
203 ASSERT (PalRet.Status == 0);
204
205 if (StartValue != NULL) {
206 *StartValue = 0;
207 }
208
209 if (EndValue != NULL) {
210 *EndValue = (UINT64)(-1);
211 }
212
213 return BaseFrequence * (PalRet.r11 >> 32) / (UINT32)PalRet.r11;
214 }