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