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