microsoft/mu_feature_ffa

Public

mirrored fromhttps://github.com/microsoft/mu_feature_ffaAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.1.4

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

FfaFeaturePkg/Library/ArmArchTimerLibEx/ArmArchTimerLibEx.c

242lines · modecode

1/** @file
2 Generic ARM implementation of TimerLib.h
3
4 Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8**/
9
10#include <Base.h>
11#include <Library/ArmLib.h>
12#include <Library/BaseLib.h>
13#include <Library/TimerLib.h>
14#include <Library/DebugLib.h>
15#include <Library/PcdLib.h>
16#include <Library/ArmGenericTimerCounterLib.h>
17
18#define TICKS_PER_MICRO_SEC (ArmGenericTimerGetTimerFreq ()/1000000U)
19
20/**
21 A local utility function that returns the PCD value, if specified.
22 Otherwise it defaults to ArmGenericTimerGetTimerFreq.
23
24 @return The timer frequency.
25
26**/
27STATIC
28UINTN
29EFIAPI
30GetPlatformTimerFreq (
31 )
32{
33 UINTN TimerFreq;
34
35 TimerFreq = ArmGenericTimerGetTimerFreq ();
36
37 ASSERT (TimerFreq != 0);
38
39 return TimerFreq;
40}
41
42/**
43 Stalls the CPU for the number of microseconds specified by MicroSeconds.
44
45 @param MicroSeconds The minimum number of microseconds to delay.
46
47 @return The value of MicroSeconds input.
48
49**/
50UINTN
51EFIAPI
52MicroSecondDelay (
53 IN UINTN MicroSeconds
54 )
55{
56 UINT64 TimerTicks64;
57 UINT64 SystemCounterVal;
58
59 // MU_CHANGE - Start - Cannot depend on GenericTimer Calls
60 // UINT64 PreviousSystemCounterVal;
61 // UINT64 DeltaCounterVal;
62 // MU_CHANGE - End - Cannot depend on GenericTimer Calls
63
64 // Calculate counter ticks that represent requested delay:
65 // = MicroSeconds x TICKS_PER_MICRO_SEC
66 // = MicroSeconds x Frequency.10^-6
67 TimerTicks64 = DivU64x32 (
68 MultU64x64 (
69 MicroSeconds,
70 GetPlatformTimerFreq ()
71 ),
72 1000000U
73 );
74
75 // MU_CHANGE - Start - Cannot depend on GenericTimer Calls
76 // // Read System Counter value
77 // PreviousSystemCounterVal = ArmGenericTimerGetSystemCount ();
78 //
79 // // Wait until delay count expires.
80 // while (TimerTicks64 > 0) {
81 // SystemCounterVal = ArmGenericTimerGetSystemCount ();
82 // // Get how much we advanced this tick. Wrap around still has delta correct
83 // DeltaCounterVal = (SystemCounterVal - PreviousSystemCounterVal)
84 // & (MAX_UINT64 >> 8); // Account for a lesser (minimum) size
85 // // Never wrap back around below zero by choosing the min and thus stop at 0
86 // TimerTicks64 -= MIN (TimerTicks64, DeltaCounterVal);
87 // PreviousSystemCounterVal = SystemCounterVal;
88 // Wait until delay count expires.
89 SystemCounterVal = 0;
90 while (SystemCounterVal < TimerTicks64) {
91 SystemCounterVal++;
92 // MU_CHANGE - End - Cannot depend on GenericTimer Calls
93 }
94
95 return MicroSeconds;
96}
97
98/**
99 Stalls the CPU for at least the given number of nanoseconds.
100
101 Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
102
103 When the timer frequency is 1MHz, each tick corresponds to 1 microsecond.
104 Therefore, the nanosecond delay will be rounded up to the nearest 1 microsecond.
105
106 @param NanoSeconds The minimum number of nanoseconds to delay.
107
108 @return The value of NanoSeconds inputted.
109
110**/
111UINTN
112EFIAPI
113NanoSecondDelay (
114 IN UINTN NanoSeconds
115 )
116{
117 UINTN MicroSeconds;
118
119 // Round up to 1us Tick Number
120 MicroSeconds = NanoSeconds / 1000;
121 MicroSeconds += ((NanoSeconds % 1000) == 0) ? 0 : 1;
122
123 MicroSecondDelay (MicroSeconds);
124
125 return NanoSeconds;
126}
127
128/**
129 Retrieves the current value of a 64-bit free running performance counter.
130
131 The counter can either count up by 1 or count down by 1. If the physical
132 performance counter counts by a larger increment, then the counter values
133 must be translated. The properties of the counter can be retrieved from
134 GetPerformanceCounterProperties().
135
136 @return The current value of the free running performance counter.
137
138**/
139UINT64
140EFIAPI
141GetPerformanceCounter (
142 VOID
143 )
144{
145 // Just return the value of system count
146 return ArmGenericTimerGetSystemCount ();
147}
148
149/**
150 Retrieves the 64-bit frequency in Hz and the range of performance counter
151 values.
152
153 If StartValue is not NULL, then the value that the performance counter starts
154 with immediately after is it rolls over is returned in StartValue. If
155 EndValue is not NULL, then the value that the performance counter end with
156 immediately before it rolls over is returned in EndValue. The 64-bit
157 frequency of the performance counter in Hz is always returned. If StartValue
158 is less than EndValue, then the performance counter counts up. If StartValue
159 is greater than EndValue, then the performance counter counts down. For
160 example, a 64-bit free running counter that counts up would have a StartValue
161 of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
162 that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
163
164 @param StartValue The value the performance counter starts with when it
165 rolls over.
166 @param EndValue The value that the performance counter ends with before
167 it rolls over.
168
169 @return The frequency in Hz.
170
171**/
172UINT64
173EFIAPI
174GetPerformanceCounterProperties (
175 OUT UINT64 *StartValue OPTIONAL,
176 OUT UINT64 *EndValue OPTIONAL
177 )
178{
179 if (StartValue != NULL) {
180 // Timer starts at 0
181 *StartValue = (UINT64)0ULL;
182 }
183
184 if (EndValue != NULL) {
185 // Timer counts up.
186 *EndValue = 0xFFFFFFFFFFFFFFFFUL;
187 }
188
189 return (UINT64)ArmGenericTimerGetTimerFreq ();
190}
191
192/**
193 Converts elapsed ticks of performance counter to time in nanoseconds.
194
195 This function converts the elapsed ticks of running performance counter to
196 time value in unit of nanoseconds.
197
198 @param Ticks The number of elapsed ticks of running performance counter.
199
200 @return The elapsed time in nanoseconds.
201
202**/
203UINT64
204EFIAPI
205GetTimeInNanoSecond (
206 IN UINT64 Ticks
207 )
208{
209 UINT64 NanoSeconds;
210 UINT64 Remainder;
211 UINT64 TimerFreq;
212
213 TimerFreq = GetPlatformTimerFreq ();
214 //
215 // Ticks
216 // Time = --------- x 1,000,000,000
217 // Frequency
218 //
219 NanoSeconds = MultU64x64 (
220 DivU64x64Remainder (
221 Ticks,
222 TimerFreq,
223 &Remainder
224 ),
225 1000000000U
226 );
227
228 //
229 // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000)
230 // will not overflow 64-bit.
231 //
232 NanoSeconds += DivU64x64Remainder (
233 MultU64x64 (
234 Remainder,
235 1000000000U
236 ),
237 TimerFreq,
238 NULL
239 );
240
241 return NanoSeconds;
242}
243