2 Performance library instance used by SMM Core.
4 This library provides the performance measurement interfaces and initializes performance
5 logging for the SMM phase.
6 It initializes SMM phase performance logging by publishing the SMM Performance and PerformanceEx Protocol,
7 which is consumed by SmmPerformanceLib to logging performance data in SMM phase.
9 This library is mainly used by SMM Core to start performance logging to ensure that
10 SMM Performance and PerformanceEx Protocol are installed at the very beginning of SMM phase.
12 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
13 This program and the accompanying materials
14 are licensed and made available under the terms and conditions of the BSD License
15 which accompanies this distribution. The full text of the license may be found at
16 http://opensource.org/licenses/bsd-license.php
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
24 #include "SmmCorePerformanceLibInternal.h"
27 // The data structure to hold global performance data.
29 GAUGE_DATA_HEADER
*mGaugeData
;
32 // The current maximum number of logging entries. If current number of
33 // entries exceeds this value, it will re-allocate a larger array and
34 // migration the old data to the larger array.
36 UINT32 mMaxGaugeRecords
;
39 // The handle to install Performance Protocol instance.
41 EFI_HANDLE mHandle
= NULL
;
43 BOOLEAN mPerformanceMeasurementEnabled
;
45 SPIN_LOCK mSmmPerfLock
;
47 EFI_SMRAM_DESCRIPTOR
*mSmramRanges
;
48 UINTN mSmramRangeCount
;
51 // Interfaces for SMM Performance Protocol.
53 PERFORMANCE_PROTOCOL mPerformanceInterface
= {
60 // Interfaces for SMM PerformanceEx Protocol.
62 PERFORMANCE_EX_PROTOCOL mPerformanceExInterface
= {
69 Searches in the gauge array with keyword Handle, Token, Module and Identfier.
71 This internal function searches for the gauge entry in the gauge array.
72 If there is an entry that exactly matches the given keywords
73 and its end time stamp is zero, then the index of that gauge entry is returned;
74 otherwise, the the number of gauge entries in the array is returned.
76 @param Handle Pointer to environment specific context used
77 to identify the component being measured.
78 @param Token Pointer to a Null-terminated ASCII string
79 that identifies the component being measured.
80 @param Module Pointer to a Null-terminated ASCII string
81 that identifies the module being measured.
82 @param Identifier 32-bit identifier.
84 @retval The index of gauge entry in the array.
88 SmmSearchForGaugeEntry (
89 IN CONST VOID
*Handle
, OPTIONAL
90 IN CONST CHAR8
*Token
, OPTIONAL
91 IN CONST CHAR8
*Module
, OPTIONAL
92 IN CONST UINT32 Identifier
96 UINT32 NumberOfEntries
;
97 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
102 if (Module
== NULL
) {
106 NumberOfEntries
= mGaugeData
->NumberOfEntries
;
107 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
109 for (Index
= 0; Index
< NumberOfEntries
; Index
++) {
110 if ((GaugeEntryExArray
[Index
].Handle
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Handle
) &&
111 AsciiStrnCmp (GaugeEntryExArray
[Index
].Token
, Token
, SMM_PERFORMANCE_STRING_LENGTH
) == 0 &&
112 AsciiStrnCmp (GaugeEntryExArray
[Index
].Module
, Module
, SMM_PERFORMANCE_STRING_LENGTH
) == 0 &&
113 (GaugeEntryExArray
[Index
].Identifier
== Identifier
) &&
114 GaugeEntryExArray
[Index
].EndTimeStamp
== 0) {
123 Adds a record at the end of the performance measurement log
124 that records the start time of a performance measurement.
126 Adds a record to the end of the performance measurement log
127 that contains the Handle, Token, Module and Identifier.
128 The end time of the new record must be set to zero.
129 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
130 If TimeStamp is zero, the start time in the record is filled in with the value
131 read from the current time stamp.
133 @param Handle Pointer to environment specific context used
134 to identify the component being measured.
135 @param Token Pointer to a Null-terminated ASCII string
136 that identifies the component being measured.
137 @param Module Pointer to a Null-terminated ASCII string
138 that identifies the module being measured.
139 @param TimeStamp 64-bit time stamp.
140 @param Identifier 32-bit identifier. If the value is 0, the created record
141 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
143 @retval EFI_SUCCESS The data was read correctly from the device.
144 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
150 IN CONST VOID
*Handle
, OPTIONAL
151 IN CONST CHAR8
*Token
, OPTIONAL
152 IN CONST CHAR8
*Module
, OPTIONAL
157 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
159 GAUGE_DATA_HEADER
*NewGaugeData
;
160 UINTN OldGaugeDataSize
;
161 GAUGE_DATA_HEADER
*OldGaugeData
;
164 AcquireSpinLock (&mSmmPerfLock
);
166 Index
= mGaugeData
->NumberOfEntries
;
167 if (Index
>= mMaxGaugeRecords
) {
169 // Try to enlarge the scale of gauge array.
171 OldGaugeData
= mGaugeData
;
172 OldGaugeDataSize
= sizeof (GAUGE_DATA_HEADER
) + sizeof (GAUGE_DATA_ENTRY_EX
) * mMaxGaugeRecords
;
174 GaugeDataSize
= sizeof (GAUGE_DATA_HEADER
) + sizeof (GAUGE_DATA_ENTRY_EX
) * mMaxGaugeRecords
* 2;
176 NewGaugeData
= AllocateZeroPool (GaugeDataSize
);
177 if (NewGaugeData
== NULL
) {
178 ReleaseSpinLock (&mSmmPerfLock
);
179 return EFI_OUT_OF_RESOURCES
;
182 mGaugeData
= NewGaugeData
;
183 mMaxGaugeRecords
*= 2;
186 // Initialize new data array and migrate old data one.
188 mGaugeData
= CopyMem (mGaugeData
, OldGaugeData
, OldGaugeDataSize
);
190 FreePool (OldGaugeData
);
193 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
194 GaugeEntryExArray
[Index
].Handle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Handle
;
197 AsciiStrnCpy (GaugeEntryExArray
[Index
].Token
, Token
, SMM_PERFORMANCE_STRING_LENGTH
);
199 if (Module
!= NULL
) {
200 AsciiStrnCpy (GaugeEntryExArray
[Index
].Module
, Module
, SMM_PERFORMANCE_STRING_LENGTH
);
203 GaugeEntryExArray
[Index
].EndTimeStamp
= 0;
204 GaugeEntryExArray
[Index
].Identifier
= Identifier
;
206 if (TimeStamp
== 0) {
207 TimeStamp
= GetPerformanceCounter ();
209 GaugeEntryExArray
[Index
].StartTimeStamp
= TimeStamp
;
211 mGaugeData
->NumberOfEntries
++;
213 ReleaseSpinLock (&mSmmPerfLock
);
219 Searches the performance measurement log from the beginning of the log
220 for the first matching record that contains a zero end time and fills in a valid end time.
222 Searches the performance measurement log from the beginning of the log
223 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
224 If the record can not be found then return EFI_NOT_FOUND.
225 If the record is found and TimeStamp is not zero,
226 then the end time in the record is filled in with the value specified by TimeStamp.
227 If the record is found and TimeStamp is zero, then the end time in the matching record
228 is filled in with the current time stamp value.
230 @param Handle Pointer to environment specific context used
231 to identify the component being measured.
232 @param Token Pointer to a Null-terminated ASCII string
233 that identifies the component being measured.
234 @param Module Pointer to a Null-terminated ASCII string
235 that identifies the module being measured.
236 @param TimeStamp 64-bit time stamp.
237 @param Identifier 32-bit identifier. If the value is 0, the found record
238 is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
240 @retval EFI_SUCCESS The end of the measurement was recorded.
241 @retval EFI_NOT_FOUND The specified measurement record could not be found.
247 IN CONST VOID
*Handle
, OPTIONAL
248 IN CONST CHAR8
*Token
, OPTIONAL
249 IN CONST CHAR8
*Module
, OPTIONAL
254 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
257 AcquireSpinLock (&mSmmPerfLock
);
259 if (TimeStamp
== 0) {
260 TimeStamp
= GetPerformanceCounter ();
263 Index
= SmmSearchForGaugeEntry (Handle
, Token
, Module
, Identifier
);
264 if (Index
>= mGaugeData
->NumberOfEntries
) {
265 ReleaseSpinLock (&mSmmPerfLock
);
266 return EFI_NOT_FOUND
;
268 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
269 GaugeEntryExArray
[Index
].EndTimeStamp
= TimeStamp
;
271 ReleaseSpinLock (&mSmmPerfLock
);
277 Retrieves a previously logged performance measurement.
278 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
279 and then assign the Identifier with 0.
281 Retrieves the performance log entry from the performance log specified by LogEntryKey.
282 If it stands for a valid entry, then EFI_SUCCESS is returned and
283 GaugeDataEntryEx stores the pointer to that entry.
285 @param LogEntryKey The key for the previous performance measurement log entry.
286 If 0, then the first performance measurement log entry is retrieved.
287 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey
288 if the retrieval is successful.
290 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.
291 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
292 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
293 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.
299 IN UINTN LogEntryKey
,
300 OUT GAUGE_DATA_ENTRY_EX
**GaugeDataEntryEx
303 UINTN NumberOfEntries
;
304 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
306 NumberOfEntries
= (UINTN
) (mGaugeData
->NumberOfEntries
);
307 if (LogEntryKey
> NumberOfEntries
) {
308 return EFI_INVALID_PARAMETER
;
310 if (LogEntryKey
== NumberOfEntries
) {
311 return EFI_NOT_FOUND
;
314 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
316 if (GaugeDataEntryEx
== NULL
) {
317 return EFI_INVALID_PARAMETER
;
319 *GaugeDataEntryEx
= &GaugeEntryExArray
[LogEntryKey
];
325 Adds a record at the end of the performance measurement log
326 that records the start time of a performance measurement.
328 Adds a record to the end of the performance measurement log
329 that contains the Handle, Token, and Module.
330 The end time of the new record must be set to zero.
331 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
332 If TimeStamp is zero, the start time in the record is filled in with the value
333 read from the current time stamp.
335 @param Handle Pointer to environment specific context used
336 to identify the component being measured.
337 @param Token Pointer to a Null-terminated ASCII string
338 that identifies the component being measured.
339 @param Module Pointer to a Null-terminated ASCII string
340 that identifies the module being measured.
341 @param TimeStamp 64-bit time stamp.
343 @retval EFI_SUCCESS The data was read correctly from the device.
344 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
350 IN CONST VOID
*Handle
, OPTIONAL
351 IN CONST CHAR8
*Token
, OPTIONAL
352 IN CONST CHAR8
*Module
, OPTIONAL
356 return StartGaugeEx (Handle
, Token
, Module
, TimeStamp
, 0);
360 Searches the performance measurement log from the beginning of the log
361 for the first matching record that contains a zero end time and fills in a valid end time.
363 Searches the performance measurement log from the beginning of the log
364 for the first record that matches Handle, Token, and Module and has an end time value of zero.
365 If the record can not be found then return EFI_NOT_FOUND.
366 If the record is found and TimeStamp is not zero,
367 then the end time in the record is filled in with the value specified by TimeStamp.
368 If the record is found and TimeStamp is zero, then the end time in the matching record
369 is filled in with the current time stamp value.
371 @param Handle Pointer to environment specific context used
372 to identify the component being measured.
373 @param Token Pointer to a Null-terminated ASCII string
374 that identifies the component being measured.
375 @param Module Pointer to a Null-terminated ASCII string
376 that identifies the module being measured.
377 @param TimeStamp 64-bit time stamp.
379 @retval EFI_SUCCESS The end of the measurement was recorded.
380 @retval EFI_NOT_FOUND The specified measurement record could not be found.
386 IN CONST VOID
*Handle
, OPTIONAL
387 IN CONST CHAR8
*Token
, OPTIONAL
388 IN CONST CHAR8
*Module
, OPTIONAL
392 return EndGaugeEx (Handle
, Token
, Module
, TimeStamp
, 0);
396 Retrieves a previously logged performance measurement.
397 It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
398 and then eliminate the Identifier.
400 Retrieves the performance log entry from the performance log specified by LogEntryKey.
401 If it stands for a valid entry, then EFI_SUCCESS is returned and
402 GaugeDataEntry stores the pointer to that entry.
404 @param LogEntryKey The key for the previous performance measurement log entry.
405 If 0, then the first performance measurement log entry is retrieved.
406 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey
407 if the retrieval is successful.
409 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.
410 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
411 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
412 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.
418 IN UINTN LogEntryKey
,
419 OUT GAUGE_DATA_ENTRY
**GaugeDataEntry
423 GAUGE_DATA_ENTRY_EX
*GaugeEntryEx
;
427 Status
= GetGaugeEx (LogEntryKey
, &GaugeEntryEx
);
428 if (EFI_ERROR (Status
)) {
432 if (GaugeDataEntry
== NULL
) {
433 return EFI_INVALID_PARAMETER
;
436 *GaugeDataEntry
= (GAUGE_DATA_ENTRY
*) GaugeEntryEx
;
442 This function check if the address is in SMRAM.
444 @param Buffer the buffer address to be checked.
445 @param Length the buffer length to be checked.
447 @retval TRUE this address is in SMRAM.
448 @retval FALSE this address is NOT in SMRAM.
452 IN EFI_PHYSICAL_ADDRESS Buffer
,
458 for (Index
= 0; Index
< mSmramRangeCount
; Index
++) {
459 if (((Buffer
>= mSmramRanges
[Index
].CpuStart
) && (Buffer
< mSmramRanges
[Index
].CpuStart
+ mSmramRanges
[Index
].PhysicalSize
)) ||
460 ((mSmramRanges
[Index
].CpuStart
>= Buffer
) && (mSmramRanges
[Index
].CpuStart
< Buffer
+ Length
))) {
469 Communication service SMI Handler entry.
471 This SMI handler provides services for the performance wrapper driver.
473 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
474 @param[in] RegisterContext Points to an optional handler context which was specified when the
475 handler was registered.
476 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
477 be conveyed from a non-SMM environment into an SMM environment.
478 @param[in, out] CommBufferSize The size of the CommBuffer.
480 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
481 should still be called.
482 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
484 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
486 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
490 SmmPerformanceHandlerEx (
491 IN EFI_HANDLE DispatchHandle
,
492 IN CONST VOID
*RegisterContext
,
493 IN OUT VOID
*CommBuffer
,
494 IN OUT UINTN
*CommBufferSize
498 SMM_PERF_COMMUNICATE_EX
*SmmPerfCommData
;
499 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
502 GaugeEntryExArray
= NULL
;
504 ASSERT (CommBuffer
!= NULL
);
506 SmmPerfCommData
= (SMM_PERF_COMMUNICATE_EX
*)CommBuffer
;
508 switch (SmmPerfCommData
->Function
) {
509 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER
:
510 SmmPerfCommData
->NumberOfEntries
= mGaugeData
->NumberOfEntries
;
511 Status
= EFI_SUCCESS
;
514 case SMM_PERF_FUNCTION_GET_GAUGE_DATA
:
515 if ( SmmPerfCommData
->GaugeDataEx
== NULL
|| SmmPerfCommData
->NumberOfEntries
== 0 ||
516 (SmmPerfCommData
->LogEntryKey
+ SmmPerfCommData
->NumberOfEntries
) > mGaugeData
->NumberOfEntries
) {
517 Status
= EFI_INVALID_PARAMETER
;
524 DataSize
= SmmPerfCommData
->NumberOfEntries
* sizeof(GAUGE_DATA_ENTRY_EX
);
525 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS
)(UINTN
)SmmPerfCommData
->GaugeDataEx
, DataSize
)) {
526 DEBUG ((EFI_D_ERROR
, "Smm Performance Data buffer is in SMRAM!\n"));
527 Status
= EFI_ACCESS_DENIED
;
531 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
533 (UINT8
*) (SmmPerfCommData
->GaugeDataEx
),
534 (UINT8
*) &GaugeEntryExArray
[SmmPerfCommData
->LogEntryKey
],
537 Status
= EFI_SUCCESS
;
542 Status
= EFI_UNSUPPORTED
;
545 SmmPerfCommData
->ReturnStatus
= Status
;
550 Communication service SMI Handler entry.
552 This SMI handler provides services for the performance wrapper driver.
554 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
555 @param[in] RegisterContext Points to an optional handler context which was specified when the
556 handler was registered.
557 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
558 be conveyed from a non-SMM environment into an SMM environment.
559 @param[in, out] CommBufferSize The size of the CommBuffer.
561 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
562 should still be called.
563 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
565 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
567 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
571 SmmPerformanceHandler (
572 IN EFI_HANDLE DispatchHandle
,
573 IN CONST VOID
*RegisterContext
,
574 IN OUT VOID
*CommBuffer
,
575 IN OUT UINTN
*CommBufferSize
579 SMM_PERF_COMMUNICATE
*SmmPerfCommData
;
580 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
585 GaugeEntryExArray
= NULL
;
587 ASSERT (CommBuffer
!= NULL
);
589 SmmPerfCommData
= (SMM_PERF_COMMUNICATE
*)CommBuffer
;
591 switch (SmmPerfCommData
->Function
) {
592 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER
:
593 SmmPerfCommData
->NumberOfEntries
= mGaugeData
->NumberOfEntries
;
594 Status
= EFI_SUCCESS
;
597 case SMM_PERF_FUNCTION_GET_GAUGE_DATA
:
598 if ( SmmPerfCommData
->GaugeData
== NULL
|| SmmPerfCommData
->NumberOfEntries
== 0 ||
599 (SmmPerfCommData
->LogEntryKey
+ SmmPerfCommData
->NumberOfEntries
) > mGaugeData
->NumberOfEntries
) {
600 Status
= EFI_INVALID_PARAMETER
;
607 DataSize
= SmmPerfCommData
->NumberOfEntries
* sizeof(GAUGE_DATA_ENTRY
);
608 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS
)(UINTN
)SmmPerfCommData
->GaugeData
, DataSize
)) {
609 DEBUG ((EFI_D_ERROR
, "Smm Performance Data buffer is in SMRAM!\n"));
610 Status
= EFI_ACCESS_DENIED
;
614 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
616 LogEntryKey
= SmmPerfCommData
->LogEntryKey
;
617 for (Index
= 0; Index
< SmmPerfCommData
->NumberOfEntries
; Index
++) {
619 (UINT8
*) &(SmmPerfCommData
->GaugeData
[Index
]),
620 (UINT8
*) &GaugeEntryExArray
[LogEntryKey
++],
621 sizeof (GAUGE_DATA_ENTRY
)
624 Status
= EFI_SUCCESS
;
629 Status
= EFI_UNSUPPORTED
;
632 SmmPerfCommData
->ReturnStatus
= Status
;
637 SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized
638 this function is callbacked to initialize the Smm Performance Lib
640 @param Event The event of notify protocol.
641 @param Context Notify event context.
646 InitializeSmmCorePerformanceLib (
653 EFI_SMM_ACCESS2_PROTOCOL
*SmmAccess
;
658 // Initialize spin lock
660 InitializeSpinLock (&mSmmPerfLock
);
662 mMaxGaugeRecords
= INIT_SMM_GAUGE_DATA_ENTRIES
;
664 mGaugeData
= AllocateZeroPool (sizeof (GAUGE_DATA_HEADER
) + (sizeof (GAUGE_DATA_ENTRY_EX
) * mMaxGaugeRecords
));
665 ASSERT (mGaugeData
!= NULL
);
668 // Get SMRAM information
670 Status
= gBS
->LocateProtocol (&gEfiSmmAccess2ProtocolGuid
, NULL
, (VOID
**)&SmmAccess
);
671 ASSERT_EFI_ERROR (Status
);
674 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, NULL
);
675 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
677 Status
= gSmst
->SmmAllocatePool (
678 EfiRuntimeServicesData
,
680 (VOID
**)&mSmramRanges
682 ASSERT_EFI_ERROR (Status
);
684 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, mSmramRanges
);
685 ASSERT_EFI_ERROR (Status
);
687 mSmramRangeCount
= Size
/ sizeof (EFI_SMRAM_DESCRIPTOR
);
690 // Install the protocol interfaces.
692 Status
= gSmst
->SmmInstallProtocolInterface (
694 &gSmmPerformanceProtocolGuid
,
695 EFI_NATIVE_INTERFACE
,
696 &mPerformanceInterface
698 ASSERT_EFI_ERROR (Status
);
700 Status
= gSmst
->SmmInstallProtocolInterface (
702 &gSmmPerformanceExProtocolGuid
,
703 EFI_NATIVE_INTERFACE
,
704 &mPerformanceExInterface
706 ASSERT_EFI_ERROR (Status
);
709 /// Register SMM Performance SMI handler
712 Status
= gSmst
->SmiHandlerRegister (SmmPerformanceHandler
, &gSmmPerformanceProtocolGuid
, &Handle
);
713 ASSERT_EFI_ERROR (Status
);
714 Status
= gSmst
->SmiHandlerRegister (SmmPerformanceHandlerEx
, &gSmmPerformanceExProtocolGuid
, &Handle
);
715 ASSERT_EFI_ERROR (Status
);
719 The constructor function initializes the Performance Measurement Enable flag and
720 registers SmmBase2 protocol notify callback.
721 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
723 @param ImageHandle The firmware allocated handle for the EFI image.
724 @param SystemTable A pointer to the EFI System Table.
726 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
731 SmmCorePerformanceLibConstructor (
732 IN EFI_HANDLE ImageHandle
,
733 IN EFI_SYSTEM_TABLE
*SystemTable
740 mPerformanceMeasurementEnabled
= (BOOLEAN
) ((PcdGet8(PcdPerformanceLibraryPropertyMask
) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED
) != 0);
741 if (!mPerformanceMeasurementEnabled
) {
743 // Do not initialize performance infrastructure if not required.
749 // Create the events to do the library init.
751 Status
= gBS
->CreateEvent (
754 InitializeSmmCorePerformanceLib
,
758 ASSERT_EFI_ERROR (Status
);
761 // Register for protocol notifications on this event
763 Status
= gBS
->RegisterProtocolNotify (
764 &gEfiSmmBase2ProtocolGuid
,
769 ASSERT_EFI_ERROR (Status
);
775 Adds a record at the end of the performance measurement log
776 that records the start time of a performance measurement.
778 Adds a record to the end of the performance measurement log
779 that contains the Handle, Token, Module and Identifier.
780 The end time of the new record must be set to zero.
781 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
782 If TimeStamp is zero, the start time in the record is filled in with the value
783 read from the current time stamp.
785 @param Handle Pointer to environment specific context used
786 to identify the component being measured.
787 @param Token Pointer to a Null-terminated ASCII string
788 that identifies the component being measured.
789 @param Module Pointer to a Null-terminated ASCII string
790 that identifies the module being measured.
791 @param TimeStamp 64-bit time stamp.
792 @param Identifier 32-bit identifier. If the value is 0, the created record
793 is same as the one created by StartPerformanceMeasurement.
795 @retval RETURN_SUCCESS The start of the measurement was recorded.
796 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
801 StartPerformanceMeasurementEx (
802 IN CONST VOID
*Handle
, OPTIONAL
803 IN CONST CHAR8
*Token
, OPTIONAL
804 IN CONST CHAR8
*Module
, OPTIONAL
809 return (RETURN_STATUS
) StartGaugeEx (Handle
, Token
, Module
, TimeStamp
, Identifier
);
813 Searches the performance measurement log from the beginning of the log
814 for the first matching record that contains a zero end time and fills in a valid end time.
816 Searches the performance measurement log from the beginning of the log
817 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
818 If the record can not be found then return RETURN_NOT_FOUND.
819 If the record is found and TimeStamp is not zero,
820 then the end time in the record is filled in with the value specified by TimeStamp.
821 If the record is found and TimeStamp is zero, then the end time in the matching record
822 is filled in with the current time stamp value.
824 @param Handle Pointer to environment specific context used
825 to identify the component being measured.
826 @param Token Pointer to a Null-terminated ASCII string
827 that identifies the component being measured.
828 @param Module Pointer to a Null-terminated ASCII string
829 that identifies the module being measured.
830 @param TimeStamp 64-bit time stamp.
831 @param Identifier 32-bit identifier. If the value is 0, the found record
832 is same as the one found by EndPerformanceMeasurement.
834 @retval RETURN_SUCCESS The end of the measurement was recorded.
835 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
840 EndPerformanceMeasurementEx (
841 IN CONST VOID
*Handle
, OPTIONAL
842 IN CONST CHAR8
*Token
, OPTIONAL
843 IN CONST CHAR8
*Module
, OPTIONAL
848 return (RETURN_STATUS
) EndGaugeEx (Handle
, Token
, Module
, TimeStamp
, Identifier
);
852 Attempts to retrieve a performance measurement log entry from the performance measurement log.
853 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
854 and then assign the Identifier with 0.
856 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
857 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
858 and the key for the second entry in the log is returned. If the performance log is empty,
859 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
860 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
861 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
862 retrieved and an implementation specific non-zero key value that specifies the end of the performance
863 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
864 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
865 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
866 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
867 If Handle is NULL, then ASSERT().
868 If Token is NULL, then ASSERT().
869 If Module is NULL, then ASSERT().
870 If StartTimeStamp is NULL, then ASSERT().
871 If EndTimeStamp is NULL, then ASSERT().
872 If Identifier is NULL, then ASSERT().
874 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
875 0, then the first performance measurement log entry is retrieved.
876 On exit, the key of the next performance log entry.
877 @param Handle Pointer to environment specific context used to identify the component
879 @param Token Pointer to a Null-terminated ASCII string that identifies the component
881 @param Module Pointer to a Null-terminated ASCII string that identifies the module
883 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
885 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
887 @param Identifier Pointer to the 32-bit identifier that was recorded.
889 @return The key for the next performance log entry (in general case).
894 GetPerformanceMeasurementEx (
895 IN UINTN LogEntryKey
,
896 OUT CONST VOID
**Handle
,
897 OUT CONST CHAR8
**Token
,
898 OUT CONST CHAR8
**Module
,
899 OUT UINT64
*StartTimeStamp
,
900 OUT UINT64
*EndTimeStamp
,
901 OUT UINT32
*Identifier
905 GAUGE_DATA_ENTRY_EX
*GaugeData
;
909 ASSERT (Handle
!= NULL
);
910 ASSERT (Token
!= NULL
);
911 ASSERT (Module
!= NULL
);
912 ASSERT (StartTimeStamp
!= NULL
);
913 ASSERT (EndTimeStamp
!= NULL
);
914 ASSERT (Identifier
!= NULL
);
916 Status
= GetGaugeEx (LogEntryKey
++, &GaugeData
);
919 // Make sure that LogEntryKey is a valid log entry key,
921 ASSERT (Status
!= EFI_INVALID_PARAMETER
);
923 if (EFI_ERROR (Status
)) {
925 // The LogEntryKey is the last entry (equals to the total entry number).
930 ASSERT (GaugeData
!= NULL
);
932 *Handle
= (VOID
*) (UINTN
) GaugeData
->Handle
;
933 *Token
= GaugeData
->Token
;
934 *Module
= GaugeData
->Module
;
935 *StartTimeStamp
= GaugeData
->StartTimeStamp
;
936 *EndTimeStamp
= GaugeData
->EndTimeStamp
;
937 *Identifier
= GaugeData
->Identifier
;
943 Adds a record at the end of the performance measurement log
944 that records the start time of a performance measurement.
946 Adds a record to the end of the performance measurement log
947 that contains the Handle, Token, and Module.
948 The end time of the new record must be set to zero.
949 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
950 If TimeStamp is zero, the start time in the record is filled in with the value
951 read from the current time stamp.
953 @param Handle Pointer to environment specific context used
954 to identify the component being measured.
955 @param Token Pointer to a Null-terminated ASCII string
956 that identifies the component being measured.
957 @param Module Pointer to a Null-terminated ASCII string
958 that identifies the module being measured.
959 @param TimeStamp 64-bit time stamp.
961 @retval RETURN_SUCCESS The start of the measurement was recorded.
962 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
967 StartPerformanceMeasurement (
968 IN CONST VOID
*Handle
, OPTIONAL
969 IN CONST CHAR8
*Token
, OPTIONAL
970 IN CONST CHAR8
*Module
, OPTIONAL
974 return StartPerformanceMeasurementEx (Handle
, Token
, Module
, TimeStamp
, 0);
978 Searches the performance measurement log from the beginning of the log
979 for the first matching record that contains a zero end time and fills in a valid end time.
981 Searches the performance measurement log from the beginning of the log
982 for the first record that matches Handle, Token, and Module and has an end time value of zero.
983 If the record can not be found then return RETURN_NOT_FOUND.
984 If the record is found and TimeStamp is not zero,
985 then the end time in the record is filled in with the value specified by TimeStamp.
986 If the record is found and TimeStamp is zero, then the end time in the matching record
987 is filled in with the current time stamp value.
989 @param Handle Pointer to environment specific context used
990 to identify the component being measured.
991 @param Token Pointer to a Null-terminated ASCII string
992 that identifies the component being measured.
993 @param Module Pointer to a Null-terminated ASCII string
994 that identifies the module being measured.
995 @param TimeStamp 64-bit time stamp.
997 @retval RETURN_SUCCESS The end of the measurement was recorded.
998 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1003 EndPerformanceMeasurement (
1004 IN CONST VOID
*Handle
, OPTIONAL
1005 IN CONST CHAR8
*Token
, OPTIONAL
1006 IN CONST CHAR8
*Module
, OPTIONAL
1010 return EndPerformanceMeasurementEx (Handle
, Token
, Module
, TimeStamp
, 0);
1014 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1015 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
1016 and then eliminate the Identifier.
1018 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1019 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1020 and the key for the second entry in the log is returned. If the performance log is empty,
1021 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1022 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1023 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1024 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1025 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1026 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1027 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
1028 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1029 If Handle is NULL, then ASSERT().
1030 If Token is NULL, then ASSERT().
1031 If Module is NULL, then ASSERT().
1032 If StartTimeStamp is NULL, then ASSERT().
1033 If EndTimeStamp is NULL, then ASSERT().
1035 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1036 0, then the first performance measurement log entry is retrieved.
1037 On exit, the key of the next performance log entry.
1038 @param Handle Pointer to environment specific context used to identify the component
1040 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1042 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1044 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1046 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1049 @return The key for the next performance log entry (in general case).
1054 GetPerformanceMeasurement (
1055 IN UINTN LogEntryKey
,
1056 OUT CONST VOID
**Handle
,
1057 OUT CONST CHAR8
**Token
,
1058 OUT CONST CHAR8
**Module
,
1059 OUT UINT64
*StartTimeStamp
,
1060 OUT UINT64
*EndTimeStamp
1064 return GetPerformanceMeasurementEx (LogEntryKey
, Handle
, Token
, Module
, StartTimeStamp
, EndTimeStamp
, &Identifier
);
1068 Returns TRUE if the performance measurement macros are enabled.
1070 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1071 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
1073 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1074 PcdPerformanceLibraryPropertyMask is set.
1075 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1076 PcdPerformanceLibraryPropertyMask is clear.
1081 PerformanceMeasurementEnabled (
1085 return mPerformanceMeasurementEnabled
;