]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
MdeModulePkg/DxeCorePerformanceLib: add lock protection
[mirror_edk2.git] / MdeModulePkg / Library / DxeCorePerformanceLib / DxeCorePerformanceLib.c
CommitLineData
8dbae30d 1/** @file\r
857dfc45 2 Performance library instance mainly used by DxeCore.\r
3\r
4 This library provides the performance measurement interfaces and initializes performance\r
5 logging for DXE phase. It first initializes its private global data structure for\r
6 performance logging and saves the performance GUIDed HOB passed from PEI phase. \r
f0da4d7d
SZ
7 It initializes DXE phase performance logging by publishing the Performance and PerformanceEx Protocol,\r
8 which are consumed by DxePerformanceLib to logging performance data in DXE phase.\r
857dfc45 9\r
10 This library is mainly used by DxeCore to start performance logging to ensure that\r
11 Performance Protocol is installed at the very beginning of DXE phase.\r
a0afd019 12\r
cfb0aba7 13Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
7c50b343 14(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
cd5ebaa0 15This program and the accompanying materials\r
a0afd019 16are licensed and made available under the terms and conditions of the BSD License\r
17which accompanies this distribution. The full text of the license may be found at\r
18http://opensource.org/licenses/bsd-license.php\r
19\r
20THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
21WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
22\r
8dbae30d 23**/\r
a0afd019 24\r
ed7748fe 25\r
aa79b0b3 26#include "DxeCorePerformanceLibInternal.h"\r
ed7748fe 27\r
a0afd019 28\r
29//\r
857dfc45 30// The data structure to hold global performance data.\r
a0afd019 31//\r
fe1e36e5 32GAUGE_DATA_HEADER *mGaugeData;\r
857dfc45 33\r
34//\r
35// The current maximum number of logging entries. If current number of \r
36// entries exceeds this value, it will re-allocate a larger array and\r
37// migration the old data to the larger array.\r
38//\r
fe1e36e5 39UINT32 mMaxGaugeRecords;\r
a0afd019 40\r
857dfc45 41//\r
42// The handle to install Performance Protocol instance.\r
43//\r
a0afd019 44EFI_HANDLE mHandle = NULL;\r
857dfc45 45\r
46//\r
f0da4d7d 47// Interfaces for Performance Protocol.\r
857dfc45 48//\r
a0afd019 49PERFORMANCE_PROTOCOL mPerformanceInterface = {\r
50 StartGauge,\r
51 EndGauge,\r
52 GetGauge\r
53 };\r
54\r
f0da4d7d
SZ
55//\r
56// Interfaces for PerformanceEx Protocol.\r
57//\r
58PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {\r
59 StartGaugeEx,\r
60 EndGaugeEx,\r
61 GetGaugeEx\r
62 };\r
63\r
cfb0aba7
SZ
64PERFORMANCE_PROPERTY mPerformanceProperty;\r
65\r
f1f7190b
HG
66//\r
67// Gauge record lock to avoid data corruption or even memory overflow\r
68//\r
69STATIC EFI_LOCK mPerfRecordLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
70\r
a0afd019 71/**\r
f0da4d7d 72 Searches in the gauge array with keyword Handle, Token, Module and Identifier.\r
a0afd019 73\r
74 This internal function searches for the gauge entry in the gauge array.\r
f0da4d7d 75 If there is an entry that exactly matches the given keywords\r
a0afd019 76 and its end time stamp is zero, then the index of that gauge entry is returned;\r
77 otherwise, the the number of gauge entries in the array is returned.\r
78\r
79 @param Handle Pointer to environment specific context used\r
80 to identify the component being measured.\r
81 @param Token Pointer to a Null-terminated ASCII string\r
82 that identifies the component being measured.\r
83 @param Module Pointer to a Null-terminated ASCII string\r
84 that identifies the module being measured.\r
f0da4d7d 85 @param Identifier 32-bit identifier.\r
a0afd019 86\r
87 @retval The index of gauge entry in the array.\r
88\r
89**/\r
a0afd019 90UINT32\r
91InternalSearchForGaugeEntry (\r
92 IN CONST VOID *Handle, OPTIONAL\r
93 IN CONST CHAR8 *Token, OPTIONAL\r
f0da4d7d
SZ
94 IN CONST CHAR8 *Module, OPTIONAL\r
95 IN UINT32 Identifier\r
a0afd019 96 )\r
97{\r
98 UINT32 Index;\r
b504f519 99 UINT32 Index2;\r
a0afd019 100 UINT32 NumberOfEntries;\r
f0da4d7d 101 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
a0afd019 102\r
103 if (Token == NULL) {\r
104 Token = "";\r
105 }\r
106 if (Module == NULL) {\r
107 Module = "";\r
108 }\r
109\r
110 NumberOfEntries = mGaugeData->NumberOfEntries;\r
f0da4d7d 111 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
a0afd019 112\r
b504f519
SZ
113 Index2 = 0;\r
114\r
a0afd019 115 for (Index = 0; Index < NumberOfEntries; Index++) {\r
b504f519
SZ
116 Index2 = NumberOfEntries - 1 - Index;\r
117 if (GaugeEntryExArray[Index2].EndTimeStamp == 0 &&\r
118 (GaugeEntryExArray[Index2].Handle == (EFI_PHYSICAL_ADDRESS) (UINTN) Handle) &&\r
119 AsciiStrnCmp (GaugeEntryExArray[Index2].Token, Token, DXE_PERFORMANCE_STRING_LENGTH) == 0 &&\r
7a9395cd 120 AsciiStrnCmp (GaugeEntryExArray[Index2].Module, Module, DXE_PERFORMANCE_STRING_LENGTH) == 0) {\r
b504f519 121 Index = Index2;\r
a0afd019 122 break;\r
123 }\r
124 }\r
125\r
126 return Index;\r
127}\r
128\r
129/**\r
130 Adds a record at the end of the performance measurement log\r
131 that records the start time of a performance measurement.\r
132\r
133 Adds a record to the end of the performance measurement log\r
f0da4d7d 134 that contains the Handle, Token, Module and Identifier.\r
a0afd019 135 The end time of the new record must be set to zero.\r
136 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
137 If TimeStamp is zero, the start time in the record is filled in with the value\r
138 read from the current time stamp.\r
139\r
140 @param Handle Pointer to environment specific context used\r
141 to identify the component being measured.\r
142 @param Token Pointer to a Null-terminated ASCII string\r
143 that identifies the component being measured.\r
144 @param Module Pointer to a Null-terminated ASCII string\r
145 that identifies the module being measured.\r
146 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
147 @param Identifier 32-bit identifier. If the value is 0, the created record\r
148 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.\r
a0afd019 149\r
150 @retval EFI_SUCCESS The data was read correctly from the device.\r
151 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
152\r
153**/\r
a0afd019 154EFI_STATUS\r
155EFIAPI\r
f0da4d7d 156StartGaugeEx (\r
a0afd019 157 IN CONST VOID *Handle, OPTIONAL\r
158 IN CONST CHAR8 *Token, OPTIONAL\r
159 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
160 IN UINT64 TimeStamp,\r
161 IN UINT32 Identifier\r
a0afd019 162 )\r
163{\r
f0da4d7d 164 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
a0afd019 165 UINTN GaugeDataSize;\r
f0da4d7d 166 GAUGE_DATA_HEADER *NewGaugeData;\r
a0afd019 167 UINTN OldGaugeDataSize;\r
168 GAUGE_DATA_HEADER *OldGaugeData;\r
169 UINT32 Index;\r
f1f7190b
HG
170 EFI_STATUS Status;\r
171\r
172 Status = EfiAcquireLockOrFail (&mPerfRecordLock);\r
173 if (EFI_ERROR (Status)) {\r
174 return Status;\r
175 }\r
a0afd019 176\r
177 Index = mGaugeData->NumberOfEntries;\r
178 if (Index >= mMaxGaugeRecords) {\r
179 //\r
857dfc45 180 // Try to enlarge the scale of gauge array.\r
a0afd019 181 //\r
182 OldGaugeData = mGaugeData;\r
f0da4d7d 183 OldGaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords;\r
a0afd019 184\r
f0da4d7d 185 GaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2;\r
a0afd019 186\r
f0da4d7d
SZ
187 NewGaugeData = AllocateZeroPool (GaugeDataSize);\r
188 if (NewGaugeData == NULL) {\r
f1f7190b 189 EfiReleaseLock (&mPerfRecordLock);\r
a0afd019 190 return EFI_OUT_OF_RESOURCES;\r
191 }\r
f0da4d7d
SZ
192\r
193 mGaugeData = NewGaugeData;\r
194 mMaxGaugeRecords *= 2;\r
195\r
a0afd019 196 //\r
857dfc45 197 // Initialize new data array and migrate old data one.\r
a0afd019 198 //\r
199 mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize);\r
200\r
201 FreePool (OldGaugeData);\r
202 }\r
203\r
f0da4d7d
SZ
204 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
205 GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;\r
a0afd019 206\r
207 if (Token != NULL) {\r
0ec2bfc8 208 AsciiStrnCpyS (GaugeEntryExArray[Index].Token, DXE_PERFORMANCE_STRING_SIZE, Token, DXE_PERFORMANCE_STRING_LENGTH);\r
a0afd019 209 }\r
210 if (Module != NULL) {\r
0ec2bfc8 211 AsciiStrnCpyS (GaugeEntryExArray[Index].Module, DXE_PERFORMANCE_STRING_SIZE, Module, DXE_PERFORMANCE_STRING_LENGTH);\r
a0afd019 212 }\r
213\r
f0da4d7d
SZ
214 GaugeEntryExArray[Index].EndTimeStamp = 0;\r
215 GaugeEntryExArray[Index].Identifier = Identifier;\r
216\r
a0afd019 217 if (TimeStamp == 0) {\r
218 TimeStamp = GetPerformanceCounter ();\r
219 }\r
f0da4d7d 220 GaugeEntryExArray[Index].StartTimeStamp = TimeStamp;\r
a0afd019 221\r
222 mGaugeData->NumberOfEntries++;\r
223\r
f1f7190b
HG
224 EfiReleaseLock (&mPerfRecordLock);\r
225\r
a0afd019 226 return EFI_SUCCESS;\r
227}\r
228\r
229/**\r
230 Searches the performance measurement log from the beginning of the log\r
231 for the first matching record that contains a zero end time and fills in a valid end time.\r
232\r
233 Searches the performance measurement log from the beginning of the log\r
7a9395cd 234 for the first record that matches Handle, Token and Module and has an end time value of zero.\r
a0afd019 235 If the record can not be found then return EFI_NOT_FOUND.\r
236 If the record is found and TimeStamp is not zero,\r
237 then the end time in the record is filled in with the value specified by TimeStamp.\r
238 If the record is found and TimeStamp is zero, then the end time in the matching record\r
239 is filled in with the current time stamp value.\r
240\r
241 @param Handle Pointer to environment specific context used\r
242 to identify the component being measured.\r
243 @param Token Pointer to a Null-terminated ASCII string\r
244 that identifies the component being measured.\r
245 @param Module Pointer to a Null-terminated ASCII string\r
246 that identifies the module being measured.\r
247 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
248 @param Identifier 32-bit identifier. If the value is 0, the found record\r
249 is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.\r
a0afd019 250\r
251 @retval EFI_SUCCESS The end of the measurement was recorded.\r
252 @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
253\r
254**/\r
a0afd019 255EFI_STATUS\r
256EFIAPI\r
f0da4d7d 257EndGaugeEx (\r
a0afd019 258 IN CONST VOID *Handle, OPTIONAL\r
259 IN CONST CHAR8 *Token, OPTIONAL\r
260 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
261 IN UINT64 TimeStamp,\r
262 IN UINT32 Identifier\r
a0afd019 263 )\r
264{\r
f0da4d7d
SZ
265 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
266 UINT32 Index;\r
f1f7190b
HG
267 EFI_STATUS Status;\r
268\r
269 Status = EfiAcquireLockOrFail (&mPerfRecordLock);\r
270 if (EFI_ERROR (Status)) {\r
271 return Status;\r
272 }\r
a0afd019 273\r
274 if (TimeStamp == 0) {\r
275 TimeStamp = GetPerformanceCounter ();\r
276 }\r
277\r
f0da4d7d 278 Index = InternalSearchForGaugeEntry (Handle, Token, Module, Identifier);\r
a0afd019 279 if (Index >= mGaugeData->NumberOfEntries) {\r
f1f7190b 280 EfiReleaseLock (&mPerfRecordLock);\r
a0afd019 281 return EFI_NOT_FOUND;\r
282 }\r
f0da4d7d
SZ
283 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
284 GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;\r
a0afd019 285\r
f1f7190b 286 EfiReleaseLock (&mPerfRecordLock);\r
a0afd019 287 return EFI_SUCCESS;\r
288}\r
289\r
290/**\r
291 Retrieves a previously logged performance measurement.\r
f0da4d7d
SZ
292 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,\r
293 and then assign the Identifier with 0.\r
a0afd019 294\r
295 Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
296 If it stands for a valid entry, then EFI_SUCCESS is returned and\r
f0da4d7d 297 GaugeDataEntryEx stores the pointer to that entry.\r
a0afd019 298\r
f1f7190b
HG
299 This internal function is added to avoid releasing lock before each return statement.\r
300\r
a0afd019 301 @param LogEntryKey The key for the previous performance measurement log entry.\r
302 If 0, then the first performance measurement log entry is retrieved.\r
f0da4d7d 303 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey\r
a0afd019 304 if the retrieval is successful.\r
305\r
f0da4d7d 306 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.\r
a0afd019 307 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
308 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
f0da4d7d 309 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.\r
a0afd019 310\r
311**/\r
a0afd019 312EFI_STATUS\r
313EFIAPI\r
f1f7190b 314InternalGetGaugeEx (\r
f0da4d7d
SZ
315 IN UINTN LogEntryKey,\r
316 OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx\r
a0afd019 317 )\r
318{\r
319 UINTN NumberOfEntries;\r
f0da4d7d 320 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
a0afd019 321\r
322 NumberOfEntries = (UINTN) (mGaugeData->NumberOfEntries);\r
323 if (LogEntryKey > NumberOfEntries) {\r
324 return EFI_INVALID_PARAMETER;\r
325 }\r
326 if (LogEntryKey == NumberOfEntries) {\r
327 return EFI_NOT_FOUND;\r
328 }\r
329\r
f0da4d7d
SZ
330 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
331\r
332 if (GaugeDataEntryEx == NULL) {\r
333 return EFI_INVALID_PARAMETER;\r
334 }\r
335 *GaugeDataEntryEx = &GaugeEntryExArray[LogEntryKey];\r
336\r
337 return EFI_SUCCESS;\r
338}\r
339\r
f1f7190b
HG
340/**\r
341 Retrieves a previously logged performance measurement.\r
342 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,\r
343 and then assign the Identifier with 0.\r
344\r
345 Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
346 If it stands for a valid entry, then EFI_SUCCESS is returned and\r
347 GaugeDataEntryEx stores the pointer to that entry.\r
348\r
349 @param LogEntryKey The key for the previous performance measurement log entry.\r
350 If 0, then the first performance measurement log entry is retrieved.\r
351 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey\r
352 if the retrieval is successful.\r
353\r
354 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.\r
355 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
356 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
357 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.\r
358\r
359**/\r
360EFI_STATUS\r
361EFIAPI\r
362GetGaugeEx (\r
363 IN UINTN LogEntryKey,\r
364 OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx\r
365 )\r
366{\r
367 EFI_STATUS Status;\r
368\r
369 Status = EfiAcquireLockOrFail (&mPerfRecordLock);\r
370 if (EFI_ERROR (Status)) {\r
371 return Status;\r
372 }\r
373\r
374 Status = InternalGetGaugeEx (LogEntryKey, GaugeDataEntryEx);\r
375\r
376 EfiReleaseLock (&mPerfRecordLock);\r
377\r
378 return Status;\r
379}\r
380\r
f0da4d7d
SZ
381/**\r
382 Adds a record at the end of the performance measurement log\r
383 that records the start time of a performance measurement.\r
384\r
385 Adds a record to the end of the performance measurement log\r
386 that contains the Handle, Token, and Module.\r
387 The end time of the new record must be set to zero.\r
388 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
389 If TimeStamp is zero, the start time in the record is filled in with the value\r
390 read from the current time stamp.\r
391\r
392 @param Handle Pointer to environment specific context used\r
393 to identify the component being measured.\r
394 @param Token Pointer to a Null-terminated ASCII string\r
395 that identifies the component being measured.\r
396 @param Module Pointer to a Null-terminated ASCII string\r
397 that identifies the module being measured.\r
398 @param TimeStamp 64-bit time stamp.\r
399\r
400 @retval EFI_SUCCESS The data was read correctly from the device.\r
401 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
402\r
403**/\r
404EFI_STATUS\r
405EFIAPI\r
406StartGauge (\r
407 IN CONST VOID *Handle, OPTIONAL\r
408 IN CONST CHAR8 *Token, OPTIONAL\r
409 IN CONST CHAR8 *Module, OPTIONAL\r
410 IN UINT64 TimeStamp\r
411 )\r
412{\r
413 return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
414}\r
415\r
416/**\r
417 Searches the performance measurement log from the beginning of the log\r
418 for the first matching record that contains a zero end time and fills in a valid end time.\r
419\r
420 Searches the performance measurement log from the beginning of the log\r
421 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
422 If the record can not be found then return EFI_NOT_FOUND.\r
423 If the record is found and TimeStamp is not zero,\r
424 then the end time in the record is filled in with the value specified by TimeStamp.\r
425 If the record is found and TimeStamp is zero, then the end time in the matching record\r
426 is filled in with the current time stamp value.\r
427\r
428 @param Handle Pointer to environment specific context used\r
429 to identify the component being measured.\r
430 @param Token Pointer to a Null-terminated ASCII string\r
431 that identifies the component being measured.\r
432 @param Module Pointer to a Null-terminated ASCII string\r
433 that identifies the module being measured.\r
434 @param TimeStamp 64-bit time stamp.\r
435\r
436 @retval EFI_SUCCESS The end of the measurement was recorded.\r
437 @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
438\r
439**/\r
440EFI_STATUS\r
441EFIAPI\r
442EndGauge (\r
443 IN CONST VOID *Handle, OPTIONAL\r
444 IN CONST CHAR8 *Token, OPTIONAL\r
445 IN CONST CHAR8 *Module, OPTIONAL\r
446 IN UINT64 TimeStamp\r
447 )\r
448{\r
449 return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
450}\r
451\r
452/**\r
453 Retrieves a previously logged performance measurement.\r
454 It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,\r
455 and then eliminate the Identifier.\r
456\r
457 Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
458 If it stands for a valid entry, then EFI_SUCCESS is returned and\r
459 GaugeDataEntry stores the pointer to that entry.\r
460\r
461 @param LogEntryKey The key for the previous performance measurement log entry.\r
462 If 0, then the first performance measurement log entry is retrieved.\r
463 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey\r
464 if the retrieval is successful.\r
465\r
466 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.\r
467 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
468 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
469 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.\r
470\r
471**/\r
472EFI_STATUS\r
473EFIAPI\r
474GetGauge (\r
475 IN UINTN LogEntryKey,\r
476 OUT GAUGE_DATA_ENTRY **GaugeDataEntry\r
477 )\r
478{\r
479 EFI_STATUS Status;\r
480 GAUGE_DATA_ENTRY_EX *GaugeEntryEx;\r
481\r
1658440e
SZ
482 GaugeEntryEx = NULL;\r
483\r
f0da4d7d
SZ
484 Status = GetGaugeEx (LogEntryKey, &GaugeEntryEx);\r
485 if (EFI_ERROR (Status)) {\r
486 return Status;\r
487 }\r
a0afd019 488\r
489 if (GaugeDataEntry == NULL) {\r
490 return EFI_INVALID_PARAMETER;\r
491 }\r
f0da4d7d
SZ
492\r
493 *GaugeDataEntry = (GAUGE_DATA_ENTRY *) GaugeEntryEx;\r
a0afd019 494\r
495 return EFI_SUCCESS;\r
496}\r
497\r
498/**\r
499 Dumps all the PEI performance log to DXE performance gauge array.\r
500\r
501 This internal function dumps all the PEI performance log to the DXE performance gauge array.\r
502 It retrieves the optional GUID HOB for PEI performance and then saves the performance data\r
503 to DXE performance data structures.\r
504\r
505**/\r
a0afd019 506VOID\r
507InternalGetPeiPerformance (\r
508 VOID\r
509 )\r
510{\r
511 EFI_HOB_GUID_TYPE *GuidHob;\r
512 PEI_PERFORMANCE_LOG_HEADER *LogHob;\r
513 PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray;\r
f0da4d7d
SZ
514 UINT32 *LogIdArray;\r
515 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
a0afd019 516 UINT32 Index;\r
517 UINT32 NumberOfEntries;\r
518\r
519 NumberOfEntries = 0;\r
f0da4d7d 520 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
a0afd019 521\r
522 //\r
523 // Dump PEI Log Entries to DXE Guage Data structure.\r
524 //\r
ee0961f7 525 GuidHob = GetFirstGuidHob (&gPerformanceProtocolGuid);\r
a0afd019 526 if (GuidHob != NULL) {\r
527 LogHob = GET_GUID_HOB_DATA (GuidHob);\r
528 LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (LogHob + 1);\r
a0afd019 529\r
530 NumberOfEntries = LogHob->NumberOfEntries;\r
531 for (Index = 0; Index < NumberOfEntries; Index++) {\r
f0da4d7d 532 GaugeEntryExArray[Index].Handle = LogEntryArray[Index].Handle;\r
96f983fa
QS
533 AsciiStrCpyS (GaugeEntryExArray[Index].Token, DXE_PERFORMANCE_STRING_SIZE, LogEntryArray[Index].Token);\r
534 AsciiStrCpyS (GaugeEntryExArray[Index].Module, DXE_PERFORMANCE_STRING_SIZE, LogEntryArray[Index].Module);\r
f0da4d7d
SZ
535 GaugeEntryExArray[Index].StartTimeStamp = LogEntryArray[Index].StartTimeStamp;\r
536 GaugeEntryExArray[Index].EndTimeStamp = LogEntryArray[Index].EndTimeStamp;\r
537 GaugeEntryExArray[Index].Identifier = 0;\r
538 }\r
539\r
540 GuidHob = GetFirstGuidHob (&gPerformanceExProtocolGuid);\r
541 if (GuidHob != NULL) {\r
542 LogIdArray = GET_GUID_HOB_DATA (GuidHob);\r
543 for (Index = 0; Index < NumberOfEntries; Index++) {\r
544 GaugeEntryExArray[Index].Identifier = LogIdArray[Index];\r
545 }\r
a0afd019 546 }\r
547 }\r
548 mGaugeData->NumberOfEntries = NumberOfEntries;\r
549}\r
550\r
551/**\r
552 The constructor function initializes Performance infrastructure for DXE phase.\r
553\r
f0da4d7d 554 The constructor function publishes Performance and PerformanceEx protocol, allocates memory to log DXE performance\r
a0afd019 555 and merges PEI performance data to DXE performance log.\r
556 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.\r
557\r
558 @param ImageHandle The firmware allocated handle for the EFI image.\r
559 @param SystemTable A pointer to the EFI System Table.\r
560\r
561 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
562\r
563**/\r
564EFI_STATUS\r
565EFIAPI\r
566DxeCorePerformanceLibConstructor (\r
567 IN EFI_HANDLE ImageHandle,\r
568 IN EFI_SYSTEM_TABLE *SystemTable\r
569 )\r
570{\r
571 EFI_STATUS Status;\r
cfb0aba7
SZ
572 PERFORMANCE_PROPERTY *PerformanceProperty;\r
573\r
a0afd019 574\r
575 if (!PerformanceMeasurementEnabled ()) {\r
576 //\r
577 // Do not initialize performance infrastructure if not required.\r
578 //\r
579 return EFI_SUCCESS;\r
580 }\r
581 //\r
582 // Install the protocol interfaces.\r
583 //\r
f0da4d7d 584 Status = gBS->InstallMultipleProtocolInterfaces (\r
a0afd019 585 &mHandle,\r
586 &gPerformanceProtocolGuid,\r
f0da4d7d
SZ
587 &mPerformanceInterface,\r
588 &gPerformanceExProtocolGuid,\r
589 &mPerformanceExInterface,\r
590 NULL\r
a0afd019 591 );\r
592 ASSERT_EFI_ERROR (Status);\r
593\r
7c50b343
CS
594 mMaxGaugeRecords = INIT_DXE_GAUGE_DATA_ENTRIES + (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?\r
595 PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :\r
596 PcdGet8 (PcdMaxPeiPerformanceLogEntries));\r
a0afd019 597\r
f0da4d7d 598 mGaugeData = AllocateZeroPool (sizeof (GAUGE_DATA_HEADER) + (sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords));\r
a0afd019 599 ASSERT (mGaugeData != NULL);\r
600\r
601 InternalGetPeiPerformance ();\r
602\r
9802d6d5 603 Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty);\r
cfb0aba7
SZ
604 if (EFI_ERROR (Status)) {\r
605 //\r
606 // Install configuration table for performance property.\r
607 //\r
608 mPerformanceProperty.Revision = PERFORMANCE_PROPERTY_REVISION;\r
609 mPerformanceProperty.Reserved = 0;\r
610 mPerformanceProperty.Frequency = GetPerformanceCounterProperties (\r
611 &mPerformanceProperty.TimerStartValue,\r
612 &mPerformanceProperty.TimerEndValue\r
613 );\r
614 Status = gBS->InstallConfigurationTable (&gPerformanceProtocolGuid, &mPerformanceProperty);\r
615 ASSERT_EFI_ERROR (Status);\r
616 }\r
617\r
618 return EFI_SUCCESS;\r
a0afd019 619}\r
620\r
621/**\r
622 Adds a record at the end of the performance measurement log\r
623 that records the start time of a performance measurement.\r
624\r
625 Adds a record to the end of the performance measurement log\r
f0da4d7d 626 that contains the Handle, Token, Module and Identifier.\r
a0afd019 627 The end time of the new record must be set to zero.\r
628 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
629 If TimeStamp is zero, the start time in the record is filled in with the value\r
630 read from the current time stamp.\r
631\r
632 @param Handle Pointer to environment specific context used\r
633 to identify the component being measured.\r
634 @param Token Pointer to a Null-terminated ASCII string\r
635 that identifies the component being measured.\r
636 @param Module Pointer to a Null-terminated ASCII string\r
637 that identifies the module being measured.\r
638 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
639 @param Identifier 32-bit identifier. If the value is 0, the created record\r
640 is same as the one created by StartPerformanceMeasurement.\r
a0afd019 641\r
642 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
643 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
644\r
645**/\r
646RETURN_STATUS\r
647EFIAPI\r
f0da4d7d 648StartPerformanceMeasurementEx (\r
a0afd019 649 IN CONST VOID *Handle, OPTIONAL\r
650 IN CONST CHAR8 *Token, OPTIONAL\r
651 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
652 IN UINT64 TimeStamp,\r
653 IN UINT32 Identifier\r
a0afd019 654 )\r
655{\r
f0da4d7d 656 return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
a0afd019 657}\r
658\r
659/**\r
660 Searches the performance measurement log from the beginning of the log\r
661 for the first matching record that contains a zero end time and fills in a valid end time.\r
662\r
663 Searches the performance measurement log from the beginning of the log\r
7a9395cd 664 for the first record that matches Handle, Token and Module and has an end time value of zero.\r
a0afd019 665 If the record can not be found then return RETURN_NOT_FOUND.\r
666 If the record is found and TimeStamp is not zero,\r
667 then the end time in the record is filled in with the value specified by TimeStamp.\r
668 If the record is found and TimeStamp is zero, then the end time in the matching record\r
669 is filled in with the current time stamp value.\r
670\r
671 @param Handle Pointer to environment specific context used\r
672 to identify the component being measured.\r
673 @param Token Pointer to a Null-terminated ASCII string\r
674 that identifies the component being measured.\r
675 @param Module Pointer to a Null-terminated ASCII string\r
676 that identifies the module being measured.\r
677 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
678 @param Identifier 32-bit identifier. If the value is 0, the found record\r
679 is same as the one found by EndPerformanceMeasurement.\r
a0afd019 680\r
681 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
682 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
683\r
684**/\r
685RETURN_STATUS\r
686EFIAPI\r
f0da4d7d 687EndPerformanceMeasurementEx (\r
a0afd019 688 IN CONST VOID *Handle, OPTIONAL\r
689 IN CONST CHAR8 *Token, OPTIONAL\r
690 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
691 IN UINT64 TimeStamp,\r
692 IN UINT32 Identifier\r
a0afd019 693 )\r
694{\r
f0da4d7d 695 return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
a0afd019 696}\r
697\r
698/**\r
699 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
f0da4d7d
SZ
700 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,\r
701 and then assign the Identifier with 0.\r
a0afd019 702\r
703 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
704 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
705 and the key for the second entry in the log is returned. If the performance log is empty,\r
706 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
707 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
708 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
709 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
710 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
711 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
f0da4d7d 712 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.\r
a0afd019 713 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
714 If Handle is NULL, then ASSERT().\r
715 If Token is NULL, then ASSERT().\r
716 If Module is NULL, then ASSERT().\r
717 If StartTimeStamp is NULL, then ASSERT().\r
718 If EndTimeStamp is NULL, then ASSERT().\r
f0da4d7d 719 If Identifier is NULL, then ASSERT().\r
a0afd019 720\r
721 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
722 0, then the first performance measurement log entry is retrieved.\r
857dfc45 723 On exit, the key of the next performance log entry.\r
a0afd019 724 @param Handle Pointer to environment specific context used to identify the component\r
725 being measured.\r
726 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
727 being measured.\r
728 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
729 being measured.\r
730 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
731 was started.\r
732 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
733 was ended.\r
f0da4d7d 734 @param Identifier Pointer to the 32-bit identifier that was recorded.\r
a0afd019 735\r
736 @return The key for the next performance log entry (in general case).\r
737\r
738**/\r
739UINTN\r
740EFIAPI\r
f0da4d7d
SZ
741GetPerformanceMeasurementEx (\r
742 IN UINTN LogEntryKey, \r
a0afd019 743 OUT CONST VOID **Handle,\r
744 OUT CONST CHAR8 **Token,\r
745 OUT CONST CHAR8 **Module,\r
746 OUT UINT64 *StartTimeStamp,\r
f0da4d7d
SZ
747 OUT UINT64 *EndTimeStamp,\r
748 OUT UINT32 *Identifier\r
a0afd019 749 )\r
750{\r
f0da4d7d
SZ
751 EFI_STATUS Status;\r
752 GAUGE_DATA_ENTRY_EX *GaugeData;\r
a0afd019 753\r
952671b3 754 GaugeData = NULL;\r
755 \r
a0afd019 756 ASSERT (Handle != NULL);\r
757 ASSERT (Token != NULL);\r
758 ASSERT (Module != NULL);\r
759 ASSERT (StartTimeStamp != NULL);\r
760 ASSERT (EndTimeStamp != NULL);\r
f0da4d7d 761 ASSERT (Identifier != NULL);\r
a0afd019 762\r
f0da4d7d 763 Status = GetGaugeEx (LogEntryKey++, &GaugeData);\r
a0afd019 764\r
765 //\r
766 // Make sure that LogEntryKey is a valid log entry key,\r
767 //\r
768 ASSERT (Status != EFI_INVALID_PARAMETER);\r
769\r
770 if (EFI_ERROR (Status)) {\r
771 //\r
772 // The LogEntryKey is the last entry (equals to the total entry number).\r
773 //\r
774 return 0;\r
775 }\r
776\r
777 ASSERT (GaugeData != NULL);\r
778\r
779 *Handle = (VOID *) (UINTN) GaugeData->Handle;\r
780 *Token = GaugeData->Token;\r
781 *Module = GaugeData->Module;\r
782 *StartTimeStamp = GaugeData->StartTimeStamp;\r
783 *EndTimeStamp = GaugeData->EndTimeStamp;\r
f0da4d7d 784 *Identifier = GaugeData->Identifier;\r
a0afd019 785\r
786 return LogEntryKey;\r
787}\r
788\r
f0da4d7d
SZ
789/**\r
790 Adds a record at the end of the performance measurement log\r
791 that records the start time of a performance measurement.\r
792\r
793 Adds a record to the end of the performance measurement log\r
794 that contains the Handle, Token, and Module.\r
795 The end time of the new record must be set to zero.\r
796 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
797 If TimeStamp is zero, the start time in the record is filled in with the value\r
798 read from the current time stamp.\r
799\r
800 @param Handle Pointer to environment specific context used\r
801 to identify the component being measured.\r
802 @param Token Pointer to a Null-terminated ASCII string\r
803 that identifies the component being measured.\r
804 @param Module Pointer to a Null-terminated ASCII string\r
805 that identifies the module being measured.\r
806 @param TimeStamp 64-bit time stamp.\r
807\r
808 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
809 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
810\r
811**/\r
812RETURN_STATUS\r
813EFIAPI\r
814StartPerformanceMeasurement (\r
815 IN CONST VOID *Handle, OPTIONAL\r
816 IN CONST CHAR8 *Token, OPTIONAL\r
817 IN CONST CHAR8 *Module, OPTIONAL\r
818 IN UINT64 TimeStamp\r
819 )\r
820{\r
821 return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
822}\r
823\r
824/**\r
825 Searches the performance measurement log from the beginning of the log\r
826 for the first matching record that contains a zero end time and fills in a valid end time.\r
827\r
828 Searches the performance measurement log from the beginning of the log\r
829 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
830 If the record can not be found then return RETURN_NOT_FOUND.\r
831 If the record is found and TimeStamp is not zero,\r
832 then the end time in the record is filled in with the value specified by TimeStamp.\r
833 If the record is found and TimeStamp is zero, then the end time in the matching record\r
834 is filled in with the current time stamp value.\r
835\r
836 @param Handle Pointer to environment specific context used\r
837 to identify the component being measured.\r
838 @param Token Pointer to a Null-terminated ASCII string\r
839 that identifies the component being measured.\r
840 @param Module Pointer to a Null-terminated ASCII string\r
841 that identifies the module being measured.\r
842 @param TimeStamp 64-bit time stamp.\r
843\r
844 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
845 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
846\r
847**/\r
848RETURN_STATUS\r
849EFIAPI\r
850EndPerformanceMeasurement (\r
851 IN CONST VOID *Handle, OPTIONAL\r
852 IN CONST CHAR8 *Token, OPTIONAL\r
853 IN CONST CHAR8 *Module, OPTIONAL\r
854 IN UINT64 TimeStamp\r
855 )\r
856{\r
857 return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
858}\r
859\r
860/**\r
861 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
862 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,\r
863 and then eliminate the Identifier.\r
864\r
865 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
866 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
867 and the key for the second entry in the log is returned. If the performance log is empty,\r
868 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
869 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
870 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
871 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
872 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
873 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
874 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.\r
875 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
876 If Handle is NULL, then ASSERT().\r
877 If Token is NULL, then ASSERT().\r
878 If Module is NULL, then ASSERT().\r
879 If StartTimeStamp is NULL, then ASSERT().\r
880 If EndTimeStamp is NULL, then ASSERT().\r
881\r
882 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
883 0, then the first performance measurement log entry is retrieved.\r
884 On exit, the key of the next performance log entry.\r
885 @param Handle Pointer to environment specific context used to identify the component\r
886 being measured.\r
887 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
888 being measured.\r
889 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
890 being measured.\r
891 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
892 was started.\r
893 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
894 was ended.\r
895\r
896 @return The key for the next performance log entry (in general case).\r
897\r
898**/\r
899UINTN\r
900EFIAPI\r
901GetPerformanceMeasurement (\r
902 IN UINTN LogEntryKey,\r
903 OUT CONST VOID **Handle,\r
904 OUT CONST CHAR8 **Token,\r
905 OUT CONST CHAR8 **Module,\r
906 OUT UINT64 *StartTimeStamp,\r
907 OUT UINT64 *EndTimeStamp\r
908 )\r
909{\r
910 UINT32 Identifier;\r
911 return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);\r
912}\r
913\r
a0afd019 914/**\r
915 Returns TRUE if the performance measurement macros are enabled.\r
916\r
917 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
918 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.\r
919\r
920 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
921 PcdPerformanceLibraryPropertyMask is set.\r
922 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
923 PcdPerformanceLibraryPropertyMask is clear.\r
924\r
925**/\r
926BOOLEAN\r
927EFIAPI\r
928PerformanceMeasurementEnabled (\r
929 VOID\r
930 )\r
931{\r
932 return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);\r
933}\r