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 Caution: This module requires additional review when modified.
13 This driver will have external input - performance data and communicate buffer in SMM mode.
14 This external input must be validated carefully to avoid security issue like
15 buffer overflow, integer overflow.
17 SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted input and do basic validation.
19 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
20 This program and the accompanying materials
21 are licensed and made available under the terms and conditions of the BSD License
22 which accompanies this distribution. The full text of the license may be found at
23 http://opensource.org/licenses/bsd-license.php
25 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
26 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
31 #include "SmmCorePerformanceLibInternal.h"
34 // The data structure to hold global performance data.
36 GAUGE_DATA_HEADER
*mGaugeData
;
39 // The current maximum number of logging entries. If current number of
40 // entries exceeds this value, it will re-allocate a larger array and
41 // migration the old data to the larger array.
43 UINT32 mMaxGaugeRecords
;
46 // The handle to install Performance Protocol instance.
48 EFI_HANDLE mHandle
= NULL
;
50 BOOLEAN mPerformanceMeasurementEnabled
;
52 SPIN_LOCK mSmmPerfLock
;
54 EFI_SMRAM_DESCRIPTOR
*mSmramRanges
;
55 UINTN mSmramRangeCount
;
58 // Interfaces for SMM Performance Protocol.
60 PERFORMANCE_PROTOCOL mPerformanceInterface
= {
67 // Interfaces for SMM PerformanceEx Protocol.
69 PERFORMANCE_EX_PROTOCOL mPerformanceExInterface
= {
76 Searches in the gauge array with keyword Handle, Token, Module and Identfier.
78 This internal function searches for the gauge entry in the gauge array.
79 If there is an entry that exactly matches the given keywords
80 and its end time stamp is zero, then the index of that gauge entry is returned;
81 otherwise, the the number of gauge entries in the array is returned.
83 @param Handle Pointer to environment specific context used
84 to identify the component being measured.
85 @param Token Pointer to a Null-terminated ASCII string
86 that identifies the component being measured.
87 @param Module Pointer to a Null-terminated ASCII string
88 that identifies the module being measured.
89 @param Identifier 32-bit identifier.
91 @retval The index of gauge entry in the array.
95 SmmSearchForGaugeEntry (
96 IN CONST VOID
*Handle
, OPTIONAL
97 IN CONST CHAR8
*Token
, OPTIONAL
98 IN CONST CHAR8
*Module
, OPTIONAL
99 IN CONST UINT32 Identifier
104 UINT32 NumberOfEntries
;
105 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
110 if (Module
== NULL
) {
114 NumberOfEntries
= mGaugeData
->NumberOfEntries
;
115 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
119 for (Index
= 0; Index
< NumberOfEntries
; Index
++) {
120 Index2
= NumberOfEntries
- 1 - Index
;
121 if (GaugeEntryExArray
[Index2
].EndTimeStamp
== 0 &&
122 (GaugeEntryExArray
[Index2
].Handle
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Handle
) &&
123 AsciiStrnCmp (GaugeEntryExArray
[Index2
].Token
, Token
, SMM_PERFORMANCE_STRING_LENGTH
) == 0 &&
124 AsciiStrnCmp (GaugeEntryExArray
[Index2
].Module
, Module
, SMM_PERFORMANCE_STRING_LENGTH
) == 0 &&
125 (GaugeEntryExArray
[Index2
].Identifier
== Identifier
)) {
135 Adds a record at the end of the performance measurement log
136 that records the start time of a performance measurement.
138 Adds a record to the end of the performance measurement log
139 that contains the Handle, Token, Module and Identifier.
140 The end time of the new record must be set to zero.
141 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
142 If TimeStamp is zero, the start time in the record is filled in with the value
143 read from the current time stamp.
145 @param Handle Pointer to environment specific context used
146 to identify the component being measured.
147 @param Token Pointer to a Null-terminated ASCII string
148 that identifies the component being measured.
149 @param Module Pointer to a Null-terminated ASCII string
150 that identifies the module being measured.
151 @param TimeStamp 64-bit time stamp.
152 @param Identifier 32-bit identifier. If the value is 0, the created record
153 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
155 @retval EFI_SUCCESS The data was read correctly from the device.
156 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
162 IN CONST VOID
*Handle
, OPTIONAL
163 IN CONST CHAR8
*Token
, OPTIONAL
164 IN CONST CHAR8
*Module
, OPTIONAL
169 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
171 GAUGE_DATA_HEADER
*NewGaugeData
;
172 UINTN OldGaugeDataSize
;
173 GAUGE_DATA_HEADER
*OldGaugeData
;
176 AcquireSpinLock (&mSmmPerfLock
);
178 Index
= mGaugeData
->NumberOfEntries
;
179 if (Index
>= mMaxGaugeRecords
) {
181 // Try to enlarge the scale of gauge array.
183 OldGaugeData
= mGaugeData
;
184 OldGaugeDataSize
= sizeof (GAUGE_DATA_HEADER
) + sizeof (GAUGE_DATA_ENTRY_EX
) * mMaxGaugeRecords
;
186 GaugeDataSize
= sizeof (GAUGE_DATA_HEADER
) + sizeof (GAUGE_DATA_ENTRY_EX
) * mMaxGaugeRecords
* 2;
188 NewGaugeData
= AllocateZeroPool (GaugeDataSize
);
189 if (NewGaugeData
== NULL
) {
190 ReleaseSpinLock (&mSmmPerfLock
);
191 return EFI_OUT_OF_RESOURCES
;
194 mGaugeData
= NewGaugeData
;
195 mMaxGaugeRecords
*= 2;
198 // Initialize new data array and migrate old data one.
200 mGaugeData
= CopyMem (mGaugeData
, OldGaugeData
, OldGaugeDataSize
);
202 FreePool (OldGaugeData
);
205 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
206 GaugeEntryExArray
[Index
].Handle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Handle
;
209 AsciiStrnCpy (GaugeEntryExArray
[Index
].Token
, Token
, SMM_PERFORMANCE_STRING_LENGTH
);
211 if (Module
!= NULL
) {
212 AsciiStrnCpy (GaugeEntryExArray
[Index
].Module
, Module
, SMM_PERFORMANCE_STRING_LENGTH
);
215 GaugeEntryExArray
[Index
].EndTimeStamp
= 0;
216 GaugeEntryExArray
[Index
].Identifier
= Identifier
;
218 if (TimeStamp
== 0) {
219 TimeStamp
= GetPerformanceCounter ();
221 GaugeEntryExArray
[Index
].StartTimeStamp
= TimeStamp
;
223 mGaugeData
->NumberOfEntries
++;
225 ReleaseSpinLock (&mSmmPerfLock
);
231 Searches the performance measurement log from the beginning of the log
232 for the first matching record that contains a zero end time and fills in a valid end time.
234 Searches the performance measurement log from the beginning of the log
235 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
236 If the record can not be found then return EFI_NOT_FOUND.
237 If the record is found and TimeStamp is not zero,
238 then the end time in the record is filled in with the value specified by TimeStamp.
239 If the record is found and TimeStamp is zero, then the end time in the matching record
240 is filled in with the current time stamp value.
242 @param Handle Pointer to environment specific context used
243 to identify the component being measured.
244 @param Token Pointer to a Null-terminated ASCII string
245 that identifies the component being measured.
246 @param Module Pointer to a Null-terminated ASCII string
247 that identifies the module being measured.
248 @param TimeStamp 64-bit time stamp.
249 @param Identifier 32-bit identifier. If the value is 0, the found record
250 is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
252 @retval EFI_SUCCESS The end of the measurement was recorded.
253 @retval EFI_NOT_FOUND The specified measurement record could not be found.
259 IN CONST VOID
*Handle
, OPTIONAL
260 IN CONST CHAR8
*Token
, OPTIONAL
261 IN CONST CHAR8
*Module
, OPTIONAL
266 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
269 AcquireSpinLock (&mSmmPerfLock
);
271 if (TimeStamp
== 0) {
272 TimeStamp
= GetPerformanceCounter ();
275 Index
= SmmSearchForGaugeEntry (Handle
, Token
, Module
, Identifier
);
276 if (Index
>= mGaugeData
->NumberOfEntries
) {
277 ReleaseSpinLock (&mSmmPerfLock
);
278 return EFI_NOT_FOUND
;
280 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
281 GaugeEntryExArray
[Index
].EndTimeStamp
= TimeStamp
;
283 ReleaseSpinLock (&mSmmPerfLock
);
289 Retrieves a previously logged performance measurement.
290 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
291 and then assign the Identifier with 0.
293 Retrieves the performance log entry from the performance log specified by LogEntryKey.
294 If it stands for a valid entry, then EFI_SUCCESS is returned and
295 GaugeDataEntryEx stores the pointer to that entry.
297 @param LogEntryKey The key for the previous performance measurement log entry.
298 If 0, then the first performance measurement log entry is retrieved.
299 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey
300 if the retrieval is successful.
302 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.
303 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
304 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
305 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.
311 IN UINTN LogEntryKey
,
312 OUT GAUGE_DATA_ENTRY_EX
**GaugeDataEntryEx
315 UINTN NumberOfEntries
;
316 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
318 NumberOfEntries
= (UINTN
) (mGaugeData
->NumberOfEntries
);
319 if (LogEntryKey
> NumberOfEntries
) {
320 return EFI_INVALID_PARAMETER
;
322 if (LogEntryKey
== NumberOfEntries
) {
323 return EFI_NOT_FOUND
;
326 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
328 if (GaugeDataEntryEx
== NULL
) {
329 return EFI_INVALID_PARAMETER
;
331 *GaugeDataEntryEx
= &GaugeEntryExArray
[LogEntryKey
];
337 Adds a record at the end of the performance measurement log
338 that records the start time of a performance measurement.
340 Adds a record to the end of the performance measurement log
341 that contains the Handle, Token, and Module.
342 The end time of the new record must be set to zero.
343 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
344 If TimeStamp is zero, the start time in the record is filled in with the value
345 read from the current time stamp.
347 @param Handle Pointer to environment specific context used
348 to identify the component being measured.
349 @param Token Pointer to a Null-terminated ASCII string
350 that identifies the component being measured.
351 @param Module Pointer to a Null-terminated ASCII string
352 that identifies the module being measured.
353 @param TimeStamp 64-bit time stamp.
355 @retval EFI_SUCCESS The data was read correctly from the device.
356 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
362 IN CONST VOID
*Handle
, OPTIONAL
363 IN CONST CHAR8
*Token
, OPTIONAL
364 IN CONST CHAR8
*Module
, OPTIONAL
368 return StartGaugeEx (Handle
, Token
, Module
, TimeStamp
, 0);
372 Searches the performance measurement log from the beginning of the log
373 for the first matching record that contains a zero end time and fills in a valid end time.
375 Searches the performance measurement log from the beginning of the log
376 for the first record that matches Handle, Token, and Module and has an end time value of zero.
377 If the record can not be found then return EFI_NOT_FOUND.
378 If the record is found and TimeStamp is not zero,
379 then the end time in the record is filled in with the value specified by TimeStamp.
380 If the record is found and TimeStamp is zero, then the end time in the matching record
381 is filled in with the current time stamp value.
383 @param Handle Pointer to environment specific context used
384 to identify the component being measured.
385 @param Token Pointer to a Null-terminated ASCII string
386 that identifies the component being measured.
387 @param Module Pointer to a Null-terminated ASCII string
388 that identifies the module being measured.
389 @param TimeStamp 64-bit time stamp.
391 @retval EFI_SUCCESS The end of the measurement was recorded.
392 @retval EFI_NOT_FOUND The specified measurement record could not be found.
398 IN CONST VOID
*Handle
, OPTIONAL
399 IN CONST CHAR8
*Token
, OPTIONAL
400 IN CONST CHAR8
*Module
, OPTIONAL
404 return EndGaugeEx (Handle
, Token
, Module
, TimeStamp
, 0);
408 Retrieves a previously logged performance measurement.
409 It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
410 and then eliminate the Identifier.
412 Retrieves the performance log entry from the performance log specified by LogEntryKey.
413 If it stands for a valid entry, then EFI_SUCCESS is returned and
414 GaugeDataEntry stores the pointer to that entry.
416 @param LogEntryKey The key for the previous performance measurement log entry.
417 If 0, then the first performance measurement log entry is retrieved.
418 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey
419 if the retrieval is successful.
421 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.
422 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
423 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
424 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.
430 IN UINTN LogEntryKey
,
431 OUT GAUGE_DATA_ENTRY
**GaugeDataEntry
435 GAUGE_DATA_ENTRY_EX
*GaugeEntryEx
;
439 Status
= GetGaugeEx (LogEntryKey
, &GaugeEntryEx
);
440 if (EFI_ERROR (Status
)) {
444 if (GaugeDataEntry
== NULL
) {
445 return EFI_INVALID_PARAMETER
;
448 *GaugeDataEntry
= (GAUGE_DATA_ENTRY
*) GaugeEntryEx
;
454 This function check if the address is in SMRAM.
456 @param Buffer the buffer address to be checked.
457 @param Length the buffer length to be checked.
459 @retval TRUE this address is in SMRAM.
460 @retval FALSE this address is NOT in SMRAM.
464 IN EFI_PHYSICAL_ADDRESS Buffer
,
470 for (Index
= 0; Index
< mSmramRangeCount
; Index
++) {
471 if (((Buffer
>= mSmramRanges
[Index
].CpuStart
) && (Buffer
< mSmramRanges
[Index
].CpuStart
+ mSmramRanges
[Index
].PhysicalSize
)) ||
472 ((mSmramRanges
[Index
].CpuStart
>= Buffer
) && (mSmramRanges
[Index
].CpuStart
< Buffer
+ Length
))) {
481 Communication service SMI Handler entry.
483 This SMI handler provides services for the performance wrapper driver.
485 Caution: This function may receive untrusted input.
486 Communicate buffer and buffer size are external input, so this function will do basic validation.
488 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
489 @param[in] RegisterContext Points to an optional handler context which was specified when the
490 handler was registered.
491 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
492 be conveyed from a non-SMM environment into an SMM environment.
493 @param[in, out] CommBufferSize The size of the CommBuffer.
495 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
496 should still be called.
497 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
499 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
501 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
505 SmmPerformanceHandlerEx (
506 IN EFI_HANDLE DispatchHandle
,
507 IN CONST VOID
*RegisterContext
,
508 IN OUT VOID
*CommBuffer
,
509 IN OUT UINTN
*CommBufferSize
513 SMM_PERF_COMMUNICATE_EX
*SmmPerfCommData
;
514 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
517 GaugeEntryExArray
= NULL
;
520 // If input is invalid, stop processing this SMI
522 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
526 if(*CommBufferSize
< sizeof (SMM_PERF_COMMUNICATE_EX
)) {
530 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS
)(UINTN
)CommBuffer
, *CommBufferSize
)) {
531 DEBUG ((EFI_D_ERROR
, "SMM communcation data buffer is in SMRAM!\n"));
535 SmmPerfCommData
= (SMM_PERF_COMMUNICATE_EX
*)CommBuffer
;
537 switch (SmmPerfCommData
->Function
) {
538 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER
:
539 SmmPerfCommData
->NumberOfEntries
= mGaugeData
->NumberOfEntries
;
540 Status
= EFI_SUCCESS
;
543 case SMM_PERF_FUNCTION_GET_GAUGE_DATA
:
544 if ( SmmPerfCommData
->GaugeDataEx
== NULL
|| SmmPerfCommData
->NumberOfEntries
== 0 ||
545 (SmmPerfCommData
->LogEntryKey
+ SmmPerfCommData
->NumberOfEntries
) > mGaugeData
->NumberOfEntries
) {
546 Status
= EFI_INVALID_PARAMETER
;
553 DataSize
= SmmPerfCommData
->NumberOfEntries
* sizeof(GAUGE_DATA_ENTRY_EX
);
554 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS
)(UINTN
)SmmPerfCommData
->GaugeDataEx
, DataSize
)) {
555 DEBUG ((EFI_D_ERROR
, "SMM Performance Data buffer is in SMRAM!\n"));
556 Status
= EFI_ACCESS_DENIED
;
560 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
562 (UINT8
*) (SmmPerfCommData
->GaugeDataEx
),
563 (UINT8
*) &GaugeEntryExArray
[SmmPerfCommData
->LogEntryKey
],
566 Status
= EFI_SUCCESS
;
570 Status
= EFI_UNSUPPORTED
;
574 SmmPerfCommData
->ReturnStatus
= Status
;
580 Communication service SMI Handler entry.
582 This SMI handler provides services for the performance wrapper driver.
584 Caution: This function may receive untrusted input.
585 Communicate buffer and buffer size are external input, so this function will do basic validation.
587 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
588 @param[in] RegisterContext Points to an optional handler context which was specified when the
589 handler was registered.
590 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
591 be conveyed from a non-SMM environment into an SMM environment.
592 @param[in, out] CommBufferSize The size of the CommBuffer.
594 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
595 should still be called.
596 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
598 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
600 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
604 SmmPerformanceHandler (
605 IN EFI_HANDLE DispatchHandle
,
606 IN CONST VOID
*RegisterContext
,
607 IN OUT VOID
*CommBuffer
,
608 IN OUT UINTN
*CommBufferSize
612 SMM_PERF_COMMUNICATE
*SmmPerfCommData
;
613 GAUGE_DATA_ENTRY_EX
*GaugeEntryExArray
;
618 GaugeEntryExArray
= NULL
;
621 // If input is invalid, stop processing this SMI
623 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
627 if(*CommBufferSize
< sizeof (SMM_PERF_COMMUNICATE
)) {
631 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS
)(UINTN
)CommBuffer
, *CommBufferSize
)) {
632 DEBUG ((EFI_D_ERROR
, "SMM communcation data buffer is in SMRAM!\n"));
636 SmmPerfCommData
= (SMM_PERF_COMMUNICATE
*)CommBuffer
;
638 switch (SmmPerfCommData
->Function
) {
639 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER
:
640 SmmPerfCommData
->NumberOfEntries
= mGaugeData
->NumberOfEntries
;
641 Status
= EFI_SUCCESS
;
644 case SMM_PERF_FUNCTION_GET_GAUGE_DATA
:
645 if ( SmmPerfCommData
->GaugeData
== NULL
|| SmmPerfCommData
->NumberOfEntries
== 0 ||
646 (SmmPerfCommData
->LogEntryKey
+ SmmPerfCommData
->NumberOfEntries
) > mGaugeData
->NumberOfEntries
) {
647 Status
= EFI_INVALID_PARAMETER
;
654 DataSize
= SmmPerfCommData
->NumberOfEntries
* sizeof(GAUGE_DATA_ENTRY
);
655 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS
)(UINTN
)SmmPerfCommData
->GaugeData
, DataSize
)) {
656 DEBUG ((EFI_D_ERROR
, "SMM Performance Data buffer is in SMRAM!\n"));
657 Status
= EFI_ACCESS_DENIED
;
661 GaugeEntryExArray
= (GAUGE_DATA_ENTRY_EX
*) (mGaugeData
+ 1);
663 LogEntryKey
= SmmPerfCommData
->LogEntryKey
;
664 for (Index
= 0; Index
< SmmPerfCommData
->NumberOfEntries
; Index
++) {
666 (UINT8
*) &(SmmPerfCommData
->GaugeData
[Index
]),
667 (UINT8
*) &GaugeEntryExArray
[LogEntryKey
++],
668 sizeof (GAUGE_DATA_ENTRY
)
671 Status
= EFI_SUCCESS
;
675 Status
= EFI_UNSUPPORTED
;
679 SmmPerfCommData
->ReturnStatus
= Status
;
685 SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized
686 this function is callbacked to initialize the Smm Performance Lib
688 @param Event The event of notify protocol.
689 @param Context Notify event context.
694 InitializeSmmCorePerformanceLib (
701 EFI_SMM_ACCESS2_PROTOCOL
*SmmAccess
;
706 // Initialize spin lock
708 InitializeSpinLock (&mSmmPerfLock
);
710 mMaxGaugeRecords
= INIT_SMM_GAUGE_DATA_ENTRIES
;
712 mGaugeData
= AllocateZeroPool (sizeof (GAUGE_DATA_HEADER
) + (sizeof (GAUGE_DATA_ENTRY_EX
) * mMaxGaugeRecords
));
713 ASSERT (mGaugeData
!= NULL
);
716 // Get SMRAM information
718 Status
= gBS
->LocateProtocol (&gEfiSmmAccess2ProtocolGuid
, NULL
, (VOID
**)&SmmAccess
);
719 ASSERT_EFI_ERROR (Status
);
722 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, NULL
);
723 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
725 Status
= gSmst
->SmmAllocatePool (
726 EfiRuntimeServicesData
,
728 (VOID
**)&mSmramRanges
730 ASSERT_EFI_ERROR (Status
);
732 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, mSmramRanges
);
733 ASSERT_EFI_ERROR (Status
);
735 mSmramRangeCount
= Size
/ sizeof (EFI_SMRAM_DESCRIPTOR
);
738 // Install the protocol interfaces.
740 Status
= gSmst
->SmmInstallProtocolInterface (
742 &gSmmPerformanceProtocolGuid
,
743 EFI_NATIVE_INTERFACE
,
744 &mPerformanceInterface
746 ASSERT_EFI_ERROR (Status
);
748 Status
= gSmst
->SmmInstallProtocolInterface (
750 &gSmmPerformanceExProtocolGuid
,
751 EFI_NATIVE_INTERFACE
,
752 &mPerformanceExInterface
754 ASSERT_EFI_ERROR (Status
);
757 /// Register SMM Performance SMI handler
760 Status
= gSmst
->SmiHandlerRegister (SmmPerformanceHandler
, &gSmmPerformanceProtocolGuid
, &Handle
);
761 ASSERT_EFI_ERROR (Status
);
762 Status
= gSmst
->SmiHandlerRegister (SmmPerformanceHandlerEx
, &gSmmPerformanceExProtocolGuid
, &Handle
);
763 ASSERT_EFI_ERROR (Status
);
767 The constructor function initializes the Performance Measurement Enable flag and
768 registers SmmBase2 protocol notify callback.
769 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
771 @param ImageHandle The firmware allocated handle for the EFI image.
772 @param SystemTable A pointer to the EFI System Table.
774 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
779 SmmCorePerformanceLibConstructor (
780 IN EFI_HANDLE ImageHandle
,
781 IN EFI_SYSTEM_TABLE
*SystemTable
788 mPerformanceMeasurementEnabled
= (BOOLEAN
) ((PcdGet8(PcdPerformanceLibraryPropertyMask
) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED
) != 0);
789 if (!mPerformanceMeasurementEnabled
) {
791 // Do not initialize performance infrastructure if not required.
797 // Create the events to do the library init.
799 Status
= gBS
->CreateEvent (
802 InitializeSmmCorePerformanceLib
,
806 ASSERT_EFI_ERROR (Status
);
809 // Register for protocol notifications on this event
811 Status
= gBS
->RegisterProtocolNotify (
812 &gEfiSmmBase2ProtocolGuid
,
817 ASSERT_EFI_ERROR (Status
);
823 Adds a record at the end of the performance measurement log
824 that records the start time of a performance measurement.
826 Adds a record to the end of the performance measurement log
827 that contains the Handle, Token, Module and Identifier.
828 The end time of the new record must be set to zero.
829 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
830 If TimeStamp is zero, the start time in the record is filled in with the value
831 read from the current time stamp.
833 @param Handle Pointer to environment specific context used
834 to identify the component being measured.
835 @param Token Pointer to a Null-terminated ASCII string
836 that identifies the component being measured.
837 @param Module Pointer to a Null-terminated ASCII string
838 that identifies the module being measured.
839 @param TimeStamp 64-bit time stamp.
840 @param Identifier 32-bit identifier. If the value is 0, the created record
841 is same as the one created by StartPerformanceMeasurement.
843 @retval RETURN_SUCCESS The start of the measurement was recorded.
844 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
849 StartPerformanceMeasurementEx (
850 IN CONST VOID
*Handle
, OPTIONAL
851 IN CONST CHAR8
*Token
, OPTIONAL
852 IN CONST CHAR8
*Module
, OPTIONAL
857 return (RETURN_STATUS
) StartGaugeEx (Handle
, Token
, Module
, TimeStamp
, Identifier
);
861 Searches the performance measurement log from the beginning of the log
862 for the first matching record that contains a zero end time and fills in a valid end time.
864 Searches the performance measurement log from the beginning of the log
865 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
866 If the record can not be found then return RETURN_NOT_FOUND.
867 If the record is found and TimeStamp is not zero,
868 then the end time in the record is filled in with the value specified by TimeStamp.
869 If the record is found and TimeStamp is zero, then the end time in the matching record
870 is filled in with the current time stamp value.
872 @param Handle Pointer to environment specific context used
873 to identify the component being measured.
874 @param Token Pointer to a Null-terminated ASCII string
875 that identifies the component being measured.
876 @param Module Pointer to a Null-terminated ASCII string
877 that identifies the module being measured.
878 @param TimeStamp 64-bit time stamp.
879 @param Identifier 32-bit identifier. If the value is 0, the found record
880 is same as the one found by EndPerformanceMeasurement.
882 @retval RETURN_SUCCESS The end of the measurement was recorded.
883 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
888 EndPerformanceMeasurementEx (
889 IN CONST VOID
*Handle
, OPTIONAL
890 IN CONST CHAR8
*Token
, OPTIONAL
891 IN CONST CHAR8
*Module
, OPTIONAL
896 return (RETURN_STATUS
) EndGaugeEx (Handle
, Token
, Module
, TimeStamp
, Identifier
);
900 Attempts to retrieve a performance measurement log entry from the performance measurement log.
901 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
902 and then assign the Identifier with 0.
904 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
905 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
906 and the key for the second entry in the log is returned. If the performance log is empty,
907 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
908 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
909 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
910 retrieved and an implementation specific non-zero key value that specifies the end of the performance
911 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
912 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
913 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
914 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
915 If Handle is NULL, then ASSERT().
916 If Token is NULL, then ASSERT().
917 If Module is NULL, then ASSERT().
918 If StartTimeStamp is NULL, then ASSERT().
919 If EndTimeStamp is NULL, then ASSERT().
920 If Identifier is NULL, then ASSERT().
922 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
923 0, then the first performance measurement log entry is retrieved.
924 On exit, the key of the next performance log entry.
925 @param Handle Pointer to environment specific context used to identify the component
927 @param Token Pointer to a Null-terminated ASCII string that identifies the component
929 @param Module Pointer to a Null-terminated ASCII string that identifies the module
931 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
933 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
935 @param Identifier Pointer to the 32-bit identifier that was recorded.
937 @return The key for the next performance log entry (in general case).
942 GetPerformanceMeasurementEx (
943 IN UINTN LogEntryKey
,
944 OUT CONST VOID
**Handle
,
945 OUT CONST CHAR8
**Token
,
946 OUT CONST CHAR8
**Module
,
947 OUT UINT64
*StartTimeStamp
,
948 OUT UINT64
*EndTimeStamp
,
949 OUT UINT32
*Identifier
953 GAUGE_DATA_ENTRY_EX
*GaugeData
;
957 ASSERT (Handle
!= NULL
);
958 ASSERT (Token
!= NULL
);
959 ASSERT (Module
!= NULL
);
960 ASSERT (StartTimeStamp
!= NULL
);
961 ASSERT (EndTimeStamp
!= NULL
);
962 ASSERT (Identifier
!= NULL
);
964 Status
= GetGaugeEx (LogEntryKey
++, &GaugeData
);
967 // Make sure that LogEntryKey is a valid log entry key,
969 ASSERT (Status
!= EFI_INVALID_PARAMETER
);
971 if (EFI_ERROR (Status
)) {
973 // The LogEntryKey is the last entry (equals to the total entry number).
978 ASSERT (GaugeData
!= NULL
);
980 *Handle
= (VOID
*) (UINTN
) GaugeData
->Handle
;
981 *Token
= GaugeData
->Token
;
982 *Module
= GaugeData
->Module
;
983 *StartTimeStamp
= GaugeData
->StartTimeStamp
;
984 *EndTimeStamp
= GaugeData
->EndTimeStamp
;
985 *Identifier
= GaugeData
->Identifier
;
991 Adds a record at the end of the performance measurement log
992 that records the start time of a performance measurement.
994 Adds a record to the end of the performance measurement log
995 that contains the Handle, Token, and Module.
996 The end time of the new record must be set to zero.
997 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
998 If TimeStamp is zero, the start time in the record is filled in with the value
999 read from the current time stamp.
1001 @param Handle Pointer to environment specific context used
1002 to identify the component being measured.
1003 @param Token Pointer to a Null-terminated ASCII string
1004 that identifies the component being measured.
1005 @param Module Pointer to a Null-terminated ASCII string
1006 that identifies the module being measured.
1007 @param TimeStamp 64-bit time stamp.
1009 @retval RETURN_SUCCESS The start of the measurement was recorded.
1010 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1015 StartPerformanceMeasurement (
1016 IN CONST VOID
*Handle
, OPTIONAL
1017 IN CONST CHAR8
*Token
, OPTIONAL
1018 IN CONST CHAR8
*Module
, OPTIONAL
1022 return StartPerformanceMeasurementEx (Handle
, Token
, Module
, TimeStamp
, 0);
1026 Searches the performance measurement log from the beginning of the log
1027 for the first matching record that contains a zero end time and fills in a valid end time.
1029 Searches the performance measurement log from the beginning of the log
1030 for the first record that matches Handle, Token, and Module and has an end time value of zero.
1031 If the record can not be found then return RETURN_NOT_FOUND.
1032 If the record is found and TimeStamp is not zero,
1033 then the end time in the record is filled in with the value specified by TimeStamp.
1034 If the record is found and TimeStamp is zero, then the end time in the matching record
1035 is filled in with the current time stamp value.
1037 @param Handle Pointer to environment specific context used
1038 to identify the component being measured.
1039 @param Token Pointer to a Null-terminated ASCII string
1040 that identifies the component being measured.
1041 @param Module Pointer to a Null-terminated ASCII string
1042 that identifies the module being measured.
1043 @param TimeStamp 64-bit time stamp.
1045 @retval RETURN_SUCCESS The end of the measurement was recorded.
1046 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1051 EndPerformanceMeasurement (
1052 IN CONST VOID
*Handle
, OPTIONAL
1053 IN CONST CHAR8
*Token
, OPTIONAL
1054 IN CONST CHAR8
*Module
, OPTIONAL
1058 return EndPerformanceMeasurementEx (Handle
, Token
, Module
, TimeStamp
, 0);
1062 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1063 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
1064 and then eliminate the Identifier.
1066 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1067 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1068 and the key for the second entry in the log is returned. If the performance log is empty,
1069 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1070 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1071 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1072 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1073 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1074 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1075 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
1076 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1077 If Handle is NULL, then ASSERT().
1078 If Token is NULL, then ASSERT().
1079 If Module is NULL, then ASSERT().
1080 If StartTimeStamp is NULL, then ASSERT().
1081 If EndTimeStamp is NULL, then ASSERT().
1083 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1084 0, then the first performance measurement log entry is retrieved.
1085 On exit, the key of the next performance log entry.
1086 @param Handle Pointer to environment specific context used to identify the component
1088 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1090 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1092 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1094 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1097 @return The key for the next performance log entry (in general case).
1102 GetPerformanceMeasurement (
1103 IN UINTN LogEntryKey
,
1104 OUT CONST VOID
**Handle
,
1105 OUT CONST CHAR8
**Token
,
1106 OUT CONST CHAR8
**Module
,
1107 OUT UINT64
*StartTimeStamp
,
1108 OUT UINT64
*EndTimeStamp
1112 return GetPerformanceMeasurementEx (LogEntryKey
, Handle
, Token
, Module
, StartTimeStamp
, EndTimeStamp
, &Identifier
);
1116 Returns TRUE if the performance measurement macros are enabled.
1118 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1119 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
1121 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1122 PcdPerformanceLibraryPropertyMask is set.
1123 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1124 PcdPerformanceLibraryPropertyMask is clear.
1129 PerformanceMeasurementEnabled (
1133 return mPerformanceMeasurementEnabled
;