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