]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Library / SmmPerformanceLib / SmmPerformanceLib.c
CommitLineData
d042c6e8 1/** @file\r
2 Performance Library used in SMM phase.\r
3\r
4 This library instance provides infrastructure for SMM drivers to log performance\r
f0da4d7d
SZ
5 data. It consumes SMM PerformanceEx or Performance Protocol published by SmmCorePerformanceLib\r
6 to log performance data. If both SMM PerformanceEx and Performance Protocol are not available, it does not log any\r
d042c6e8 7 performance information.\r
8\r
d1102dba 9 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 10SPDX-License-Identifier: BSD-2-Clause-Patent\r
d042c6e8 11\r
12**/\r
13\r
14\r
137fb13d 15#include <Guid/PerformanceMeasurement.h>\r
d042c6e8 16\r
17#include <Library/PerformanceLib.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/SmmServicesTableLib.h>\r
20#include <Library/PcdLib.h>\r
21#include <Library/BaseMemoryLib.h>\r
22\r
d042c6e8 23//\r
f0da4d7d 24// The cached SMM Performance Protocol and SMM PerformanceEx Protocol interface.\r
137fb13d
BD
25EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL *mPerformanceMeasurement = NULL;\r
26BOOLEAN mPerformanceMeasurementEnabled;\r
d042c6e8 27\r
28/**\r
f0da4d7d 29 The constructor function initializes the Performance Measurement Enable flag\r
d042c6e8 30\r
31 @param ImageHandle The firmware allocated handle for the EFI image.\r
32 @param SystemTable A pointer to the EFI System Table.\r
33\r
34 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
35\r
36**/\r
37EFI_STATUS\r
38EFIAPI\r
39SmmPerformanceLibConstructor (\r
40 IN EFI_HANDLE ImageHandle,\r
41 IN EFI_SYSTEM_TABLE *SystemTable\r
42 )\r
43{\r
d1102dba 44\r
d042c6e8 45 mPerformanceMeasurementEnabled = (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);\r
46\r
47 return EFI_SUCCESS;\r
48}\r
49\r
50/**\r
f0da4d7d 51 The function caches the pointers to SMM PerformanceEx protocol and Performance Protocol.\r
d042c6e8 52\r
f0da4d7d 53 The function locates SMM PerformanceEx protocol and Performance Protocol from protocol database.\r
d042c6e8 54\r
f0da4d7d
SZ
55 @retval EFI_SUCCESS SMM PerformanceEx protocol or Performance Protocol is successfully located.\r
56 @retval EFI_NOT_FOUND Both SMM PerformanceEx protocol and Performance Protocol are not located to log performance.\r
d042c6e8 57\r
58**/\r
59EFI_STATUS\r
137fb13d 60GetPerformanceMeasurementProtocol (\r
d042c6e8 61 VOID\r
62 )\r
63{\r
f0da4d7d 64 EFI_STATUS Status;\r
137fb13d 65 EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL *PerformanceMeasurement;\r
d042c6e8 66\r
137fb13d 67 if (mPerformanceMeasurement != NULL) {\r
f0da4d7d
SZ
68 return EFI_SUCCESS;\r
69 }\r
70\r
137fb13d 71 Status = gSmst->SmmLocateProtocol (&gEdkiiSmmPerformanceMeasurementProtocolGuid, NULL, (VOID **) &PerformanceMeasurement);\r
f0da4d7d 72 if (!EFI_ERROR (Status)) {\r
137fb13d 73 ASSERT (PerformanceMeasurement != NULL);\r
f0da4d7d 74 //\r
137fb13d 75 // Cache PerformanceMeasurement Protocol.\r
f0da4d7d 76 //\r
137fb13d 77 mPerformanceMeasurement = PerformanceMeasurement;\r
d042c6e8 78 return EFI_SUCCESS;\r
79 }\r
f0da4d7d 80 return EFI_NOT_FOUND;\r
d042c6e8 81}\r
82\r
83/**\r
84 Creates a record for the beginning of a performance measurement.\r
85\r
f0da4d7d 86 Creates a record that contains the Handle, Token, Module and Identifier.\r
d042c6e8 87 If TimeStamp is not zero, then TimeStamp is added to the record as the start time.\r
88 If TimeStamp is zero, then this function reads the current time stamp\r
89 and adds that time stamp value to the record as the start time.\r
90\r
91 @param Handle Pointer to environment specific context used\r
92 to identify the component being measured.\r
93 @param Token Pointer to a Null-terminated ASCII string\r
94 that identifies the component being measured.\r
95 @param Module Pointer to a Null-terminated ASCII string\r
96 that identifies the module being measured.\r
97 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
98 @param Identifier 32-bit identifier. If the value is 0, the created record\r
99 is same as the one created by StartPerformanceMeasurement.\r
d042c6e8 100\r
101 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
102 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
103\r
104**/\r
105RETURN_STATUS\r
106EFIAPI\r
f0da4d7d 107StartPerformanceMeasurementEx (\r
d042c6e8 108 IN CONST VOID *Handle, OPTIONAL\r
109 IN CONST CHAR8 *Token, OPTIONAL\r
110 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
111 IN UINT64 TimeStamp,\r
112 IN UINT32 Identifier\r
d042c6e8 113 )\r
114{\r
137fb13d
BD
115 EFI_STATUS Status;\r
116 CONST CHAR8* String;\r
d042c6e8 117\r
137fb13d 118 Status = GetPerformanceMeasurementProtocol ();\r
d042c6e8 119 if (EFI_ERROR (Status)) {\r
137fb13d 120 return RETURN_NOT_FOUND;\r
d042c6e8 121 }\r
122\r
137fb13d
BD
123 if (Token != NULL) {\r
124 String = Token;\r
125 } else if (Module != NULL) {\r
126 String = Module;\r
127 } else {\r
128 String = NULL;\r
129 }\r
130\r
131 if (mPerformanceMeasurement != NULL) {\r
132 Status = mPerformanceMeasurement->CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);\r
f0da4d7d
SZ
133 } else {\r
134 ASSERT (FALSE);\r
135 }\r
d042c6e8 136\r
137 return (RETURN_STATUS) Status;\r
138}\r
139\r
140/**\r
141 Fills in the end time of a performance measurement.\r
142\r
7a9395cd 143 Looks up the record that matches Handle, Token and Module.\r
d042c6e8 144 If the record can not be found then return RETURN_NOT_FOUND.\r
145 If the record is found and TimeStamp is not zero,\r
146 then TimeStamp is added to the record as the end time.\r
147 If the record is found and TimeStamp is zero, then this function reads\r
148 the current time stamp and adds that time stamp value to the record as the end time.\r
d042c6e8 149\r
150 @param Handle Pointer to environment specific context used\r
151 to identify the component being measured.\r
152 @param Token Pointer to a Null-terminated ASCII string\r
153 that identifies the component being measured.\r
154 @param Module Pointer to a Null-terminated ASCII string\r
155 that identifies the module being measured.\r
156 @param TimeStamp 64-bit time stamp.\r
f0da4d7d
SZ
157 @param Identifier 32-bit identifier. If the value is 0, the found record\r
158 is same as the one found by EndPerformanceMeasurement.\r
d042c6e8 159\r
160 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
161 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
162\r
163**/\r
164RETURN_STATUS\r
165EFIAPI\r
f0da4d7d 166EndPerformanceMeasurementEx (\r
d042c6e8 167 IN CONST VOID *Handle, OPTIONAL\r
168 IN CONST CHAR8 *Token, OPTIONAL\r
169 IN CONST CHAR8 *Module, OPTIONAL\r
f0da4d7d
SZ
170 IN UINT64 TimeStamp,\r
171 IN UINT32 Identifier\r
d042c6e8 172 )\r
173{\r
137fb13d
BD
174 EFI_STATUS Status;\r
175 CONST CHAR8* String;\r
d042c6e8 176\r
137fb13d 177 Status = GetPerformanceMeasurementProtocol ();\r
d042c6e8 178 if (EFI_ERROR (Status)) {\r
179 return RETURN_NOT_FOUND;\r
180 }\r
181\r
137fb13d
BD
182 if (Token != NULL) {\r
183 String = Token;\r
184 } else if (Module != NULL) {\r
185 String = Module;\r
186 } else {\r
187 String = NULL;\r
188 }\r
189\r
190 if (mPerformanceMeasurement != NULL) {\r
191 Status = mPerformanceMeasurement->CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);\r
f0da4d7d
SZ
192 } else {\r
193 ASSERT (FALSE);\r
194 }\r
d042c6e8 195\r
196 return (RETURN_STATUS) Status;\r
197}\r
198\r
199/**\r
200 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
f0da4d7d
SZ
201 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,\r
202 and then assign the Identifier with 0.\r
d042c6e8 203\r
204 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
205 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
206 and the key for the second entry in the log is returned. If the performance log is empty,\r
207 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
208 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
209 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
210 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
211 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
212 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
f0da4d7d 213 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.\r
d042c6e8 214 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
215 If Handle is NULL, then ASSERT().\r
216 If Token is NULL, then ASSERT().\r
217 If Module is NULL, then ASSERT().\r
218 If StartTimeStamp is NULL, then ASSERT().\r
219 If EndTimeStamp is NULL, then ASSERT().\r
f0da4d7d 220 If Identifier is NULL, then ASSERT().\r
d042c6e8 221\r
222 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
223 0, then the first performance measurement log entry is retrieved.\r
224 On exit, the key of the next performance log entry.\r
225 @param Handle Pointer to environment specific context used to identify the component\r
226 being measured.\r
227 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
228 being measured.\r
229 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
230 being measured.\r
231 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
232 was started.\r
233 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
234 was ended.\r
f0da4d7d 235 @param Identifier Pointer to the 32-bit identifier that was recorded.\r
d042c6e8 236\r
237 @return The key for the next performance log entry (in general case).\r
238\r
239**/\r
240UINTN\r
241EFIAPI\r
f0da4d7d 242GetPerformanceMeasurementEx (\r
d1102dba 243 IN UINTN LogEntryKey,\r
d042c6e8 244 OUT CONST VOID **Handle,\r
245 OUT CONST CHAR8 **Token,\r
246 OUT CONST CHAR8 **Module,\r
247 OUT UINT64 *StartTimeStamp,\r
f0da4d7d
SZ
248 OUT UINT64 *EndTimeStamp,\r
249 OUT UINT32 *Identifier\r
d042c6e8 250 )\r
251{\r
137fb13d 252 return 0;\r
d042c6e8 253}\r
254\r
f0da4d7d
SZ
255/**\r
256 Creates a record for the beginning of a performance measurement.\r
257\r
258 Creates a record that contains the Handle, Token, and Module.\r
259 If TimeStamp is not zero, then TimeStamp is added to the record as the start time.\r
260 If TimeStamp is zero, then this function reads the current time stamp\r
261 and adds that time stamp value to the record as the start time.\r
262\r
263 @param Handle Pointer to environment specific context used\r
264 to identify the component being measured.\r
265 @param Token Pointer to a Null-terminated ASCII string\r
266 that identifies the component being measured.\r
267 @param Module Pointer to a Null-terminated ASCII string\r
268 that identifies the module being measured.\r
269 @param TimeStamp 64-bit time stamp.\r
270\r
271 @retval RETURN_SUCCESS The start of the measurement was recorded.\r
272 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
273\r
274**/\r
275RETURN_STATUS\r
276EFIAPI\r
277StartPerformanceMeasurement (\r
278 IN CONST VOID *Handle, OPTIONAL\r
279 IN CONST CHAR8 *Token, OPTIONAL\r
280 IN CONST CHAR8 *Module, OPTIONAL\r
281 IN UINT64 TimeStamp\r
282 )\r
283{\r
284 return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
285}\r
286\r
287/**\r
288 Fills in the end time of a performance measurement.\r
289\r
290 Looks up the record that matches Handle, Token, and Module.\r
291 If the record can not be found then return RETURN_NOT_FOUND.\r
292 If the record is found and TimeStamp is not zero,\r
293 then TimeStamp is added to the record as the end time.\r
294 If the record is found and TimeStamp is zero, then this function reads\r
295 the current time stamp and adds that time stamp value to the record as the end time.\r
296\r
297 @param Handle Pointer to environment specific context used\r
298 to identify the component being measured.\r
299 @param Token Pointer to a Null-terminated ASCII string\r
300 that identifies the component being measured.\r
301 @param Module Pointer to a Null-terminated ASCII string\r
302 that identifies the module being measured.\r
303 @param TimeStamp 64-bit time stamp.\r
304\r
305 @retval RETURN_SUCCESS The end of the measurement was recorded.\r
306 @retval RETURN_NOT_FOUND The specified measurement record could not be found.\r
307\r
308**/\r
309RETURN_STATUS\r
310EFIAPI\r
311EndPerformanceMeasurement (\r
312 IN CONST VOID *Handle, OPTIONAL\r
313 IN CONST CHAR8 *Token, OPTIONAL\r
314 IN CONST CHAR8 *Module, OPTIONAL\r
315 IN UINT64 TimeStamp\r
316 )\r
317{\r
318 return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
319}\r
320\r
321/**\r
322 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
323 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,\r
324 and then eliminate the Identifier.\r
325\r
326 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is\r
327 zero on entry, then an attempt is made to retrieve the first entry from the performance log,\r
328 and the key for the second entry in the log is returned. If the performance log is empty,\r
329 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance\r
330 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is\r
331 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is\r
332 retrieved and an implementation specific non-zero key value that specifies the end of the performance\r
333 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry\r
334 is retrieved and zero is returned. In the cases where a performance log entry can be returned,\r
335 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.\r
336 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().\r
337 If Handle is NULL, then ASSERT().\r
338 If Token is NULL, then ASSERT().\r
339 If Module is NULL, then ASSERT().\r
340 If StartTimeStamp is NULL, then ASSERT().\r
341 If EndTimeStamp is NULL, then ASSERT().\r
342\r
343 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
344 0, then the first performance measurement log entry is retrieved.\r
345 On exit, the key of the next performance log entry.\r
346 @param Handle Pointer to environment specific context used to identify the component\r
347 being measured.\r
348 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
349 being measured.\r
350 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
351 being measured.\r
352 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
353 was started.\r
354 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
355 was ended.\r
356\r
357 @return The key for the next performance log entry (in general case).\r
358\r
359**/\r
360UINTN\r
361EFIAPI\r
362GetPerformanceMeasurement (\r
363 IN UINTN LogEntryKey,\r
364 OUT CONST VOID **Handle,\r
365 OUT CONST CHAR8 **Token,\r
366 OUT CONST CHAR8 **Module,\r
367 OUT UINT64 *StartTimeStamp,\r
368 OUT UINT64 *EndTimeStamp\r
369 )\r
370{\r
137fb13d 371 return 0;\r
f0da4d7d
SZ
372}\r
373\r
d042c6e8 374/**\r
375 Returns TRUE if the performance measurement macros are enabled.\r
376\r
377 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
378 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.\r
379\r
380 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
381 PcdPerformanceLibraryPropertyMask is set.\r
382 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of\r
383 PcdPerformanceLibraryPropertyMask is clear.\r
384\r
385**/\r
386BOOLEAN\r
387EFIAPI\r
388PerformanceMeasurementEnabled (\r
389 VOID\r
390 )\r
391{\r
392 return mPerformanceMeasurementEnabled;\r
393}\r
6b4d58a1
BD
394\r
395/**\r
396 Create performance record with event description and a timestamp.\r
397\r
398 @param CallerIdentifier - Image handle or pointer to caller ID GUID\r
399 @param Guid - Pointer to a GUID\r
400 @param String - Pointer to a string describing the measurement\r
401 @param Address - Pointer to a location in memory relevant to the measurement\r
402 @param Identifier - Performance identifier describing the type of measurement\r
403\r
404 @retval RETURN_SUCCESS - Successfully created performance record\r
405 @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records\r
406 @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL\r
407 pointer or invalid PerfId\r
408\r
409**/\r
410RETURN_STATUS\r
411EFIAPI\r
412LogPerformanceMeasurement (\r
413 IN CONST VOID *CallerIdentifier,\r
414 IN CONST VOID *Guid, OPTIONAL\r
415 IN CONST CHAR8 *String, OPTIONAL\r
416 IN UINT64 Address, OPTIONAL\r
417 IN UINT32 Identifier\r
418 )\r
419{\r
420 EFI_STATUS Status;\r
421\r
422 Status = GetPerformanceMeasurementProtocol ();\r
423 if (EFI_ERROR (Status)) {\r
424 return RETURN_OUT_OF_RESOURCES;\r
425 }\r
426\r
427 if (mPerformanceMeasurement != NULL) {\r
428 Status = mPerformanceMeasurement->CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);\r
429 } else {\r
430 ASSERT (FALSE);\r
431 }\r
432\r
433 return (RETURN_STATUS) Status;\r
434}\r
435\r
436/**\r
437 Check whether the specified performance measurement can be logged.\r
438\r
439 This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set\r
440 and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.\r
441\r
442 @param Type - Type of the performance measurement entry.\r
443\r
444 @retval TRUE The performance measurement can be logged.\r
445 @retval FALSE The performance measurement can NOT be logged.\r
446\r
447**/\r
448BOOLEAN\r
449EFIAPI\r
450LogPerformanceMeasurementEnabled (\r
451 IN CONST UINTN Type\r
452 )\r
453{\r
454 //\r
455 // When Performance measurement is enabled and the type is not filtered, the performance can be logged.\r
456 //\r
457 if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {\r
458 return TRUE;\r
459 }\r
460 return FALSE;\r
461}\r