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
97 UINT32 NumberOfEntries
;
98 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
103 if (Module
== NULL
) {
107 NumberOfEntries
= mGaugeData
->NumberOfEntries
;
108 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
112 for (Index
= 0; Index
< NumberOfEntries
; Index
++) {
113 Index2
= NumberOfEntries
- 1 - Index
;
114 if (GaugeEntryExArray
[Index2
].EndTimeStamp
== 0 &&
115 (GaugeEntryExArray
[Index2
].Handle
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Handle
) &&
116 AsciiStrnCmp (GaugeEntryExArray
[Index2
].Token
, Token
, SMM_PERFORMANCE_STRING_LENGTH
) == 0 &&
117 AsciiStrnCmp (GaugeEntryExArray
[Index2
].Module
, Module
, SMM_PERFORMANCE_STRING_LENGTH
) == 0 &&
118 (GaugeEntryExArray
[Index2
].Identifier
== Identifier
)) {
128 Adds a record at the end of the performance measurement log
129 that records the start time of a performance measurement.
131 Adds a record to the end of the performance measurement log
132 that contains the Handle, Token, Module and Identifier.
133 The end time of the new record must be set to zero.
134 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
135 If TimeStamp is zero, the start time in the record is filled in with the value
136 read from the current time stamp.
138 @param Handle Pointer to environment specific context used
139 to identify the component being measured.
140 @param Token Pointer to a Null-terminated ASCII string
141 that identifies the component being measured.
142 @param Module Pointer to a Null-terminated ASCII string
143 that identifies the module being measured.
144 @param TimeStamp 64-bit time stamp.
145 @param Identifier 32-bit identifier. If the value is 0, the created record
146 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
148 @retval EFI_SUCCESS The data was read correctly from the device.
149 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
155 IN CONST VOID
*Handle
, OPTIONAL
156 IN CONST CHAR8
*Token
, OPTIONAL
157 IN CONST CHAR8
*Module
, OPTIONAL
162 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
164 GAUGE_DATA_HEADER
*NewGaugeData
;
165 UINTN OldGaugeDataSize
;
166 GAUGE_DATA_HEADER
*OldGaugeData
;
169 AcquireSpinLock (&mSmmPerfLock
);
171 Index
= mGaugeData
->NumberOfEntries
;
172 if (Index
>= mMaxGaugeRecords
) {
174 // Try to enlarge the scale of gauge array.
176 OldGaugeData
= mGaugeData
;
177 OldGaugeDataSize
= sizeof (GAUGE_DATA_HEADER
) + sizeof (GAUGE_DATA_ENTRY_EX
) * mMaxGaugeRecords
;
179 GaugeDataSize
= sizeof (GAUGE_DATA_HEADER
) + sizeof (GAUGE_DATA_ENTRY_EX
) * mMaxGaugeRecords
* 2;
181 NewGaugeData
= AllocateZeroPool (GaugeDataSize
);
182 if (NewGaugeData
== NULL
) {
183 ReleaseSpinLock (&mSmmPerfLock
);
184 return EFI_OUT_OF_RESOURCES
;
187 mGaugeData
= NewGaugeData
;
188 mMaxGaugeRecords
*= 2;
191 // Initialize new data array and migrate old data one.
193 mGaugeData
= CopyMem (mGaugeData
, OldGaugeData
, OldGaugeDataSize
);
195 FreePool (OldGaugeData
);
198 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
199 GaugeEntryExArray
[Index
].Handle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Handle
;
202 AsciiStrnCpy (GaugeEntryExArray
[Index
].Token
, Token
, SMM_PERFORMANCE_STRING_LENGTH
);
204 if (Module
!= NULL
) {
205 AsciiStrnCpy (GaugeEntryExArray
[Index
].Module
, Module
, SMM_PERFORMANCE_STRING_LENGTH
);
208 GaugeEntryExArray
[Index
].EndTimeStamp
= 0;
209 GaugeEntryExArray
[Index
].Identifier
= Identifier
;
211 if (TimeStamp
== 0) {
212 TimeStamp
= GetPerformanceCounter ();
214 GaugeEntryExArray
[Index
].StartTimeStamp
= TimeStamp
;
216 mGaugeData
->NumberOfEntries
++;
218 ReleaseSpinLock (&mSmmPerfLock
);
224 Searches the performance measurement log from the beginning of the log
225 for the first matching record that contains a zero end time and fills in a valid end time.
227 Searches the performance measurement log from the beginning of the log
228 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
229 If the record can not be found then return EFI_NOT_FOUND.
230 If the record is found and TimeStamp is not zero,
231 then the end time in the record is filled in with the value specified by TimeStamp.
232 If the record is found and TimeStamp is zero, then the end time in the matching record
233 is filled in with the current time stamp value.
235 @param Handle Pointer to environment specific context used
236 to identify the component being measured.
237 @param Token Pointer to a Null-terminated ASCII string
238 that identifies the component being measured.
239 @param Module Pointer to a Null-terminated ASCII string
240 that identifies the module being measured.
241 @param TimeStamp 64-bit time stamp.
242 @param Identifier 32-bit identifier. If the value is 0, the found record
243 is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
245 @retval EFI_SUCCESS The end of the measurement was recorded.
246 @retval EFI_NOT_FOUND The specified measurement record could not be found.
252 IN CONST VOID
*Handle
, OPTIONAL
253 IN CONST CHAR8
*Token
, OPTIONAL
254 IN CONST CHAR8
*Module
, OPTIONAL
259 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
262 AcquireSpinLock (&mSmmPerfLock
);
264 if (TimeStamp
== 0) {
265 TimeStamp
= GetPerformanceCounter ();
268 Index
= SmmSearchForGaugeEntry (Handle
, Token
, Module
, Identifier
);
269 if (Index
>= mGaugeData
->NumberOfEntries
) {
270 ReleaseSpinLock (&mSmmPerfLock
);
271 return EFI_NOT_FOUND
;
273 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
274 GaugeEntryExArray
[Index
].EndTimeStamp
= TimeStamp
;
276 ReleaseSpinLock (&mSmmPerfLock
);
282 Retrieves a previously logged performance measurement.
283 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
284 and then assign the Identifier with 0.
286 Retrieves the performance log entry from the performance log specified by LogEntryKey.
287 If it stands for a valid entry, then EFI_SUCCESS is returned and
288 GaugeDataEntryEx stores the pointer to that entry.
290 @param LogEntryKey The key for the previous performance measurement log entry.
291 If 0, then the first performance measurement log entry is retrieved.
292 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey
293 if the retrieval is successful.
295 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.
296 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
297 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
298 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.
304 IN UINTN LogEntryKey
,
305 OUT GAUGE_DATA_ENTRY_EX
**GaugeDataEntryEx
308 UINTN NumberOfEntries
;
309 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
311 NumberOfEntries
= (UINTN
) (mGaugeData
->NumberOfEntries
);
312 if (LogEntryKey
> NumberOfEntries
) {
313 return EFI_INVALID_PARAMETER
;
315 if (LogEntryKey
== NumberOfEntries
) {
316 return EFI_NOT_FOUND
;
319 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
321 if (GaugeDataEntryEx
== NULL
) {
322 return EFI_INVALID_PARAMETER
;
324 *GaugeDataEntryEx
= &GaugeEntryExArray
[LogEntryKey
];
330 Adds a record at the end of the performance measurement log
331 that records the start time of a performance measurement.
333 Adds a record to the end of the performance measurement log
334 that contains the Handle, Token, and Module.
335 The end time of the new record must be set to zero.
336 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
337 If TimeStamp is zero, the start time in the record is filled in with the value
338 read from the current time stamp.
340 @param Handle Pointer to environment specific context used
341 to identify the component being measured.
342 @param Token Pointer to a Null-terminated ASCII string
343 that identifies the component being measured.
344 @param Module Pointer to a Null-terminated ASCII string
345 that identifies the module being measured.
346 @param TimeStamp 64-bit time stamp.
348 @retval EFI_SUCCESS The data was read correctly from the device.
349 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
355 IN CONST VOID
*Handle
, OPTIONAL
356 IN CONST CHAR8
*Token
, OPTIONAL
357 IN CONST CHAR8
*Module
, OPTIONAL
361 return StartGaugeEx (Handle
, Token
, Module
, TimeStamp
, 0);
365 Searches the performance measurement log from the beginning of the log
366 for the first matching record that contains a zero end time and fills in a valid end time.
368 Searches the performance measurement log from the beginning of the log
369 for the first record that matches Handle, Token, and Module and has an end time value of zero.
370 If the record can not be found then return EFI_NOT_FOUND.
371 If the record is found and TimeStamp is not zero,
372 then the end time in the record is filled in with the value specified by TimeStamp.
373 If the record is found and TimeStamp is zero, then the end time in the matching record
374 is filled in with the current time stamp value.
376 @param Handle Pointer to environment specific context used
377 to identify the component being measured.
378 @param Token Pointer to a Null-terminated ASCII string
379 that identifies the component being measured.
380 @param Module Pointer to a Null-terminated ASCII string
381 that identifies the module being measured.
382 @param TimeStamp 64-bit time stamp.
384 @retval EFI_SUCCESS The end of the measurement was recorded.
385 @retval EFI_NOT_FOUND The specified measurement record could not be found.
391 IN CONST VOID
*Handle
, OPTIONAL
392 IN CONST CHAR8
*Token
, OPTIONAL
393 IN CONST CHAR8
*Module
, OPTIONAL
397 return EndGaugeEx (Handle
, Token
, Module
, TimeStamp
, 0);
401 Retrieves a previously logged performance measurement.
402 It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
403 and then eliminate the Identifier.
405 Retrieves the performance log entry from the performance log specified by LogEntryKey.
406 If it stands for a valid entry, then EFI_SUCCESS is returned and
407 GaugeDataEntry stores the pointer to that entry.
409 @param LogEntryKey The key for the previous performance measurement log entry.
410 If 0, then the first performance measurement log entry is retrieved.
411 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey
412 if the retrieval is successful.
414 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.
415 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
416 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
417 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.
423 IN UINTN LogEntryKey
,
424 OUT GAUGE_DATA_ENTRY
**GaugeDataEntry
428 GAUGE_DATA_ENTRY_EX
*GaugeEntryEx
;
432 Status
= GetGaugeEx (LogEntryKey
, &GaugeEntryEx
);
433 if (EFI_ERROR (Status
)) {
437 if (GaugeDataEntry
== NULL
) {
438 return EFI_INVALID_PARAMETER
;
441 *GaugeDataEntry
= (GAUGE_DATA_ENTRY
*) GaugeEntryEx
;
447 This function check if the address is in SMRAM.
449 @param Buffer the buffer address to be checked.
450 @param Length the buffer length to be checked.
452 @retval TRUE this address is in SMRAM.
453 @retval FALSE this address is NOT in SMRAM.
457 IN EFI_PHYSICAL_ADDRESS Buffer
,
463 for (Index
= 0; Index
< mSmramRangeCount
; Index
++) {
464 if (((Buffer
>= mSmramRanges
[Index
].CpuStart
) && (Buffer
< mSmramRanges
[Index
].CpuStart
+ mSmramRanges
[Index
].PhysicalSize
)) ||
465 ((mSmramRanges
[Index
].CpuStart
>= Buffer
) && (mSmramRanges
[Index
].CpuStart
< Buffer
+ Length
))) {
474 Communication service SMI Handler entry.
476 This SMI handler provides services for the performance wrapper driver.
478 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
479 @param[in] RegisterContext Points to an optional handler context which was specified when the
480 handler was registered.
481 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
482 be conveyed from a non-SMM environment into an SMM environment.
483 @param[in, out] CommBufferSize The size of the CommBuffer.
485 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
486 should still be called.
487 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
489 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
491 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
495 SmmPerformanceHandlerEx (
496 IN EFI_HANDLE DispatchHandle
,
497 IN CONST VOID
*RegisterContext
,
498 IN OUT VOID
*CommBuffer
,
499 IN OUT UINTN
*CommBufferSize
503 SMM_PERF_COMMUNICATE_EX
*SmmPerfCommData
;
504 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
507 GaugeEntryExArray
= NULL
;
509 ASSERT (CommBuffer
!= NULL
);
511 SmmPerfCommData
= (SMM_PERF_COMMUNICATE_EX
*)CommBuffer
;
513 switch (SmmPerfCommData
->Function
) {
514 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER
:
515 SmmPerfCommData
->NumberOfEntries
= mGaugeData
->NumberOfEntries
;
516 Status
= EFI_SUCCESS
;
519 case SMM_PERF_FUNCTION_GET_GAUGE_DATA
:
520 if ( SmmPerfCommData
->GaugeDataEx
== NULL
|| SmmPerfCommData
->NumberOfEntries
== 0 ||
521 (SmmPerfCommData
->LogEntryKey
+ SmmPerfCommData
->NumberOfEntries
) > mGaugeData
->NumberOfEntries
) {
522 Status
= EFI_INVALID_PARAMETER
;
529 DataSize
= SmmPerfCommData
->NumberOfEntries
* sizeof(GAUGE_DATA_ENTRY_EX
);
530 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS
)(UINTN
)SmmPerfCommData
->GaugeDataEx
, DataSize
)) {
531 DEBUG ((EFI_D_ERROR
, "Smm Performance Data buffer is in SMRAM!\n"));
532 Status
= EFI_ACCESS_DENIED
;
536 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
538 (UINT8
*) (SmmPerfCommData
->GaugeDataEx
),
539 (UINT8
*) &GaugeEntryExArray
[SmmPerfCommData
->LogEntryKey
],
542 Status
= EFI_SUCCESS
;
547 Status
= EFI_UNSUPPORTED
;
550 SmmPerfCommData
->ReturnStatus
= Status
;
555 Communication service SMI Handler entry.
557 This SMI handler provides services for the performance wrapper driver.
559 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
560 @param[in] RegisterContext Points to an optional handler context which was specified when the
561 handler was registered.
562 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
563 be conveyed from a non-SMM environment into an SMM environment.
564 @param[in, out] CommBufferSize The size of the CommBuffer.
566 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
567 should still be called.
568 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
570 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
572 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
576 SmmPerformanceHandler (
577 IN EFI_HANDLE DispatchHandle
,
578 IN CONST VOID
*RegisterContext
,
579 IN OUT VOID
*CommBuffer
,
580 IN OUT UINTN
*CommBufferSize
584 SMM_PERF_COMMUNICATE
*SmmPerfCommData
;
585 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
590 GaugeEntryExArray
= NULL
;
592 ASSERT (CommBuffer
!= NULL
);
594 SmmPerfCommData
= (SMM_PERF_COMMUNICATE
*)CommBuffer
;
596 switch (SmmPerfCommData
->Function
) {
597 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER
:
598 SmmPerfCommData
->NumberOfEntries
= mGaugeData
->NumberOfEntries
;
599 Status
= EFI_SUCCESS
;
602 case SMM_PERF_FUNCTION_GET_GAUGE_DATA
:
603 if ( SmmPerfCommData
->GaugeData
== NULL
|| SmmPerfCommData
->NumberOfEntries
== 0 ||
604 (SmmPerfCommData
->LogEntryKey
+ SmmPerfCommData
->NumberOfEntries
) > mGaugeData
->NumberOfEntries
) {
605 Status
= EFI_INVALID_PARAMETER
;
612 DataSize
= SmmPerfCommData
->NumberOfEntries
* sizeof(GAUGE_DATA_ENTRY
);
613 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS
)(UINTN
)SmmPerfCommData
->GaugeData
, DataSize
)) {
614 DEBUG ((EFI_D_ERROR
, "Smm Performance Data buffer is in SMRAM!\n"));
615 Status
= EFI_ACCESS_DENIED
;
619 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
621 LogEntryKey
= SmmPerfCommData
->LogEntryKey
;
622 for (Index
= 0; Index
< SmmPerfCommData
->NumberOfEntries
; Index
++) {
624 (UINT8
*) &(SmmPerfCommData
->GaugeData
[Index
]),
625 (UINT8
*) &GaugeEntryExArray
[LogEntryKey
++],
626 sizeof (GAUGE_DATA_ENTRY
)
629 Status
= EFI_SUCCESS
;
634 Status
= EFI_UNSUPPORTED
;
637 SmmPerfCommData
->ReturnStatus
= Status
;
642 SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized
643 this function is callbacked to initialize the Smm Performance Lib
645 @param Event The event of notify protocol.
646 @param Context Notify event context.
651 InitializeSmmCorePerformanceLib (
658 EFI_SMM_ACCESS2_PROTOCOL
*SmmAccess
;
663 // Initialize spin lock
665 InitializeSpinLock (&mSmmPerfLock
);
667 mMaxGaugeRecords
= INIT_SMM_GAUGE_DATA_ENTRIES
;
669 mGaugeData
= AllocateZeroPool (sizeof (GAUGE_DATA_HEADER
) + (sizeof (GAUGE_DATA_ENTRY_EX
) * mMaxGaugeRecords
));
670 ASSERT (mGaugeData
!= NULL
);
673 // Get SMRAM information
675 Status
= gBS
->LocateProtocol (&gEfiSmmAccess2ProtocolGuid
, NULL
, (VOID
**)&SmmAccess
);
676 ASSERT_EFI_ERROR (Status
);
679 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, NULL
);
680 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
682 Status
= gSmst
->SmmAllocatePool (
683 EfiRuntimeServicesData
,
685 (VOID
**)&mSmramRanges
687 ASSERT_EFI_ERROR (Status
);
689 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, mSmramRanges
);
690 ASSERT_EFI_ERROR (Status
);
692 mSmramRangeCount
= Size
/ sizeof (EFI_SMRAM_DESCRIPTOR
);
695 // Install the protocol interfaces.
697 Status
= gSmst
->SmmInstallProtocolInterface (
699 &gSmmPerformanceProtocolGuid
,
700 EFI_NATIVE_INTERFACE
,
701 &mPerformanceInterface
703 ASSERT_EFI_ERROR (Status
);
705 Status
= gSmst
->SmmInstallProtocolInterface (
707 &gSmmPerformanceExProtocolGuid
,
708 EFI_NATIVE_INTERFACE
,
709 &mPerformanceExInterface
711 ASSERT_EFI_ERROR (Status
);
714 /// Register SMM Performance SMI handler
717 Status
= gSmst
->SmiHandlerRegister (SmmPerformanceHandler
, &gSmmPerformanceProtocolGuid
, &Handle
);
718 ASSERT_EFI_ERROR (Status
);
719 Status
= gSmst
->SmiHandlerRegister (SmmPerformanceHandlerEx
, &gSmmPerformanceExProtocolGuid
, &Handle
);
720 ASSERT_EFI_ERROR (Status
);
724 The constructor function initializes the Performance Measurement Enable flag and
725 registers SmmBase2 protocol notify callback.
726 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
728 @param ImageHandle The firmware allocated handle for the EFI image.
729 @param SystemTable A pointer to the EFI System Table.
731 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
736 SmmCorePerformanceLibConstructor (
737 IN EFI_HANDLE ImageHandle
,
738 IN EFI_SYSTEM_TABLE
*SystemTable
745 mPerformanceMeasurementEnabled
= (BOOLEAN
) ((PcdGet8(PcdPerformanceLibraryPropertyMask
) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED
) != 0);
746 if (!mPerformanceMeasurementEnabled
) {
748 // Do not initialize performance infrastructure if not required.
754 // Create the events to do the library init.
756 Status
= gBS
->CreateEvent (
759 InitializeSmmCorePerformanceLib
,
763 ASSERT_EFI_ERROR (Status
);
766 // Register for protocol notifications on this event
768 Status
= gBS
->RegisterProtocolNotify (
769 &gEfiSmmBase2ProtocolGuid
,
774 ASSERT_EFI_ERROR (Status
);
780 Adds a record at the end of the performance measurement log
781 that records the start time of a performance measurement.
783 Adds a record to the end of the performance measurement log
784 that contains the Handle, Token, Module and Identifier.
785 The end time of the new record must be set to zero.
786 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
787 If TimeStamp is zero, the start time in the record is filled in with the value
788 read from the current time stamp.
790 @param Handle Pointer to environment specific context used
791 to identify the component being measured.
792 @param Token Pointer to a Null-terminated ASCII string
793 that identifies the component being measured.
794 @param Module Pointer to a Null-terminated ASCII string
795 that identifies the module being measured.
796 @param TimeStamp 64-bit time stamp.
797 @param Identifier 32-bit identifier. If the value is 0, the created record
798 is same as the one created by StartPerformanceMeasurement.
800 @retval RETURN_SUCCESS The start of the measurement was recorded.
801 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
806 StartPerformanceMeasurementEx (
807 IN CONST VOID
*Handle
, OPTIONAL
808 IN CONST CHAR8
*Token
, OPTIONAL
809 IN CONST CHAR8
*Module
, OPTIONAL
814 return (RETURN_STATUS
) StartGaugeEx (Handle
, Token
, Module
, TimeStamp
, Identifier
);
818 Searches the performance measurement log from the beginning of the log
819 for the first matching record that contains a zero end time and fills in a valid end time.
821 Searches the performance measurement log from the beginning of the log
822 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
823 If the record can not be found then return RETURN_NOT_FOUND.
824 If the record is found and TimeStamp is not zero,
825 then the end time in the record is filled in with the value specified by TimeStamp.
826 If the record is found and TimeStamp is zero, then the end time in the matching record
827 is filled in with the current time stamp value.
829 @param Handle Pointer to environment specific context used
830 to identify the component being measured.
831 @param Token Pointer to a Null-terminated ASCII string
832 that identifies the component being measured.
833 @param Module Pointer to a Null-terminated ASCII string
834 that identifies the module being measured.
835 @param TimeStamp 64-bit time stamp.
836 @param Identifier 32-bit identifier. If the value is 0, the found record
837 is same as the one found by EndPerformanceMeasurement.
839 @retval RETURN_SUCCESS The end of the measurement was recorded.
840 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
845 EndPerformanceMeasurementEx (
846 IN CONST VOID
*Handle
, OPTIONAL
847 IN CONST CHAR8
*Token
, OPTIONAL
848 IN CONST CHAR8
*Module
, OPTIONAL
853 return (RETURN_STATUS
) EndGaugeEx (Handle
, Token
, Module
, TimeStamp
, Identifier
);
857 Attempts to retrieve a performance measurement log entry from the performance measurement log.
858 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
859 and then assign the Identifier with 0.
861 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
862 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
863 and the key for the second entry in the log is returned. If the performance log is empty,
864 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
865 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
866 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
867 retrieved and an implementation specific non-zero key value that specifies the end of the performance
868 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
869 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
870 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
871 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
872 If Handle is NULL, then ASSERT().
873 If Token is NULL, then ASSERT().
874 If Module is NULL, then ASSERT().
875 If StartTimeStamp is NULL, then ASSERT().
876 If EndTimeStamp is NULL, then ASSERT().
877 If Identifier is NULL, then ASSERT().
879 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
880 0, then the first performance measurement log entry is retrieved.
881 On exit, the key of the next performance log entry.
882 @param Handle Pointer to environment specific context used to identify the component
884 @param Token Pointer to a Null-terminated ASCII string that identifies the component
886 @param Module Pointer to a Null-terminated ASCII string that identifies the module
888 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
890 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
892 @param Identifier Pointer to the 32-bit identifier that was recorded.
894 @return The key for the next performance log entry (in general case).
899 GetPerformanceMeasurementEx (
900 IN UINTN LogEntryKey
,
901 OUT CONST VOID
**Handle
,
902 OUT CONST CHAR8
**Token
,
903 OUT CONST CHAR8
**Module
,
904 OUT UINT64
*StartTimeStamp
,
905 OUT UINT64
*EndTimeStamp
,
906 OUT UINT32
*Identifier
910 GAUGE_DATA_ENTRY_EX
*GaugeData
;
914 ASSERT (Handle
!= NULL
);
915 ASSERT (Token
!= NULL
);
916 ASSERT (Module
!= NULL
);
917 ASSERT (StartTimeStamp
!= NULL
);
918 ASSERT (EndTimeStamp
!= NULL
);
919 ASSERT (Identifier
!= NULL
);
921 Status
= GetGaugeEx (LogEntryKey
++, &GaugeData
);
924 // Make sure that LogEntryKey is a valid log entry key,
926 ASSERT (Status
!= EFI_INVALID_PARAMETER
);
928 if (EFI_ERROR (Status
)) {
930 // The LogEntryKey is the last entry (equals to the total entry number).
935 ASSERT (GaugeData
!= NULL
);
937 *Handle
= (VOID
*) (UINTN
) GaugeData
->Handle
;
938 *Token
= GaugeData
->Token
;
939 *Module
= GaugeData
->Module
;
940 *StartTimeStamp
= GaugeData
->StartTimeStamp
;
941 *EndTimeStamp
= GaugeData
->EndTimeStamp
;
942 *Identifier
= GaugeData
->Identifier
;
948 Adds a record at the end of the performance measurement log
949 that records the start time of a performance measurement.
951 Adds a record to the end of the performance measurement log
952 that contains the Handle, Token, and Module.
953 The end time of the new record must be set to zero.
954 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
955 If TimeStamp is zero, the start time in the record is filled in with the value
956 read from the current time stamp.
958 @param Handle Pointer to environment specific context used
959 to identify the component being measured.
960 @param Token Pointer to a Null-terminated ASCII string
961 that identifies the component being measured.
962 @param Module Pointer to a Null-terminated ASCII string
963 that identifies the module being measured.
964 @param TimeStamp 64-bit time stamp.
966 @retval RETURN_SUCCESS The start of the measurement was recorded.
967 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
972 StartPerformanceMeasurement (
973 IN CONST VOID
*Handle
, OPTIONAL
974 IN CONST CHAR8
*Token
, OPTIONAL
975 IN CONST CHAR8
*Module
, OPTIONAL
979 return StartPerformanceMeasurementEx (Handle
, Token
, Module
, TimeStamp
, 0);
983 Searches the performance measurement log from the beginning of the log
984 for the first matching record that contains a zero end time and fills in a valid end time.
986 Searches the performance measurement log from the beginning of the log
987 for the first record that matches Handle, Token, and Module and has an end time value of zero.
988 If the record can not be found then return RETURN_NOT_FOUND.
989 If the record is found and TimeStamp is not zero,
990 then the end time in the record is filled in with the value specified by TimeStamp.
991 If the record is found and TimeStamp is zero, then the end time in the matching record
992 is filled in with the current time stamp value.
994 @param Handle Pointer to environment specific context used
995 to identify the component being measured.
996 @param Token Pointer to a Null-terminated ASCII string
997 that identifies the component being measured.
998 @param Module Pointer to a Null-terminated ASCII string
999 that identifies the module being measured.
1000 @param TimeStamp 64-bit time stamp.
1002 @retval RETURN_SUCCESS The end of the measurement was recorded.
1003 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1008 EndPerformanceMeasurement (
1009 IN CONST VOID
*Handle
, OPTIONAL
1010 IN CONST CHAR8
*Token
, OPTIONAL
1011 IN CONST CHAR8
*Module
, OPTIONAL
1015 return EndPerformanceMeasurementEx (Handle
, Token
, Module
, TimeStamp
, 0);
1019 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1020 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
1021 and then eliminate the Identifier.
1023 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1024 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1025 and the key for the second entry in the log is returned. If the performance log is empty,
1026 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1027 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1028 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1029 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1030 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1031 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1032 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
1033 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1034 If Handle is NULL, then ASSERT().
1035 If Token is NULL, then ASSERT().
1036 If Module is NULL, then ASSERT().
1037 If StartTimeStamp is NULL, then ASSERT().
1038 If EndTimeStamp is NULL, then ASSERT().
1040 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1041 0, then the first performance measurement log entry is retrieved.
1042 On exit, the key of the next performance log entry.
1043 @param Handle Pointer to environment specific context used to identify the component
1045 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1047 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1049 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1051 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1054 @return The key for the next performance log entry (in general case).
1059 GetPerformanceMeasurement (
1060 IN UINTN LogEntryKey
,
1061 OUT CONST VOID
**Handle
,
1062 OUT CONST CHAR8
**Token
,
1063 OUT CONST CHAR8
**Module
,
1064 OUT UINT64
*StartTimeStamp
,
1065 OUT UINT64
*EndTimeStamp
1069 return GetPerformanceMeasurementEx (LogEntryKey
, Handle
, Token
, Module
, StartTimeStamp
, EndTimeStamp
, &Identifier
);
1073 Returns TRUE if the performance measurement macros are enabled.
1075 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1076 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
1078 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1079 PcdPerformanceLibraryPropertyMask is set.
1080 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1081 PcdPerformanceLibraryPropertyMask is clear.
1086 PerformanceMeasurementEnabled (
1090 return mPerformanceMeasurementEnabled
;