]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
Optimize the log entry search algorithm to save boot performance.
[mirror_edk2.git] / MdeModulePkg / Library / SmmCorePerformanceLib / SmmCorePerformanceLib.c
... / ...
CommitLineData
1/** @file\r
2 Performance library instance used by SMM Core.\r
3\r
4 This library provides the performance measurement interfaces and initializes performance\r
5 logging for the SMM phase.\r
6 It initializes SMM phase performance logging by publishing the SMM Performance and PerformanceEx Protocol,\r
7 which is consumed by SmmPerformanceLib to logging performance data in SMM phase.\r
8\r
9 This library is mainly used by SMM Core to start performance logging to ensure that\r
10 SMM Performance and PerformanceEx Protocol are installed at the very beginning of SMM phase.\r
11\r
12Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
13This program and the accompanying materials\r
14are licensed and made available under the terms and conditions of the BSD License\r
15which accompanies this distribution. The full text of the license may be found at\r
16http://opensource.org/licenses/bsd-license.php\r
17\r
18THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
19WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
20\r
21**/\r
22\r
23\r
24#include "SmmCorePerformanceLibInternal.h"\r
25\r
26//\r
27// The data structure to hold global performance data.\r
28//\r
29GAUGE_DATA_HEADER *mGaugeData;\r
30\r
31//\r
32// The current maximum number of logging entries. If current number of \r
33// entries exceeds this value, it will re-allocate a larger array and\r
34// migration the old data to the larger array.\r
35//\r
36UINT32 mMaxGaugeRecords;\r
37\r
38//\r
39// The handle to install Performance Protocol instance.\r
40//\r
41EFI_HANDLE mHandle = NULL;\r
42\r
43BOOLEAN mPerformanceMeasurementEnabled;\r
44\r
45SPIN_LOCK mSmmPerfLock;\r
46\r
47EFI_SMRAM_DESCRIPTOR *mSmramRanges;\r
48UINTN mSmramRangeCount;\r
49\r
50//\r
51// Interfaces for SMM Performance Protocol.\r
52//\r
53PERFORMANCE_PROTOCOL mPerformanceInterface = {\r
54 StartGauge,\r
55 EndGauge,\r
56 GetGauge\r
57};\r
58\r
59//\r
60// Interfaces for SMM PerformanceEx Protocol.\r
61//\r
62PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {\r
63 StartGaugeEx,\r
64 EndGaugeEx,\r
65 GetGaugeEx\r
66};\r
67\r
68/**\r
69 Searches in the gauge array with keyword Handle, Token, Module and Identfier.\r
70\r
71 This internal function searches for the gauge entry in the gauge array.\r
72 If there is an entry that exactly matches the given keywords\r
73 and its end time stamp is zero, then the index of that gauge entry is returned;\r
74 otherwise, the the number of gauge entries in the array is returned.\r
75\r
76 @param Handle Pointer to environment specific context used\r
77 to identify the component being measured.\r
78 @param Token Pointer to a Null-terminated ASCII string\r
79 that identifies the component being measured.\r
80 @param Module Pointer to a Null-terminated ASCII string\r
81 that identifies the module being measured.\r
82 @param Identifier 32-bit identifier.\r
83\r
84 @retval The index of gauge entry in the array.\r
85\r
86**/\r
87UINT32\r
88SmmSearchForGaugeEntry (\r
89 IN CONST VOID *Handle, OPTIONAL\r
90 IN CONST CHAR8 *Token, OPTIONAL\r
91 IN CONST CHAR8 *Module, OPTIONAL\r
92 IN CONST UINT32 Identifier\r
93 )\r
94{\r
95 UINT32 Index;\r
96 UINT32 Index2;\r
97 UINT32 NumberOfEntries;\r
98 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
99\r
100 if (Token == NULL) {\r
101 Token = "";\r
102 }\r
103 if (Module == NULL) {\r
104 Module = "";\r
105 }\r
106\r
107 NumberOfEntries = mGaugeData->NumberOfEntries;\r
108 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
109\r
110 Index2 = 0;\r
111\r
112 for (Index = 0; Index < NumberOfEntries; Index++) {\r
113 Index2 = NumberOfEntries - 1 - Index;\r
114 if (GaugeEntryExArray[Index2].EndTimeStamp == 0 &&\r
115 (GaugeEntryExArray[Index2].Handle == (EFI_PHYSICAL_ADDRESS) (UINTN) Handle) &&\r
116 AsciiStrnCmp (GaugeEntryExArray[Index2].Token, Token, SMM_PERFORMANCE_STRING_LENGTH) == 0 &&\r
117 AsciiStrnCmp (GaugeEntryExArray[Index2].Module, Module, SMM_PERFORMANCE_STRING_LENGTH) == 0 &&\r
118 (GaugeEntryExArray[Index2].Identifier == Identifier)) {\r
119 Index = Index2;\r
120 break;\r
121 }\r
122 }\r
123\r
124 return Index;\r
125}\r
126\r
127/**\r
128 Adds a record at the end of the performance measurement log\r
129 that records the start time of a performance measurement.\r
130\r
131 Adds a record to the end of the performance measurement log\r
132 that contains the Handle, Token, Module and Identifier.\r
133 The end time of the new record must be set to zero.\r
134 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
135 If TimeStamp is zero, the start time in the record is filled in with the value\r
136 read from the current time stamp.\r
137\r
138 @param Handle Pointer to environment specific context used\r
139 to identify the component being measured.\r
140 @param Token Pointer to a Null-terminated ASCII string\r
141 that identifies the component being measured.\r
142 @param Module Pointer to a Null-terminated ASCII string\r
143 that identifies the module being measured.\r
144 @param TimeStamp 64-bit time stamp.\r
145 @param Identifier 32-bit identifier. If the value is 0, the created record\r
146 is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.\r
147\r
148 @retval EFI_SUCCESS The data was read correctly from the device.\r
149 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
150\r
151**/\r
152EFI_STATUS\r
153EFIAPI\r
154StartGaugeEx (\r
155 IN CONST VOID *Handle, OPTIONAL\r
156 IN CONST CHAR8 *Token, OPTIONAL\r
157 IN CONST CHAR8 *Module, OPTIONAL\r
158 IN UINT64 TimeStamp,\r
159 IN UINT32 Identifier\r
160 )\r
161{\r
162 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
163 UINTN GaugeDataSize;\r
164 GAUGE_DATA_HEADER *NewGaugeData;\r
165 UINTN OldGaugeDataSize;\r
166 GAUGE_DATA_HEADER *OldGaugeData;\r
167 UINT32 Index;\r
168\r
169 AcquireSpinLock (&mSmmPerfLock);\r
170\r
171 Index = mGaugeData->NumberOfEntries;\r
172 if (Index >= mMaxGaugeRecords) {\r
173 //\r
174 // Try to enlarge the scale of gauge array.\r
175 //\r
176 OldGaugeData = mGaugeData;\r
177 OldGaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords;\r
178\r
179 GaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2;\r
180\r
181 NewGaugeData = AllocateZeroPool (GaugeDataSize);\r
182 if (NewGaugeData == NULL) {\r
183 ReleaseSpinLock (&mSmmPerfLock);\r
184 return EFI_OUT_OF_RESOURCES;\r
185 }\r
186\r
187 mGaugeData = NewGaugeData;\r
188 mMaxGaugeRecords *= 2;\r
189\r
190 //\r
191 // Initialize new data array and migrate old data one.\r
192 //\r
193 mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize);\r
194\r
195 FreePool (OldGaugeData);\r
196 }\r
197\r
198 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
199 GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;\r
200\r
201 if (Token != NULL) {\r
202 AsciiStrnCpy (GaugeEntryExArray[Index].Token, Token, SMM_PERFORMANCE_STRING_LENGTH);\r
203 }\r
204 if (Module != NULL) {\r
205 AsciiStrnCpy (GaugeEntryExArray[Index].Module, Module, SMM_PERFORMANCE_STRING_LENGTH);\r
206 }\r
207\r
208 GaugeEntryExArray[Index].EndTimeStamp = 0;\r
209 GaugeEntryExArray[Index].Identifier = Identifier;\r
210\r
211 if (TimeStamp == 0) {\r
212 TimeStamp = GetPerformanceCounter ();\r
213 }\r
214 GaugeEntryExArray[Index].StartTimeStamp = TimeStamp;\r
215\r
216 mGaugeData->NumberOfEntries++;\r
217\r
218 ReleaseSpinLock (&mSmmPerfLock);\r
219\r
220 return EFI_SUCCESS;\r
221}\r
222\r
223/**\r
224 Searches the performance measurement log from the beginning of the log\r
225 for the first matching record that contains a zero end time and fills in a valid end time.\r
226\r
227 Searches the performance measurement log from the beginning of the log\r
228 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.\r
229 If the record can not be found then return EFI_NOT_FOUND.\r
230 If the record is found and TimeStamp is not zero,\r
231 then the end time in the record is filled in with the value specified by TimeStamp.\r
232 If the record is found and TimeStamp is zero, then the end time in the matching record\r
233 is filled in with the current time stamp value.\r
234\r
235 @param Handle Pointer to environment specific context used\r
236 to identify the component being measured.\r
237 @param Token Pointer to a Null-terminated ASCII string\r
238 that identifies the component being measured.\r
239 @param Module Pointer to a Null-terminated ASCII string\r
240 that identifies the module being measured.\r
241 @param TimeStamp 64-bit time stamp.\r
242 @param Identifier 32-bit identifier. If the value is 0, the found record\r
243 is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.\r
244\r
245 @retval EFI_SUCCESS The end of the measurement was recorded.\r
246 @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
247\r
248**/\r
249EFI_STATUS\r
250EFIAPI\r
251EndGaugeEx (\r
252 IN CONST VOID *Handle, OPTIONAL\r
253 IN CONST CHAR8 *Token, OPTIONAL\r
254 IN CONST CHAR8 *Module, OPTIONAL\r
255 IN UINT64 TimeStamp,\r
256 IN UINT32 Identifier\r
257 )\r
258{\r
259 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
260 UINT32 Index;\r
261\r
262 AcquireSpinLock (&mSmmPerfLock);\r
263\r
264 if (TimeStamp == 0) {\r
265 TimeStamp = GetPerformanceCounter ();\r
266 }\r
267\r
268 Index = SmmSearchForGaugeEntry (Handle, Token, Module, Identifier);\r
269 if (Index >= mGaugeData->NumberOfEntries) {\r
270 ReleaseSpinLock (&mSmmPerfLock);\r
271 return EFI_NOT_FOUND;\r
272 }\r
273 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
274 GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;\r
275\r
276 ReleaseSpinLock (&mSmmPerfLock);\r
277\r
278 return EFI_SUCCESS;\r
279}\r
280\r
281/**\r
282 Retrieves a previously logged performance measurement.\r
283 It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,\r
284 and then assign the Identifier with 0.\r
285\r
286 Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
287 If it stands for a valid entry, then EFI_SUCCESS is returned and\r
288 GaugeDataEntryEx stores the pointer to that entry.\r
289\r
290 @param LogEntryKey The key for the previous performance measurement log entry.\r
291 If 0, then the first performance measurement log entry is retrieved.\r
292 @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey\r
293 if the retrieval is successful.\r
294\r
295 @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.\r
296 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
297 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
298 @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.\r
299\r
300**/\r
301EFI_STATUS\r
302EFIAPI\r
303GetGaugeEx (\r
304 IN UINTN LogEntryKey,\r
305 OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx\r
306 )\r
307{\r
308 UINTN NumberOfEntries;\r
309 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
310\r
311 NumberOfEntries = (UINTN) (mGaugeData->NumberOfEntries);\r
312 if (LogEntryKey > NumberOfEntries) {\r
313 return EFI_INVALID_PARAMETER;\r
314 }\r
315 if (LogEntryKey == NumberOfEntries) {\r
316 return EFI_NOT_FOUND;\r
317 }\r
318\r
319 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
320\r
321 if (GaugeDataEntryEx == NULL) {\r
322 return EFI_INVALID_PARAMETER;\r
323 }\r
324 *GaugeDataEntryEx = &GaugeEntryExArray[LogEntryKey];\r
325\r
326 return EFI_SUCCESS;\r
327}\r
328\r
329/**\r
330 Adds a record at the end of the performance measurement log\r
331 that records the start time of a performance measurement.\r
332\r
333 Adds a record to the end of the performance measurement log\r
334 that contains the Handle, Token, and Module.\r
335 The end time of the new record must be set to zero.\r
336 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
337 If TimeStamp is zero, the start time in the record is filled in with the value\r
338 read from the current time stamp.\r
339\r
340 @param Handle Pointer to environment specific context used\r
341 to identify the component being measured.\r
342 @param Token Pointer to a Null-terminated ASCII string\r
343 that identifies the component being measured.\r
344 @param Module Pointer to a Null-terminated ASCII string\r
345 that identifies the module being measured.\r
346 @param TimeStamp 64-bit time stamp.\r
347\r
348 @retval EFI_SUCCESS The data was read correctly from the device.\r
349 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
350\r
351**/\r
352EFI_STATUS\r
353EFIAPI\r
354StartGauge (\r
355 IN CONST VOID *Handle, OPTIONAL\r
356 IN CONST CHAR8 *Token, OPTIONAL\r
357 IN CONST CHAR8 *Module, OPTIONAL\r
358 IN UINT64 TimeStamp\r
359 )\r
360{\r
361 return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
362}\r
363\r
364/**\r
365 Searches the performance measurement log from the beginning of the log\r
366 for the first matching record that contains a zero end time and fills in a valid end time.\r
367\r
368 Searches the performance measurement log from the beginning of the log\r
369 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
370 If the record can not be found then return EFI_NOT_FOUND.\r
371 If the record is found and TimeStamp is not zero,\r
372 then the end time in the record is filled in with the value specified by TimeStamp.\r
373 If the record is found and TimeStamp is zero, then the end time in the matching record\r
374 is filled in with the current time stamp value.\r
375\r
376 @param Handle Pointer to environment specific context used\r
377 to identify the component being measured.\r
378 @param Token Pointer to a Null-terminated ASCII string\r
379 that identifies the component being measured.\r
380 @param Module Pointer to a Null-terminated ASCII string\r
381 that identifies the module being measured.\r
382 @param TimeStamp 64-bit time stamp.\r
383\r
384 @retval EFI_SUCCESS The end of the measurement was recorded.\r
385 @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
386\r
387**/\r
388EFI_STATUS\r
389EFIAPI\r
390EndGauge (\r
391 IN CONST VOID *Handle, OPTIONAL\r
392 IN CONST CHAR8 *Token, OPTIONAL\r
393 IN CONST CHAR8 *Module, OPTIONAL\r
394 IN UINT64 TimeStamp\r
395 )\r
396{\r
397 return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
398}\r
399\r
400/**\r
401 Retrieves a previously logged performance measurement.\r
402 It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,\r
403 and then eliminate the Identifier.\r
404\r
405 Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
406 If it stands for a valid entry, then EFI_SUCCESS is returned and\r
407 GaugeDataEntry stores the pointer to that entry.\r
408\r
409 @param LogEntryKey The key for the previous performance measurement log entry.\r
410 If 0, then the first performance measurement log entry is retrieved.\r
411 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey\r
412 if the retrieval is successful.\r
413\r
414 @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.\r
415 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
416 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
417 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.\r
418\r
419**/\r
420EFI_STATUS\r
421EFIAPI\r
422GetGauge (\r
423 IN UINTN LogEntryKey,\r
424 OUT GAUGE_DATA_ENTRY **GaugeDataEntry\r
425 )\r
426{\r
427 EFI_STATUS Status;\r
428 GAUGE_DATA_ENTRY_EX *GaugeEntryEx;\r
429\r
430 GaugeEntryEx = NULL;\r
431\r
432 Status = GetGaugeEx (LogEntryKey, &GaugeEntryEx);\r
433 if (EFI_ERROR (Status)) {\r
434 return Status;\r
435 }\r
436\r
437 if (GaugeDataEntry == NULL) {\r
438 return EFI_INVALID_PARAMETER;\r
439 }\r
440\r
441 *GaugeDataEntry = (GAUGE_DATA_ENTRY *) GaugeEntryEx;\r
442\r
443 return EFI_SUCCESS;\r
444}\r
445\r
446/**\r
447 This function check if the address is in SMRAM.\r
448\r
449 @param Buffer the buffer address to be checked.\r
450 @param Length the buffer length to be checked.\r
451\r
452 @retval TRUE this address is in SMRAM.\r
453 @retval FALSE this address is NOT in SMRAM.\r
454**/\r
455BOOLEAN\r
456IsAddressInSmram (\r
457 IN EFI_PHYSICAL_ADDRESS Buffer,\r
458 IN UINT64 Length\r
459 )\r
460{\r
461 UINTN Index;\r
462\r
463 for (Index = 0; Index < mSmramRangeCount; Index ++) {\r
464 if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) ||\r
465 ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) {\r
466 return TRUE;\r
467 }\r
468 }\r
469\r
470 return FALSE;\r
471}\r
472\r
473/**\r
474 Communication service SMI Handler entry.\r
475\r
476 This SMI handler provides services for the performance wrapper driver.\r
477\r
478 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
479 @param[in] RegisterContext Points to an optional handler context which was specified when the\r
480 handler was registered.\r
481 @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
482 be conveyed from a non-SMM environment into an SMM environment.\r
483 @param[in, out] CommBufferSize The size of the CommBuffer.\r
484\r
485 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers \r
486 should still be called.\r
487 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should \r
488 still be called.\r
489 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still \r
490 be called.\r
491 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
492**/\r
493EFI_STATUS\r
494EFIAPI\r
495SmmPerformanceHandlerEx (\r
496 IN EFI_HANDLE DispatchHandle,\r
497 IN CONST VOID *RegisterContext,\r
498 IN OUT VOID *CommBuffer,\r
499 IN OUT UINTN *CommBufferSize\r
500 )\r
501{\r
502 EFI_STATUS Status;\r
503 SMM_PERF_COMMUNICATE_EX *SmmPerfCommData;\r
504 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
505 UINTN DataSize;\r
506\r
507 GaugeEntryExArray = NULL;\r
508\r
509 ASSERT (CommBuffer != NULL);\r
510\r
511 SmmPerfCommData = (SMM_PERF_COMMUNICATE_EX *)CommBuffer;\r
512\r
513 switch (SmmPerfCommData->Function) {\r
514 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER :\r
515 SmmPerfCommData->NumberOfEntries = mGaugeData->NumberOfEntries;\r
516 Status = EFI_SUCCESS;\r
517 break;\r
518\r
519 case SMM_PERF_FUNCTION_GET_GAUGE_DATA :\r
520 if ( SmmPerfCommData->GaugeDataEx == NULL || SmmPerfCommData->NumberOfEntries == 0 ||\r
521 (SmmPerfCommData->LogEntryKey + SmmPerfCommData->NumberOfEntries) > mGaugeData->NumberOfEntries) {\r
522 Status = EFI_INVALID_PARAMETER;\r
523 break;\r
524 }\r
525\r
526 //\r
527 // Sanity check\r
528 //\r
529 DataSize = SmmPerfCommData->NumberOfEntries * sizeof(GAUGE_DATA_ENTRY_EX);\r
530 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)SmmPerfCommData->GaugeDataEx, DataSize)) {\r
531 DEBUG ((EFI_D_ERROR, "Smm Performance Data buffer is in SMRAM!\n"));\r
532 Status = EFI_ACCESS_DENIED;\r
533 break ;\r
534 }\r
535\r
536 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
537 CopyMem(\r
538 (UINT8 *) (SmmPerfCommData->GaugeDataEx),\r
539 (UINT8 *) &GaugeEntryExArray[SmmPerfCommData->LogEntryKey],\r
540 DataSize\r
541 );\r
542 Status = EFI_SUCCESS;\r
543 break;\r
544\r
545 default:\r
546 ASSERT (FALSE);\r
547 Status = EFI_UNSUPPORTED;\r
548 }\r
549\r
550 SmmPerfCommData->ReturnStatus = Status;\r
551 return EFI_SUCCESS;\r
552}\r
553\r
554/**\r
555 Communication service SMI Handler entry.\r
556\r
557 This SMI handler provides services for the performance wrapper driver.\r
558\r
559 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
560 @param[in] RegisterContext Points to an optional handler context which was specified when the\r
561 handler was registered.\r
562 @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
563 be conveyed from a non-SMM environment into an SMM environment.\r
564 @param[in, out] CommBufferSize The size of the CommBuffer.\r
565\r
566 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers \r
567 should still be called.\r
568 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should \r
569 still be called.\r
570 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still \r
571 be called.\r
572 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
573**/\r
574EFI_STATUS\r
575EFIAPI\r
576SmmPerformanceHandler (\r
577 IN EFI_HANDLE DispatchHandle,\r
578 IN CONST VOID *RegisterContext,\r
579 IN OUT VOID *CommBuffer,\r
580 IN OUT UINTN *CommBufferSize\r
581 )\r
582{\r
583 EFI_STATUS Status;\r
584 SMM_PERF_COMMUNICATE *SmmPerfCommData;\r
585 GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;\r
586 UINTN DataSize;\r
587 UINTN Index;\r
588 UINTN LogEntryKey;\r
589\r
590 GaugeEntryExArray = NULL;\r
591\r
592 ASSERT (CommBuffer != NULL);\r
593\r
594 SmmPerfCommData = (SMM_PERF_COMMUNICATE *)CommBuffer;\r
595\r
596 switch (SmmPerfCommData->Function) {\r
597 case SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER :\r
598 SmmPerfCommData->NumberOfEntries = mGaugeData->NumberOfEntries;\r
599 Status = EFI_SUCCESS;\r
600 break;\r
601\r
602 case SMM_PERF_FUNCTION_GET_GAUGE_DATA :\r
603 if ( SmmPerfCommData->GaugeData == NULL || SmmPerfCommData->NumberOfEntries == 0 ||\r
604 (SmmPerfCommData->LogEntryKey + SmmPerfCommData->NumberOfEntries) > mGaugeData->NumberOfEntries) {\r
605 Status = EFI_INVALID_PARAMETER;\r
606 break;\r
607 }\r
608\r
609 //\r
610 // Sanity check\r
611 //\r
612 DataSize = SmmPerfCommData->NumberOfEntries * sizeof(GAUGE_DATA_ENTRY);\r
613 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)SmmPerfCommData->GaugeData, DataSize)) {\r
614 DEBUG ((EFI_D_ERROR, "Smm Performance Data buffer is in SMRAM!\n"));\r
615 Status = EFI_ACCESS_DENIED;\r
616 break ;\r
617 }\r
618\r
619 GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);\r
620\r
621 LogEntryKey = SmmPerfCommData->LogEntryKey;\r
622 for (Index = 0; Index < SmmPerfCommData->NumberOfEntries; Index++) {\r
623 CopyMem(\r
624 (UINT8 *) &(SmmPerfCommData->GaugeData[Index]),\r
625 (UINT8 *) &GaugeEntryExArray[LogEntryKey++],\r
626 sizeof (GAUGE_DATA_ENTRY)\r
627 );\r
628 }\r
629 Status = EFI_SUCCESS;\r
630 break;\r
631\r
632 default:\r
633 ASSERT (FALSE);\r
634 Status = EFI_UNSUPPORTED;\r
635 }\r
636\r
637 SmmPerfCommData->ReturnStatus = Status;\r
638 return EFI_SUCCESS;\r
639}\r
640\r
641/**\r
642 SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized \r
643 this function is callbacked to initialize the Smm Performance Lib \r
644\r
645 @param Event The event of notify protocol.\r
646 @param Context Notify event context.\r
647\r
648**/\r
649VOID\r
650EFIAPI\r
651InitializeSmmCorePerformanceLib (\r
652 IN EFI_EVENT Event,\r
653 IN VOID *Context\r
654 )\r
655{\r
656 EFI_STATUS Status;\r
657 EFI_HANDLE Handle;\r
658 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
659 UINTN Size;\r
660\r
661\r
662 //\r
663 // Initialize spin lock\r
664 //\r
665 InitializeSpinLock (&mSmmPerfLock);\r
666\r
667 mMaxGaugeRecords = INIT_SMM_GAUGE_DATA_ENTRIES;\r
668\r
669 mGaugeData = AllocateZeroPool (sizeof (GAUGE_DATA_HEADER) + (sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords));\r
670 ASSERT (mGaugeData != NULL);\r
671 \r
672 //\r
673 // Get SMRAM information\r
674 //\r
675 Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);\r
676 ASSERT_EFI_ERROR (Status);\r
677\r
678 Size = 0;\r
679 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);\r
680 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
681\r
682 Status = gSmst->SmmAllocatePool (\r
683 EfiRuntimeServicesData,\r
684 Size,\r
685 (VOID **)&mSmramRanges\r
686 );\r
687 ASSERT_EFI_ERROR (Status);\r
688\r
689 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);\r
690 ASSERT_EFI_ERROR (Status);\r
691\r
692 mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
693\r
694 //\r
695 // Install the protocol interfaces.\r
696 //\r
697 Status = gSmst->SmmInstallProtocolInterface (\r
698 &mHandle,\r
699 &gSmmPerformanceProtocolGuid,\r
700 EFI_NATIVE_INTERFACE,\r
701 &mPerformanceInterface\r
702 );\r
703 ASSERT_EFI_ERROR (Status);\r
704\r
705 Status = gSmst->SmmInstallProtocolInterface (\r
706 &mHandle,\r
707 &gSmmPerformanceExProtocolGuid,\r
708 EFI_NATIVE_INTERFACE,\r
709 &mPerformanceExInterface\r
710 );\r
711 ASSERT_EFI_ERROR (Status);\r
712\r
713 ///\r
714 /// Register SMM Performance SMI handler\r
715 ///\r
716 Handle = NULL;\r
717 Status = gSmst->SmiHandlerRegister (SmmPerformanceHandler, &gSmmPerformanceProtocolGuid, &Handle);\r
718 ASSERT_EFI_ERROR (Status);\r
719 Status = gSmst->SmiHandlerRegister (SmmPerformanceHandlerEx, &gSmmPerformanceExProtocolGuid, &Handle);\r
720 ASSERT_EFI_ERROR (Status);\r
721}\r
722\r
723/**\r
724 The constructor function initializes the Performance Measurement Enable flag and \r
725 registers SmmBase2 protocol notify callback.\r
726 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.\r
727\r
728 @param ImageHandle The firmware allocated handle for the EFI image.\r
729 @param SystemTable A pointer to the EFI System Table.\r
730\r
731 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
732\r
733**/\r
734EFI_STATUS\r
735EFIAPI\r
736SmmCorePerformanceLibConstructor (\r
737 IN EFI_HANDLE ImageHandle,\r
738 IN EFI_SYSTEM_TABLE *SystemTable\r
739 )\r
740{\r
741 EFI_STATUS Status;\r
742 EFI_EVENT Event;\r
743 VOID *Registration;\r
744\r
745 mPerformanceMeasurementEnabled = (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);\r
746 if (!mPerformanceMeasurementEnabled) {\r
747 //\r
748 // Do not initialize performance infrastructure if not required.\r
749 //\r
750 return EFI_SUCCESS;\r
751 }\r
752\r
753 //\r
754 // Create the events to do the library init.\r
755 //\r
756 Status = gBS->CreateEvent (\r
757 EVT_NOTIFY_SIGNAL,\r
758 TPL_CALLBACK,\r
759 InitializeSmmCorePerformanceLib,\r
760 NULL,\r
761 &Event\r
762 );\r
763 ASSERT_EFI_ERROR (Status);\r
764\r
765 //\r
766 // Register for protocol notifications on this event\r
767 //\r
768 Status = gBS->RegisterProtocolNotify (\r
769 &gEfiSmmBase2ProtocolGuid,\r
770 Event,\r
771 &Registration\r
772 );\r
773\r
774 ASSERT_EFI_ERROR (Status);\r
775\r
776 return EFI_SUCCESS;\r
777}\r
778\r
779/**\r
780 Adds a record at the end of the performance measurement log\r
781 that records the start time of a performance measurement.\r
782\r
783 Adds a record to the end of the performance measurement log\r
784 that contains the Handle, Token, Module and Identifier.\r
785 The end time of the new record must be set to zero.\r
786 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
787 If TimeStamp is zero, the start time in the record is filled in with the value\r
788 read from the current time stamp.\r
789\r
790 @param Handle Pointer to environment specific context used\r
791 to identify the component being measured.\r
792 @param Token Pointer to a Null-terminated ASCII string\r
793 that identifies the component being measured.\r
794 @param Module Pointer to a Null-terminated ASCII string\r
795 that identifies the module being measured.\r
796 @param TimeStamp 64-bit time stamp.\r
797 @param Identifier 32-bit identifier. If the value is 0, the created record\r
798 is same as the one created by StartPerformanceMeasurement.\r
799\r
800 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
801 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
802\r
803**/\r
804RETURN_STATUS\r
805EFIAPI\r
806StartPerformanceMeasurementEx (\r
807 IN CONST VOID *Handle, OPTIONAL\r
808 IN CONST CHAR8 *Token, OPTIONAL\r
809 IN CONST CHAR8 *Module, OPTIONAL\r
810 IN UINT64 TimeStamp,\r
811 IN UINT32 Identifier\r
812 )\r
813{\r
814 return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
815}\r
816\r
817/**\r
818 Searches the performance measurement log from the beginning of the log\r
819 for the first matching record that contains a zero end time and fills in a valid end time.\r
820\r
821 Searches the performance measurement log from the beginning of the log\r
822 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.\r
823 If the record can not be found then return RETURN_NOT_FOUND.\r
824 If the record is found and TimeStamp is not zero,\r
825 then the end time in the record is filled in with the value specified by TimeStamp.\r
826 If the record is found and TimeStamp is zero, then the end time in the matching record\r
827 is filled in with the current time stamp value.\r
828\r
829 @param Handle Pointer to environment specific context used\r
830 to identify the component being measured.\r
831 @param Token Pointer to a Null-terminated ASCII string\r
832 that identifies the component being measured.\r
833 @param Module Pointer to a Null-terminated ASCII string\r
834 that identifies the module being measured.\r
835 @param TimeStamp 64-bit time stamp.\r
836 @param Identifier 32-bit identifier. If the value is 0, the found record\r
837 is same as the one found by EndPerformanceMeasurement.\r
838\r
839 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
840 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
841\r
842**/\r
843RETURN_STATUS\r
844EFIAPI\r
845EndPerformanceMeasurementEx (\r
846 IN CONST VOID *Handle, OPTIONAL\r
847 IN CONST CHAR8 *Token, OPTIONAL\r
848 IN CONST CHAR8 *Module, OPTIONAL\r
849 IN UINT64 TimeStamp,\r
850 IN UINT32 Identifier\r
851 )\r
852{\r
853 return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
854}\r
855\r
856/**\r
857 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
858 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,\r
859 and then assign the Identifier with 0.\r
860\r
861 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
862 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
863 and the key for the second entry in the log is returned. If the performance log is empty,\r
864 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
865 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
866 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
867 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
868 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
869 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
870 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.\r
871 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
872 If Handle is NULL, then ASSERT().\r
873 If Token is NULL, then ASSERT().\r
874 If Module is NULL, then ASSERT().\r
875 If StartTimeStamp is NULL, then ASSERT().\r
876 If EndTimeStamp is NULL, then ASSERT().\r
877 If Identifier is NULL, then ASSERT().\r
878\r
879 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
880 0, then the first performance measurement log entry is retrieved.\r
881 On exit, the key of the next performance log entry.\r
882 @param Handle Pointer to environment specific context used to identify the component\r
883 being measured.\r
884 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
885 being measured.\r
886 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
887 being measured.\r
888 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
889 was started.\r
890 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
891 was ended.\r
892 @param Identifier Pointer to the 32-bit identifier that was recorded.\r
893\r
894 @return The key for the next performance log entry (in general case).\r
895\r
896**/\r
897UINTN\r
898EFIAPI\r
899GetPerformanceMeasurementEx (\r
900 IN UINTN LogEntryKey, \r
901 OUT CONST VOID **Handle,\r
902 OUT CONST CHAR8 **Token,\r
903 OUT CONST CHAR8 **Module,\r
904 OUT UINT64 *StartTimeStamp,\r
905 OUT UINT64 *EndTimeStamp,\r
906 OUT UINT32 *Identifier\r
907 )\r
908{\r
909 EFI_STATUS Status;\r
910 GAUGE_DATA_ENTRY_EX *GaugeData;\r
911\r
912 GaugeData = NULL;\r
913 \r
914 ASSERT (Handle != NULL);\r
915 ASSERT (Token != NULL);\r
916 ASSERT (Module != NULL);\r
917 ASSERT (StartTimeStamp != NULL);\r
918 ASSERT (EndTimeStamp != NULL);\r
919 ASSERT (Identifier != NULL);\r
920\r
921 Status = GetGaugeEx (LogEntryKey++, &GaugeData);\r
922\r
923 //\r
924 // Make sure that LogEntryKey is a valid log entry key,\r
925 //\r
926 ASSERT (Status != EFI_INVALID_PARAMETER);\r
927\r
928 if (EFI_ERROR (Status)) {\r
929 //\r
930 // The LogEntryKey is the last entry (equals to the total entry number).\r
931 //\r
932 return 0;\r
933 }\r
934\r
935 ASSERT (GaugeData != NULL);\r
936\r
937 *Handle = (VOID *) (UINTN) GaugeData->Handle;\r
938 *Token = GaugeData->Token;\r
939 *Module = GaugeData->Module;\r
940 *StartTimeStamp = GaugeData->StartTimeStamp;\r
941 *EndTimeStamp = GaugeData->EndTimeStamp;\r
942 *Identifier = GaugeData->Identifier;\r
943\r
944 return LogEntryKey;\r
945}\r
946\r
947/**\r
948 Adds a record at the end of the performance measurement log\r
949 that records the start time of a performance measurement.\r
950\r
951 Adds a record to the end of the performance measurement log\r
952 that contains the Handle, Token, and Module.\r
953 The end time of the new record must be set to zero.\r
954 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
955 If TimeStamp is zero, the start time in the record is filled in with the value\r
956 read from the current time stamp.\r
957\r
958 @param Handle Pointer to environment specific context used\r
959 to identify the component being measured.\r
960 @param Token Pointer to a Null-terminated ASCII string\r
961 that identifies the component being measured.\r
962 @param Module Pointer to a Null-terminated ASCII string\r
963 that identifies the module being measured.\r
964 @param TimeStamp 64-bit time stamp.\r
965\r
966 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
967 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
968\r
969**/\r
970RETURN_STATUS\r
971EFIAPI\r
972StartPerformanceMeasurement (\r
973 IN CONST VOID *Handle, OPTIONAL\r
974 IN CONST CHAR8 *Token, OPTIONAL\r
975 IN CONST CHAR8 *Module, OPTIONAL\r
976 IN UINT64 TimeStamp\r
977 )\r
978{\r
979 return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
980}\r
981\r
982/**\r
983 Searches the performance measurement log from the beginning of the log\r
984 for the first matching record that contains a zero end time and fills in a valid end time.\r
985\r
986 Searches the performance measurement log from the beginning of the log\r
987 for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
988 If the record can not be found then return RETURN_NOT_FOUND.\r
989 If the record is found and TimeStamp is not zero,\r
990 then the end time in the record is filled in with the value specified by TimeStamp.\r
991 If the record is found and TimeStamp is zero, then the end time in the matching record\r
992 is filled in with the current time stamp value.\r
993\r
994 @param Handle Pointer to environment specific context used\r
995 to identify the component being measured.\r
996 @param Token Pointer to a Null-terminated ASCII string\r
997 that identifies the component being measured.\r
998 @param Module Pointer to a Null-terminated ASCII string\r
999 that identifies the module being measured.\r
1000 @param TimeStamp 64-bit time stamp.\r
1001\r
1002 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
1003 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
1004\r
1005**/\r
1006RETURN_STATUS\r
1007EFIAPI\r
1008EndPerformanceMeasurement (\r
1009 IN CONST VOID *Handle, OPTIONAL\r
1010 IN CONST CHAR8 *Token, OPTIONAL\r
1011 IN CONST CHAR8 *Module, OPTIONAL\r
1012 IN UINT64 TimeStamp\r
1013 )\r
1014{\r
1015 return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
1016}\r
1017\r
1018/**\r
1019 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
1020 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,\r
1021 and then eliminate the Identifier.\r
1022\r
1023 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
1024 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
1025 and the key for the second entry in the log is returned. If the performance log is empty,\r
1026 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
1027 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
1028 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
1029 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
1030 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
1031 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
1032 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.\r
1033 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
1034 If Handle is NULL, then ASSERT().\r
1035 If Token is NULL, then ASSERT().\r
1036 If Module is NULL, then ASSERT().\r
1037 If StartTimeStamp is NULL, then ASSERT().\r
1038 If EndTimeStamp is NULL, then ASSERT().\r
1039\r
1040 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
1041 0, then the first performance measurement log entry is retrieved.\r
1042 On exit, the key of the next performance log entry.\r
1043 @param Handle Pointer to environment specific context used to identify the component\r
1044 being measured.\r
1045 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
1046 being measured.\r
1047 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
1048 being measured.\r
1049 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1050 was started.\r
1051 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
1052 was ended.\r
1053\r
1054 @return The key for the next performance log entry (in general case).\r
1055\r
1056**/\r
1057UINTN\r
1058EFIAPI\r
1059GetPerformanceMeasurement (\r
1060 IN UINTN LogEntryKey,\r
1061 OUT CONST VOID **Handle,\r
1062 OUT CONST CHAR8 **Token,\r
1063 OUT CONST CHAR8 **Module,\r
1064 OUT UINT64 *StartTimeStamp,\r
1065 OUT UINT64 *EndTimeStamp\r
1066 )\r
1067{\r
1068 UINT32 Identifier;\r
1069 return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);\r
1070}\r
1071\r
1072/**\r
1073 Returns TRUE if the performance measurement macros are enabled.\r
1074\r
1075 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1076 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.\r
1077\r
1078 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1079 PcdPerformanceLibraryPropertyMask is set.\r
1080 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
1081 PcdPerformanceLibraryPropertyMask is clear.\r
1082\r
1083**/\r
1084BOOLEAN\r
1085EFIAPI\r
1086PerformanceMeasurementEnabled (\r
1087 VOID\r
1088 )\r
1089{\r
1090 return mPerformanceMeasurementEnabled;\r
1091}\r