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