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