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