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