]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.c
Add new extension PerformanceLib APIs to store ID info.
[mirror_edk2.git] / MdeModulePkg / Library / PeiPerformanceLib / PeiPerformanceLib.c
1 /** @file
2 Performance library instance used in PEI phase.
3
4 This file implements all APIs in Performance Library class in MdePkg. It creates
5 performance logging GUIDed HOB on the first performance logging and then logs the
6 performance data to the GUIDed HOB. Due to the limitation of temporary RAM, the maximum
7 number of performance logging entry is specified by PcdMaxPeiPerformanceLogEntries.
8
9 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
10 This program and the accompanying materials
11 are licensed and made available under the terms and conditions of the BSD License
12 which accompanies this distribution. The full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
14
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17
18 **/
19
20
21 #include <PiPei.h>
22
23 #include <Guid/Performance.h>
24
25 #include <Library/PerformanceLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/HobLib.h>
28 #include <Library/BaseLib.h>
29 #include <Library/TimerLib.h>
30 #include <Library/PcdLib.h>
31 #include <Library/BaseMemoryLib.h>
32
33
34 /**
35 Gets the GUID HOB for PEI performance.
36
37 This internal function searches for the GUID HOB for PEI performance.
38 If that GUID HOB is not found, it will build a new one.
39 It outputs the data area of that GUID HOB to record performance log.
40
41 @param PeiPerformanceLog Pointer to Pointer to PEI performance log header.
42 @param PeiPerformanceIdArray Pointer to Pointer to PEI performance identifier array.
43
44 **/
45 VOID
46 InternalGetPerformanceHobLog (
47 OUT PEI_PERFORMANCE_LOG_HEADER **PeiPerformanceLog,
48 OUT UINT32 **PeiPerformanceIdArray
49 )
50 {
51 EFI_HOB_GUID_TYPE *GuidHob;
52 UINTN PeiPerformanceSize;
53
54 ASSERT (PeiPerformanceLog != NULL);
55 ASSERT (PeiPerformanceIdArray != NULL);
56
57 GuidHob = GetFirstGuidHob (&gPerformanceProtocolGuid);
58
59 if (GuidHob != NULL) {
60 //
61 // PEI Performance HOB was found, then return the existing one.
62 //
63 *PeiPerformanceLog = GET_GUID_HOB_DATA (GuidHob);
64
65 GuidHob = GetFirstGuidHob (&gPerformanceExProtocolGuid);
66 ASSERT (GuidHob != NULL);
67 *PeiPerformanceIdArray = GET_GUID_HOB_DATA (GuidHob);
68 } else {
69 //
70 // PEI Performance HOB was not found, then build one.
71 //
72 PeiPerformanceSize = sizeof (PEI_PERFORMANCE_LOG_HEADER) +
73 sizeof (PEI_PERFORMANCE_LOG_ENTRY) * PcdGet8 (PcdMaxPeiPerformanceLogEntries);
74 *PeiPerformanceLog = BuildGuidHob (&gPerformanceProtocolGuid, PeiPerformanceSize);
75 *PeiPerformanceLog = ZeroMem (*PeiPerformanceLog, PeiPerformanceSize);
76
77 PeiPerformanceSize = sizeof (UINT32) * PcdGet8 (PcdMaxPeiPerformanceLogEntries);
78 *PeiPerformanceIdArray = BuildGuidHob (&gPerformanceExProtocolGuid, PeiPerformanceSize);
79 *PeiPerformanceIdArray = ZeroMem (*PeiPerformanceIdArray, PeiPerformanceSize);
80 }
81 }
82
83 /**
84 Searches in the log array with keyword Handle, Token, Module and Identifier.
85
86 This internal function searches for the log entry in the log array.
87 If there is an entry that exactly matches the given keywords
88 and its end time stamp is zero, then the index of that log entry is returned;
89 otherwise, the the number of log entries in the array is returned.
90
91 @param PeiPerformanceLog Pointer to the data structure containing PEI
92 performance data.
93 @param Handle Pointer to environment specific context used
94 to identify the component being measured.
95 @param Token Pointer to a Null-terminated ASCII string
96 that identifies the component being measured.
97 @param Module Pointer to a Null-terminated ASCII string
98 that identifies the module being measured.
99 @param Identifier 32-bit identifier.
100
101 @retval The index of log entry in the array.
102
103 **/
104 UINT32
105 InternalSearchForLogEntry (
106 IN PEI_PERFORMANCE_LOG_HEADER *PeiPerformanceLog,
107 IN UINT32 *PeiPerformanceIdArray,
108 IN CONST VOID *Handle, OPTIONAL
109 IN CONST CHAR8 *Token, OPTIONAL
110 IN CONST CHAR8 *Module, OPTIONAL
111 IN UINT32 Identifier
112 )
113 {
114 UINT32 Index;
115 UINT32 NumberOfEntries;
116 PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray;
117
118
119 if (Token == NULL) {
120 Token = "";
121 }
122 if (Module == NULL) {
123 Module = "";
124 }
125 NumberOfEntries = PeiPerformanceLog->NumberOfEntries;
126 LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1);
127
128 for (Index = 0; Index < NumberOfEntries; Index++) {
129 if ((LogEntryArray[Index].Handle == (EFI_PHYSICAL_ADDRESS) (UINTN) Handle) &&
130 AsciiStrnCmp (LogEntryArray[Index].Token, Token, PEI_PERFORMANCE_STRING_LENGTH) == 0 &&
131 AsciiStrnCmp (LogEntryArray[Index].Module, Module, PEI_PERFORMANCE_STRING_LENGTH) == 0 &&
132 (PeiPerformanceIdArray[Index] == Identifier) &&
133 LogEntryArray[Index].EndTimeStamp == 0
134 ) {
135 break;
136 }
137 }
138 return Index;
139 }
140
141 /**
142 Creates a record for the beginning of a performance measurement.
143
144 Creates a record that contains the Handle, Token, Module and Identifier.
145 If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
146 If TimeStamp is zero, then this function reads the current time stamp
147 and adds that time stamp value to the record as the start time.
148
149 @param Handle Pointer to environment specific context used
150 to identify the component being measured.
151 @param Token Pointer to a Null-terminated ASCII string
152 that identifies the component being measured.
153 @param Module Pointer to a Null-terminated ASCII string
154 that identifies the module being measured.
155 @param TimeStamp 64-bit time stamp.
156 @param Identifier 32-bit identifier. If the value is 0, the created record
157 is same as the one created by StartPerformanceMeasurement.
158
159 @retval RETURN_SUCCESS The start of the measurement was recorded.
160 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
161
162 **/
163 RETURN_STATUS
164 EFIAPI
165 StartPerformanceMeasurementEx (
166 IN CONST VOID *Handle, OPTIONAL
167 IN CONST CHAR8 *Token, OPTIONAL
168 IN CONST CHAR8 *Module, OPTIONAL
169 IN UINT64 TimeStamp,
170 IN UINT32 Identifier
171 )
172 {
173 PEI_PERFORMANCE_LOG_HEADER *PeiPerformanceLog;
174 UINT32 *PeiPerformanceIdArray;
175 PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray;
176 UINT32 Index;
177
178 InternalGetPerformanceHobLog (&PeiPerformanceLog, &PeiPerformanceIdArray);
179
180 if (PeiPerformanceLog->NumberOfEntries >= PcdGet8 (PcdMaxPeiPerformanceLogEntries)) {
181 return RETURN_OUT_OF_RESOURCES;
182 }
183 Index = PeiPerformanceLog->NumberOfEntries++;
184 LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1);
185 LogEntryArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;
186
187 if (Token != NULL) {
188 AsciiStrnCpy (LogEntryArray[Index].Token, Token, PEI_PERFORMANCE_STRING_LENGTH);
189 }
190 if (Module != NULL) {
191 AsciiStrnCpy (LogEntryArray[Index].Module, Module, PEI_PERFORMANCE_STRING_LENGTH);
192 }
193
194 LogEntryArray[Index].EndTimeStamp = 0;
195 PeiPerformanceIdArray[Index] = Identifier;
196
197 if (TimeStamp == 0) {
198 TimeStamp = GetPerformanceCounter ();
199 }
200 LogEntryArray[Index].StartTimeStamp = TimeStamp;
201
202 return RETURN_SUCCESS;
203 }
204
205 /**
206 Fills in the end time of a performance measurement.
207
208 Looks up the record that matches Handle, Token, Module and Identifier.
209 If the record can not be found then return RETURN_NOT_FOUND.
210 If the record is found and TimeStamp is not zero,
211 then TimeStamp is added to the record as the end time.
212 If the record is found and TimeStamp is zero, then this function reads
213 the current time stamp and adds that time stamp value to the record as the end time.
214
215 @param Handle Pointer to environment specific context used
216 to identify the component being measured.
217 @param Token Pointer to a Null-terminated ASCII string
218 that identifies the component being measured.
219 @param Module Pointer to a Null-terminated ASCII string
220 that identifies the module being measured.
221 @param TimeStamp 64-bit time stamp.
222 @param Identifier 32-bit identifier. If the value is 0, the found record
223 is same as the one found by EndPerformanceMeasurement.
224
225 @retval RETURN_SUCCESS The end of the measurement was recorded.
226 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
227
228 **/
229 RETURN_STATUS
230 EFIAPI
231 EndPerformanceMeasurementEx (
232 IN CONST VOID *Handle, OPTIONAL
233 IN CONST CHAR8 *Token, OPTIONAL
234 IN CONST CHAR8 *Module, OPTIONAL
235 IN UINT64 TimeStamp,
236 IN UINT32 Identifier
237 )
238 {
239 PEI_PERFORMANCE_LOG_HEADER *PeiPerformanceLog;
240 UINT32 *PeiPerformanceIdArray;
241 PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray;
242 UINT32 Index;
243
244 if (TimeStamp == 0) {
245 TimeStamp = GetPerformanceCounter ();
246 }
247
248 InternalGetPerformanceHobLog (&PeiPerformanceLog, &PeiPerformanceIdArray);
249 Index = InternalSearchForLogEntry (PeiPerformanceLog, PeiPerformanceIdArray, Handle, Token, Module, Identifier);
250 if (Index >= PeiPerformanceLog->NumberOfEntries) {
251 return RETURN_NOT_FOUND;
252 }
253 LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1);
254 LogEntryArray[Index].EndTimeStamp = TimeStamp;
255
256 return RETURN_SUCCESS;
257 }
258
259 /**
260 Attempts to retrieve a performance measurement log entry from the performance measurement log.
261 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
262 and then assign the Identifier with 0.
263
264 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
265 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
266 and the key for the second entry in the log is returned. If the performance log is empty,
267 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
268 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
269 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
270 retrieved and an implementation specific non-zero key value that specifies the end of the performance
271 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
272 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
273 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
274 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
275 If Handle is NULL, then ASSERT().
276 If Token is NULL, then ASSERT().
277 If Module is NULL, then ASSERT().
278 If StartTimeStamp is NULL, then ASSERT().
279 If EndTimeStamp is NULL, then ASSERT().
280 If Identifier is NULL, then ASSERT().
281
282 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
283 0, then the first performance measurement log entry is retrieved.
284 On exit, the key of the next performance of entry entry.
285 @param Handle Pointer to environment specific context used to identify the component
286 being measured.
287 @param Token Pointer to a Null-terminated ASCII string that identifies the component
288 being measured.
289 @param Module Pointer to a Null-terminated ASCII string that identifies the module
290 being measured.
291 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
292 was started.
293 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
294 was ended.
295 @param Identifier Pointer to the 32-bit identifier that was recorded.
296
297 @return The key for the next performance log entry (in general case).
298
299 **/
300 UINTN
301 EFIAPI
302 GetPerformanceMeasurementEx (
303 IN UINTN LogEntryKey,
304 OUT CONST VOID **Handle,
305 OUT CONST CHAR8 **Token,
306 OUT CONST CHAR8 **Module,
307 OUT UINT64 *StartTimeStamp,
308 OUT UINT64 *EndTimeStamp,
309 OUT UINT32 *Identifier
310 )
311 {
312 PEI_PERFORMANCE_LOG_HEADER *PeiPerformanceLog;
313 UINT32 *PeiPerformanceIdArray;
314 PEI_PERFORMANCE_LOG_ENTRY *CurrentLogEntry;
315 PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray;
316 UINTN NumberOfEntries;
317
318 ASSERT (Handle != NULL);
319 ASSERT (Token != NULL);
320 ASSERT (Module != NULL);
321 ASSERT (StartTimeStamp != NULL);
322 ASSERT (EndTimeStamp != NULL);
323 ASSERT (Identifier != NULL);
324
325 InternalGetPerformanceHobLog (&PeiPerformanceLog, &PeiPerformanceIdArray);
326
327 NumberOfEntries = (UINTN) (PeiPerformanceLog->NumberOfEntries);
328 LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1);
329 //
330 // Make sure that LogEntryKey is a valid log entry key.
331 //
332 ASSERT (LogEntryKey <= NumberOfEntries);
333
334 if (LogEntryKey == NumberOfEntries) {
335 return 0;
336 }
337
338 CurrentLogEntry = &(LogEntryArray[LogEntryKey]);
339
340 *Handle = (VOID *) (UINTN) (CurrentLogEntry->Handle);
341 *Token = CurrentLogEntry->Token;
342 *Module = CurrentLogEntry->Module;
343 *StartTimeStamp = CurrentLogEntry->StartTimeStamp;
344 *EndTimeStamp = CurrentLogEntry->EndTimeStamp;
345 *Identifier = PeiPerformanceIdArray[LogEntryKey++];
346
347 return LogEntryKey;
348 }
349
350 /**
351 Creates a record for the beginning of a performance measurement.
352
353 Creates a record that contains the Handle, Token, and Module.
354 If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
355 If TimeStamp is zero, then this function reads the current time stamp
356 and adds that time stamp value to the record as the start time.
357
358 @param Handle Pointer to environment specific context used
359 to identify the component being measured.
360 @param Token Pointer to a Null-terminated ASCII string
361 that identifies the component being measured.
362 @param Module Pointer to a Null-terminated ASCII string
363 that identifies the module being measured.
364 @param TimeStamp 64-bit time stamp.
365
366 @retval RETURN_SUCCESS The start of the measurement was recorded.
367 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
368
369 **/
370 RETURN_STATUS
371 EFIAPI
372 StartPerformanceMeasurement (
373 IN CONST VOID *Handle, OPTIONAL
374 IN CONST CHAR8 *Token, OPTIONAL
375 IN CONST CHAR8 *Module, OPTIONAL
376 IN UINT64 TimeStamp
377 )
378 {
379 return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
380 }
381
382 /**
383 Fills in the end time of a performance measurement.
384
385 Looks up the record that matches Handle, Token, and Module.
386 If the record can not be found then return RETURN_NOT_FOUND.
387 If the record is found and TimeStamp is not zero,
388 then TimeStamp is added to the record as the end time.
389 If the record is found and TimeStamp is zero, then this function reads
390 the current time stamp and adds that time stamp value to the record as the end time.
391
392 @param Handle Pointer to environment specific context used
393 to identify the component being measured.
394 @param Token Pointer to a Null-terminated ASCII string
395 that identifies the component being measured.
396 @param Module Pointer to a Null-terminated ASCII string
397 that identifies the module being measured.
398 @param TimeStamp 64-bit time stamp.
399
400 @retval RETURN_SUCCESS The end of the measurement was recorded.
401 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
402
403 **/
404 RETURN_STATUS
405 EFIAPI
406 EndPerformanceMeasurement (
407 IN CONST VOID *Handle, OPTIONAL
408 IN CONST CHAR8 *Token, OPTIONAL
409 IN CONST CHAR8 *Module, OPTIONAL
410 IN UINT64 TimeStamp
411 )
412 {
413 return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
414 }
415
416 /**
417 Attempts to retrieve a performance measurement log entry from the performance measurement log.
418 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
419 and then eliminate the Identifier.
420
421 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
422 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
423 and the key for the second entry in the log is returned. If the performance log is empty,
424 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
425 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
426 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
427 retrieved and an implementation specific non-zero key value that specifies the end of the performance
428 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
429 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
430 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
431 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
432 If Handle is NULL, then ASSERT().
433 If Token is NULL, then ASSERT().
434 If Module is NULL, then ASSERT().
435 If StartTimeStamp is NULL, then ASSERT().
436 If EndTimeStamp is NULL, then ASSERT().
437
438 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
439 0, then the first performance measurement log entry is retrieved.
440 On exit, the key of the next performance of entry entry.
441 @param Handle Pointer to environment specific context used to identify the component
442 being measured.
443 @param Token Pointer to a Null-terminated ASCII string that identifies the component
444 being measured.
445 @param Module Pointer to a Null-terminated ASCII string that identifies the module
446 being measured.
447 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
448 was started.
449 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
450 was ended.
451
452 @return The key for the next performance log entry (in general case).
453
454 **/
455 UINTN
456 EFIAPI
457 GetPerformanceMeasurement (
458 IN UINTN LogEntryKey,
459 OUT CONST VOID **Handle,
460 OUT CONST CHAR8 **Token,
461 OUT CONST CHAR8 **Module,
462 OUT UINT64 *StartTimeStamp,
463 OUT UINT64 *EndTimeStamp
464 )
465 {
466 UINT32 Identifier;
467 return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);
468 }
469
470 /**
471 Returns TRUE if the performance measurement macros are enabled.
472
473 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
474 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
475
476 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
477 PcdPerformanceLibraryPropertyMask is set.
478 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
479 PcdPerformanceLibraryPropertyMask is clear.
480
481 **/
482 BOOLEAN
483 EFIAPI
484 PerformanceMeasurementEnabled (
485 VOID
486 )
487 {
488 return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
489 }