public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [patch V2 0/9] Add new Perf macros
@ 2018-06-22  8:56 Dandan Bi
  2018-06-22  8:56 ` [patch V2 1/9] MdeModulePkg: Add PERFORMANCE_MEASUREMENT_PROTOCOL Dandan Bi
                   ` (9 more replies)
  0 siblings, 10 replies; 12+ messages in thread
From: Dandan Bi @ 2018-06-22  8:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Star Zeng, Michael Kinney

Add a group of new Perf macros in performance library for performance
logging. Which will simplify the usage model of performance measurement.
And also introduce new control functionality to disable different
perf types.

Patch 1-2:
Add a new internal protocol PERFORMANCE_MEASUREMENT_PROTOCOL,
which can be used to log performance info.

Patch 3-5:
Add new Perf macros and update library instances in MdeModulePkg
to for the implementation of new perf macros.

Patch 6:
Enhance the logic in DP tool since some new record and control
functionality are introduced by new Perf macros.

Patch 7-9:
update the consumer codes in core to use the new Perf macros.

Unit test:
1.DP tool can dump the performance data saved in the ACPI FPDT
  when set PcdEdkiiFpdtStringRecordEnableOnly to TRUE/FALSE.
2.Can disable specific knids of Perf entry through
  setting PcdPerformanceLibraryPropertyMask.

V2:
Patch 5: Share the common logics of creating FPDT record for
new added Perf macros and existing Perf macros.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>

Dandan Bi (9):
  MdeModulePkg: Add PERFORMANCE_MEASUREMENT_PROTOCOL
  MdeModulePkg: Update Performance instances to use new protocol
  MdePkg/PerformanceLib.h: Add new Perf macros
  MdeModulePkg/ExtendedFirmwarePerf: Remove PerfId definitions
  MdeModulePkg: Update performance library instances
  ShellPkg/dp: Update dp tool to parse new Perf record
  MdeModulePkg: Use new added Perf macros
  SecurityPkg: Use new added Perf macros
  UefiCpuPkg: Use new added Perf macros

 MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c      |    7 +
 MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c            |    8 +-
 MdeModulePkg/Core/Dxe/Hand/DriverSupport.c         |    8 +-
 MdeModulePkg/Core/Dxe/Image/Image.c                |   30 +-
 MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c      |    8 +-
 MdeModulePkg/Core/Pei/PeiMain/PeiMain.c            |   17 +-
 MdeModulePkg/Core/PiSmmCore/Dispatcher.c           |   15 +-
 MdeModulePkg/Core/PiSmmCore/PiSmmCore.c            |    4 +-
 .../Include/Guid/ExtendedFirmwarePerformance.h     |   31 -
 MdeModulePkg/Include/Guid/PerformanceMeasurement.h |   91 ++
 .../DxeCorePerformanceLib/DxeCorePerformanceLib.c  | 1183 +++++++++++---------
 .../DxeCorePerformanceLib.inf                      |    7 +-
 .../DxeCorePerformanceLibInternal.h                |  217 +---
 .../Library/DxePerformanceLib/DxePerformanceLib.c  |  193 ++--
 .../DxePerformanceLib/DxePerformanceLib.inf        |    5 +-
 .../Library/PeiPerformanceLib/PeiPerformanceLib.c  |  632 +++++++----
 .../SmmCorePerformanceLib/SmmCorePerformanceLib.c  |  960 ++++++++--------
 .../SmmCorePerformanceLib.inf                      |    7 +-
 .../SmmCorePerformanceLibInternal.h                |  215 +---
 .../Library/SmmPerformanceLib/SmmPerformanceLib.c  |  198 ++--
 .../SmmPerformanceLib/SmmPerformanceLib.inf        |    5 +-
 MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c   |    2 +-
 .../Library/UefiBootManagerLib/BmConsole.c         |    9 +-
 MdeModulePkg/MdeModulePkg.dec                      |    3 +
 MdeModulePkg/Universal/BdsDxe/BdsEntry.c           |   21 +-
 MdePkg/Include/Library/PerformanceLib.h            |  408 ++++++-
 .../BasePerformanceLibNull/PerformanceLib.c        |   57 +-
 MdePkg/MdePkg.dec                                  |    9 +-
 MdePkg/MdePkg.uni                                  |    6 +
 .../DxeRsa2048Sha256GuidedSectionExtractLib.c      |   16 +-
 .../PeiRsa2048Sha256GuidedSectionExtractLib.c      |   16 +-
 ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c      |   75 +-
 ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h      |    1 +
 .../DynamicCommand/DpDynamicCommand/DpInternal.h   |   14 +
 ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c |    4 +-
 .../DynamicCommand/DpDynamicCommand/DpUtilities.c  |   31 +
 UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c  |   16 +-
 37 files changed, 2600 insertions(+), 1929 deletions(-)
 create mode 100644 MdeModulePkg/Include/Guid/PerformanceMeasurement.h

-- 
2.14.3.windows.1



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch V2 1/9] MdeModulePkg: Add PERFORMANCE_MEASUREMENT_PROTOCOL
  2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
@ 2018-06-22  8:56 ` Dandan Bi
  2018-06-22  8:56 ` [patch V2 2/9] MdeModulePkg: Update Performance instances to use new protocol Dandan Bi
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Dandan Bi @ 2018-06-22  8:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Star Zeng

Add PerformanceMeasurement protocol to log performance info.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 MdeModulePkg/Include/Guid/PerformanceMeasurement.h | 91 ++++++++++++++++++++++
 MdeModulePkg/MdeModulePkg.dec                      |  3 +
 2 files changed, 94 insertions(+)
 create mode 100644 MdeModulePkg/Include/Guid/PerformanceMeasurement.h

diff --git a/MdeModulePkg/Include/Guid/PerformanceMeasurement.h b/MdeModulePkg/Include/Guid/PerformanceMeasurement.h
new file mode 100644
index 00000000000..f2955c73589
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/PerformanceMeasurement.h
@@ -0,0 +1,91 @@
+/** @file
+
+Copyright (c) 2017, Microsoft Corporation
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Performance measurement protocol, allows logging performance data.
+
+**/
+
+#ifndef _PERFORMANCE_MEASUREMENT_H_
+#define _PERFORMANCE_MEASUREMENT_H_
+
+//
+// GUID for Performance measurement Protocol
+//
+#define PERFORMANCE_MEASUREMENT_PROTOCOL_GUID \
+  { 0xc85d06be, 0x5f75, 0x48ce, {0xa8, 0x0f, 0x12, 0x36, 0xba, 0x3b, 0x87, 0xb1 } }
+
+#define SMM_PERFORMANCE_MEASUREMENT_PROTOCOL_GUID \
+  { 0xd56b6d73, 0x1a7b, 0x4015, {0x9b, 0xb4, 0x7b, 0x07, 0x17, 0x29, 0xed, 0x24 } }
+
+typedef struct _EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL;
+
+typedef enum {
+  PerfStartEntry,                        // used in StartPerformanceMeasurement()/StartPerformanceMeasurementEx()
+                                         // (map to PERF_START/PERF_START_EX)
+  PerfEndEntry,                          // used in EndPerformanceMeasurement()/EndPerformanceMeasurementEx()
+                                         // (map to PERF_END/PERF_END_EX)
+  PerfEntry                              // used in LogPerformanceMeasurement()
+                                         // (map to other Perf macros except above 4 macros)
+} PERF_MEASUREMENT_ATTRIBUTE;
+
+/**
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID.
+  @param Guid              - Pointer to a GUID.
+  @param String            - Pointer to a string describing the measurement.
+  @param TimeStamp         - 64-bit time stamp.
+  @param Address           - Pointer to a location in memory relevant to the measurement.
+  @param Identifier        - Performance identifier describing the type of measurement.
+  @param Attribute         - The attribute of the measurement. According to attribute can create a start
+                             record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+                             or a general record for other Perf macros.
+
+  @retval EFI_SUCCESS           - Successfully created performance record.
+  @retval EFI_OUT_OF_RESOURCES  - Ran out of space to store the records.
+  @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                  pointer or invalid PerfId.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *CREATE_PERFORMANCE_MEASUREMENT)(
+  IN CONST VOID                        *CallerIdentifier, OPTIONAL
+  IN CONST VOID                        *Guid,     OPTIONAL
+  IN CONST CHAR8                       *String,   OPTIONAL
+  IN       UINT64                      TimeStamp, OPTIONAL
+  IN       UINT64                      Address,   OPTIONAL
+  IN       UINT32                      Identifier,
+  IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute
+  );
+
+struct _EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL {
+  CREATE_PERFORMANCE_MEASUREMENT CreatePerformanceMeasurement;
+};
+
+extern EFI_GUID gEdkiiPerformanceMeasurementProtocolGuid;
+extern EFI_GUID gEdkiiSmmPerformanceMeasurementProtocolGuid;
+
+#endif // _PERFORMANCE_MEASUREMENT_H_
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 3802b6e0b86..108accc2c29 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -258,10 +258,13 @@
   #  Include/Guid/Performance.h
   gPerformanceProtocolGuid       = { 0x76B6BDFA, 0x2ACD, 0x4462, { 0x9E, 0x3F, 0xCB, 0x58, 0xC9, 0x69, 0xD9, 0x37 } }
   gSmmPerformanceProtocolGuid    = { 0xf866226a, 0xeaa5, 0x4f5a, { 0xa9, 0xa,  0x6c, 0xfb, 0xa5, 0x7c, 0x58, 0x8e } }
   gPerformanceExProtocolGuid     = { 0x1ea81bec, 0xf01a, 0x4d98, { 0xa2, 0x1,  0x4a, 0x61, 0xce, 0x2f, 0xc0, 0x22 } }
   gSmmPerformanceExProtocolGuid  = { 0x931fc048, 0xc71d, 0x4455, { 0x89, 0x30, 0x47, 0x6,  0x30, 0xe3, 0xe,  0xe5 } }
+  #  Include/Guid/PerformanceMeasurement.h
+  gEdkiiPerformanceMeasurementProtocolGuid      = { 0xc85d06be, 0x5f75, 0x48ce, { 0xa8, 0x0f, 0x12, 0x36, 0xba, 0x3b, 0x87, 0xb1 } }
+  gEdkiiSmmPerformanceMeasurementProtocolGuid   = { 0xd56b6d73, 0x1a7b, 0x4015, { 0x9b, 0xb4, 0x7b, 0x07, 0x17, 0x29, 0xed, 0x24 } }
 
   ## Guid is defined for CRC32 encapsulation scheme.
   #  Include/Guid/Crc32GuidedSectionExtraction.h
   gEfiCrc32GuidedSectionExtractionGuid = { 0xFC1BCDB0, 0x7D31, 0x49aa, {0x93, 0x6A, 0xA4, 0x60, 0x0D, 0x9D, 0xD0, 0x83 } }
 
-- 
2.14.3.windows.1



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch V2 2/9] MdeModulePkg: Update Performance instances to use new protocol
  2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
  2018-06-22  8:56 ` [patch V2 1/9] MdeModulePkg: Add PERFORMANCE_MEASUREMENT_PROTOCOL Dandan Bi
@ 2018-06-22  8:56 ` Dandan Bi
  2018-06-22  8:56 ` [patch V2 3/9] MdePkg/PerformanceLib.h: Add new Perf macros Dandan Bi
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Dandan Bi @ 2018-06-22  8:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Star Zeng

Update Performance instances in MdeModulePkg to use new
PerformanceMeasurement protocol.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 .../DxeCorePerformanceLib/DxeCorePerformanceLib.c  | 325 +++++---------------
 .../DxeCorePerformanceLib.inf                      |   6 +-
 .../DxeCorePerformanceLibInternal.h                | 216 ++------------
 .../Library/DxePerformanceLib/DxePerformanceLib.c  | 125 +++-----
 .../DxePerformanceLib/DxePerformanceLib.inf        |   5 +-
 .../SmmCorePerformanceLib/SmmCorePerformanceLib.c  | 327 +++++----------------
 .../SmmCorePerformanceLib.inf                      |   7 +-
 .../SmmCorePerformanceLibInternal.h                | 215 ++------------
 .../Library/SmmPerformanceLib/SmmPerformanceLib.c  | 130 +++-----
 .../SmmPerformanceLib/SmmPerformanceLib.inf        |   5 +-
 10 files changed, 283 insertions(+), 1078 deletions(-)

diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
index 68b29ac5a9e..79820605184 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
@@ -80,25 +80,14 @@ UINT8   *mBootRecordBuffer    = NULL;
 BOOLEAN  mLockInsertRecord    = FALSE;
 
 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL  *mDevicePathToText = NULL;
 
 //
-// Interfaces for Performance Protocol.
+// Interfaces for PerformanceMeasurement Protocol.
 //
-PERFORMANCE_PROTOCOL mPerformanceInterface = {
-  StartGauge,
-  EndGauge,
-  GetGauge
-  };
-
-//
-// Interfaces for PerformanceEx Protocol.
-//
-PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {
-  StartGaugeEx,
-  EndGaugeEx,
-  GetGaugeEx
+EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
+  CreatePerformanceMeasurement,
   };
 
 PERFORMANCE_PROPERTY  mPerformanceProperty;
 
 /**
@@ -797,22 +786,15 @@ InsertFpdtMeasurement (
 
   StringPtr     = NULL;
   UseModuleName = FALSE;
   ZeroMem (ModuleName, sizeof (ModuleName));
 
-  if (mLockInsertRecord) {
-    return EFI_UNSUPPORTED;
-  }
-
-  mLockInsertRecord = TRUE;
-
   //
   // Get record info (type, size, ProgressID and Module Guid).
   //
   Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo, &UseModuleName);
   if (EFI_ERROR (Status)) {
-    mLockInsertRecord = FALSE;
     return Status;
   }
 
   //
   // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
@@ -822,11 +804,10 @@ InsertFpdtMeasurement (
   // If it is start pref: the lower 4 bits of the ID should be 0.
   // If it is end pref: the lower 4 bits of the ID should not be 0.
   // If input ID doesn't follow the rule, we will adjust it.
   //
   if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
-    mLockInsertRecord = FALSE;
     return EFI_UNSUPPORTED;
   } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
     if (IsStart && ((Identifier & 0x000F) != 0)) {
       Identifier &= 0xFFF0;
     } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {
@@ -842,11 +823,10 @@ InsertFpdtMeasurement (
     if (mBootRecordSize + RecordInfo.RecordSize > mBootRecordMaxSize) {
       if (!mLackSpaceIsReported) {
         DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save boot records\n"));
         mLackSpaceIsReported = TRUE;
       }
-      mLockInsertRecord = FALSE;
       return EFI_OUT_OF_RESOURCES;
     } else {
       //
       // Save boot record into BootPerformance table
       //
@@ -864,11 +844,10 @@ InsertFpdtMeasurement (
                               mPerformanceLength + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER,
                               mPerformancePointer
                               );
 
       if (mPerformancePointer == NULL) {
-        mLockInsertRecord = FALSE;
         return EFI_OUT_OF_RESOURCES;
       }
       mMaxPerformanceLength = mPerformanceLength + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER;
     }
     //
@@ -961,15 +940,13 @@ InsertFpdtMeasurement (
 
   default:
     //
     // Record is not supported in current DXE phase, return EFI_ABORTED
     //
-    mLockInsertRecord = FALSE;
     return EFI_UNSUPPORTED;
   }
 
-  mLockInsertRecord = FALSE;
   return EFI_SUCCESS;
 }
 
 /**
   Dumps all the PEI performance.
@@ -1061,223 +1038,10 @@ ReportFpdtRecordBuffer (
     //
     mFpdtBufferIsReported = TRUE;
   }
 }
 
-/**
-  Adds a record at the end of the performance measurement log
-  that records the start time of a performance measurement.
-
-  Adds a record to the end of the performance measurement log
-  that contains the Handle, Token, Module and Identifier.
-  The end time of the new record must be set to zero.
-  If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
-  If TimeStamp is zero, the start time in the record is filled in with the value
-  read from the current time stamp.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the created record
-                                  is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
-
-  @retval EFI_SUCCESS             The data was read correctly from the device.
-  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
-
-**/
-EFI_STATUS
-EFIAPI
-StartGaugeEx (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp,
-  IN UINT32       Identifier
-  )
-{
-  return InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);
-}
-
-/**
-  Searches the performance measurement log from the beginning of the log
-  for the first matching record that contains a zero end time and fills in a valid end time.
-
-  Searches the performance measurement log from the beginning of the log
-  for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
-  If the record can not be found then return EFI_NOT_FOUND.
-  If the record is found and TimeStamp is not zero,
-  then the end time in the record is filled in with the value specified by TimeStamp.
-  If the record is found and TimeStamp is zero, then the end time in the matching record
-  is filled in with the current time stamp value.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the found record
-                                  is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
-
-  @retval EFI_SUCCESS             The end of  the measurement was recorded.
-  @retval EFI_NOT_FOUND           The specified measurement record could not be found.
-
-**/
-EFI_STATUS
-EFIAPI
-EndGaugeEx (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp,
-  IN UINT32       Identifier
-  )
-{
-  return InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);
-}
-
-/**
-  Retrieves a previously logged performance measurement.
-  It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
-  and then assign the Identifier with 0.
-
-    !!! Not support!!!
-
-  Retrieves the performance log entry from the performance log specified by LogEntryKey.
-  If it stands for a valid entry, then EFI_SUCCESS is returned and
-  GaugeDataEntryEx stores the pointer to that entry.
-
-  @param  LogEntryKey             The key for the previous performance measurement log entry.
-                                  If 0, then the first performance measurement log entry is retrieved.
-  @param  GaugeDataEntryEx        The indirect pointer to the extended gauge data entry specified by LogEntryKey
-                                  if the retrieval is successful.
-
-  @retval EFI_SUCCESS             The GuageDataEntryEx is successfully found based on LogEntryKey.
-  @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  GaugeDataEntryEx is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-GetGaugeEx (
-  IN  UINTN                 LogEntryKey,
-  OUT GAUGE_DATA_ENTRY_EX   **GaugeDataEntryEx
-  )
-{
-  return EFI_UNSUPPORTED;
-}
-
-/**
-  Adds a record at the end of the performance measurement log
-  that records the start time of a performance measurement.
-
-  Adds a record to the end of the performance measurement log
-  that contains the Handle, Token, and Module.
-  The end time of the new record must be set to zero.
-  If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
-  If TimeStamp is zero, the start time in the record is filled in with the value
-  read from the current time stamp.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-
-  @retval EFI_SUCCESS             The data was read correctly from the device.
-  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
-
-**/
-EFI_STATUS
-EFIAPI
-StartGauge (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp
-  )
-{
-  return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);
-}
-
-/**
-  Searches the performance measurement log from the beginning of the log
-  for the first matching record that contains a zero end time and fills in a valid end time.
-
-  Searches the performance measurement log from the beginning of the log
-  for the first record that matches Handle, Token, and Module and has an end time value of zero.
-  If the record can not be found then return EFI_NOT_FOUND.
-  If the record is found and TimeStamp is not zero,
-  then the end time in the record is filled in with the value specified by TimeStamp.
-  If the record is found and TimeStamp is zero, then the end time in the matching record
-  is filled in with the current time stamp value.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-
-  @retval EFI_SUCCESS             The end of  the measurement was recorded.
-  @retval EFI_NOT_FOUND           The specified measurement record could not be found.
-
-**/
-EFI_STATUS
-EFIAPI
-EndGauge (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp
-  )
-{
-  return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);
-}
-
-/**
-  Retrieves a previously logged performance measurement.
-  It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
-  and then eliminate the Identifier.
-
-    !!! Not support!!!
-
-  Retrieves the performance log entry from the performance log specified by LogEntryKey.
-  If it stands for a valid entry, then EFI_SUCCESS is returned and
-  GaugeDataEntry stores the pointer to that entry.
-
-  @param  LogEntryKey             The key for the previous performance measurement log entry.
-                                  If 0, then the first performance measurement log entry is retrieved.
-  @param  GaugeDataEntry          The indirect pointer to the gauge data entry specified by LogEntryKey
-                                  if the retrieval is successful.
-
-  @retval EFI_SUCCESS             The GuageDataEntry is successfully found based on LogEntryKey.
-  @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  GaugeDataEntry is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-GetGauge (
-  IN  UINTN               LogEntryKey,
-  OUT GAUGE_DATA_ENTRY    **GaugeDataEntry
-  )
-{
-  return EFI_UNSUPPORTED;
-}
-
-
 /**
   The constructor function initializes Performance infrastructure for DXE phase.
 
   The constructor function publishes Performance and PerformanceEx protocol, allocates memory to log DXE performance
   and merges PEI performance data to DXE performance log.
@@ -1317,14 +1081,12 @@ DxeCorePerformanceLibConstructor (
   // Install the protocol interfaces for DXE performance library instance.
   //
   Handle = NULL;
   Status = gBS->InstallMultipleProtocolInterfaces (
                   &Handle,
-                  &gPerformanceProtocolGuid,
-                  &mPerformanceInterface,
-                  &gPerformanceExProtocolGuid,
-                  &mPerformanceExInterface,
+                  &gEdkiiPerformanceMeasurementProtocolGuid,
+                  &mPerformanceMeasurementInterface,
                   NULL
                   );
   ASSERT_EFI_ERROR (Status);
 
   //
@@ -1357,10 +1119,59 @@ DxeCorePerformanceLibConstructor (
   }
 
   return EFI_SUCCESS;
 }
 
+/**
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID.
+  @param Guid              - Pointer to a GUID.
+  @param String            - Pointer to a string describing the measurement.
+  @param TimeStamp         - 64-bit time stamp.
+  @param Address           - Pointer to a location in memory relevant to the measurement.
+  @param Identifier        - Performance identifier describing the type of measurement.
+  @param Attribute         - The attribute of the measurement. According to attribute can create a start
+                             record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+                             or a general record for other Perf macros.
+
+  @retval EFI_SUCCESS           - Successfully created performance record.
+  @retval EFI_OUT_OF_RESOURCES  - Ran out of space to store the records.
+  @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                  pointer or invalid PerfId.
+**/
+EFI_STATUS
+EFIAPI
+CreatePerformanceMeasurement (
+  IN CONST VOID                        *CallerIdentifier,
+  IN CONST VOID                        *Guid,   OPTIONAL
+  IN CONST CHAR8                       *String, OPTIONAL
+  IN       UINT64                      TimeStamp,
+  IN       UINT64                      Address,  OPTIONAL
+  IN       UINT32                      Identifier,
+  IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute
+  )
+{
+  EFI_STATUS   Status;
+
+  Status = EFI_SUCCESS;
+
+  if (mLockInsertRecord) {
+    return EFI_INVALID_PARAMETER;
+  }
+  mLockInsertRecord = TRUE;
+
+  if (Attribute == PerfStartEntry) {
+    Status = InsertFpdtMeasurement (TRUE, CallerIdentifier, String, String, TimeStamp, Identifier);
+  } else if (Attribute == PerfEndEntry) {
+    Status = InsertFpdtMeasurement (FALSE, CallerIdentifier, String, String, TimeStamp, Identifier);
+  }
+  mLockInsertRecord = FALSE;
+
+  return Status;
+}
+
 /**
   Adds a record at the end of the performance measurement log
   that records the start time of a performance measurement.
 
   Adds a record to the end of the performance measurement log
@@ -1392,11 +1203,21 @@ StartPerformanceMeasurementEx (
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp,
   IN UINT32       Identifier
   )
 {
-  return InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);
+  CONST CHAR8     *String;
+
+  if (Token != NULL) {
+    String = Token;
+  } else if (Module != NULL) {
+    String = Module;
+  } else {
+    String = NULL;
+  }
+
+  return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);
 }
 
 /**
   Searches the performance measurement log from the beginning of the log
   for the first matching record that contains a zero end time and fills in a valid end time.
@@ -1431,11 +1252,21 @@ EndPerformanceMeasurementEx (
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp,
   IN UINT32       Identifier
   )
 {
-  return InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);
+  CONST CHAR8     *String;
+
+  if (Token != NULL) {
+    String = Token;
+  } else if (Module != NULL) {
+    String = Module;
+  } else {
+    String = NULL;
+  }
+
+  return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);
 }
 
 /**
   Attempts to retrieve a performance measurement log entry from the performance measurement log.
   It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
@@ -1525,11 +1356,11 @@ StartPerformanceMeasurement (
   IN CONST CHAR8  *Token,   OPTIONAL
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp
   )
 {
-  return InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, 0);
+  return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
 }
 
 /**
   Searches the performance measurement log from the beginning of the log
   for the first matching record that contains a zero end time and fills in a valid end time.
@@ -1561,11 +1392,11 @@ EndPerformanceMeasurement (
   IN CONST CHAR8  *Token,   OPTIONAL
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp
   )
 {
-  return InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, 0);
+  return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
 }
 
 /**
   Attempts to retrieve a performance measurement log entry from the performance measurement log.
   It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
index e752a93d837..68cd76da5b3 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
@@ -65,22 +65,18 @@
 [Protocols]
   gEfiSmmCommunicationProtocolGuid              ## SOMETIMES_CONSUMES
 
 
 [Guids]
-  ## SOMETIMES_CONSUMES   ## HOB
-  ## PRODUCES             ## UNDEFINED # Install protocol
   ## PRODUCES             ## SystemTable
   gPerformanceProtocolGuid
-  ## SOMETIMES_CONSUMES   ## HOB
-  ## PRODUCES             ## UNDEFINED # Install protocol
-  gPerformanceExProtocolGuid
   gZeroGuid                                     ## SOMETIMES_CONSUMES ## GUID
   gEfiFirmwarePerformanceGuid                   ## SOMETIMES_PRODUCES ## UNDEFINED # StatusCode Data
   gEdkiiFpdtExtendedFirmwarePerformanceGuid     ## SOMETIMES_CONSUMES ## HOB # StatusCode Data
   gEfiEventReadyToBootGuid                      ## CONSUMES           ## Event
   gEdkiiPiSmmCommunicationRegionTableGuid       ## SOMETIMES_CONSUMES    ## SystemTable
+  gEdkiiPerformanceMeasurementProtocolGuid      ## PRODUCES           ## UNDEFINED # Install protocol
 
 [Pcd]
   gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask         ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiFpdtStringRecordEnableOnly  ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdExtFpdtBootRecordPadSize         ## CONSUMES
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
index 7e79675f940..f9800e34941 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
@@ -20,10 +20,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 
 #include <PiDxe.h>
 
 #include <Guid/Performance.h>
+#include <Guid/PerformanceMeasurement.h>
 #include <Guid/ExtendedFirmwarePerformance.h>
 #include <Guid/ZeroGuid.h>
 #include <Guid/EventGroup.h>
 #include <Guid/FirmwarePerformance.h>
 #include <Guid/PiSmmCommunicationRegionTable.h>
@@ -47,203 +48,36 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/UefiLib.h>
 #include <Library/ReportStatusCodeLib.h>
 #include <Library/DxeServicesLib.h>
 #include <Library/PeCoffGetEntryPointLib.h>
 
-//
-// Interface declarations for PerformanceEx Protocol.
-//
 /**
-  Adds a record at the end of the performance measurement log
-  that records the start time of a performance measurement.
-
-  Adds a record to the end of the performance measurement log
-  that contains the Handle, Token, Module and Identifier.
-  The end time of the new record must be set to zero.
-  If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
-  If TimeStamp is zero, the start time in the record is filled in with the value
-  read from the current time stamp.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the created record
-                                  is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
-
-  @retval EFI_SUCCESS             The data was read correctly from the device.
-  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
-
-**/
-EFI_STATUS
-EFIAPI
-StartGaugeEx (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp,
-  IN UINT32       Identifier
-  );
-
-/**
-  Searches the performance measurement log from the beginning of the log
-  for the first matching record that contains a zero end time and fills in a valid end time.
-
-  Searches the performance measurement log from the beginning of the log
-  for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
-  If the record can not be found then return EFI_NOT_FOUND.
-  If the record is found and TimeStamp is not zero,
-  then the end time in the record is filled in with the value specified by TimeStamp.
-  If the record is found and TimeStamp is zero, then the end time in the matching record
-  is filled in with the current time stamp value.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the found record
-                                  is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
-
-  @retval EFI_SUCCESS             The end of  the measurement was recorded.
-  @retval EFI_NOT_FOUND           The specified measurement record could not be found.
-
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID.
+  @param Guid              - Pointer to a GUID.
+  @param String            - Pointer to a string describing the measurement.
+  @param TimeStamp         - 64-bit time stamp.
+  @param Address           - Pointer to a location in memory relevant to the measurement.
+  @param Identifier        - Performance identifier describing the type of measurement.
+  @param Attribute         - The attribute of the measurement. According to attribute can create a start
+                             record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+                             or a general record for other Perf macros.
+
+  @retval EFI_SUCCESS           - Successfully created performance record.
+  @retval EFI_OUT_OF_RESOURCES  - Ran out of space to store the records.
+  @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                  pointer or invalid PerfId.
 **/
 EFI_STATUS
 EFIAPI
-EndGaugeEx (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp,
-  IN UINT32       Identifier
+CreatePerformanceMeasurement(
+  IN CONST VOID                        *CallerIdentifier, OPTIONAL
+  IN CONST VOID                        *Guid,     OPTIONAL
+  IN CONST CHAR8                       *String,   OPTIONAL
+  IN       UINT64                      TimeStamp, OPTIONAL
+  IN       UINT64                      Address,   OPTIONAL
+  IN       UINT32                      Identifier,
+  IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute
   );
 
-/**
-  Retrieves a previously logged performance measurement.
-  It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
-  and then assign the Identifier with 0.
-
-  Retrieves the performance log entry from the performance log specified by LogEntryKey.
-  If it stands for a valid entry, then EFI_SUCCESS is returned and
-  GaugeDataEntryEx stores the pointer to that entry.
-
-  @param  LogEntryKey             The key for the previous performance measurement log entry.
-                                  If 0, then the first performance measurement log entry is retrieved.
-  @param  GaugeDataEntryEx        The indirect pointer to the extended gauge data entry specified by LogEntryKey
-                                  if the retrieval is successful.
-
-  @retval EFI_SUCCESS             The GuageDataEntryEx is successfully found based on LogEntryKey.
-  @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  GaugeDataEntryEx is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-GetGaugeEx (
-  IN  UINTN                 LogEntryKey,
-  OUT GAUGE_DATA_ENTRY_EX   **GaugeDataEntryEx
-  );
-
-//
-// Interface declarations for Performance Protocol.
-//
-/**
-  Adds a record at the end of the performance measurement log
-  that records the start time of a performance measurement.
-
-  Adds a record to the end of the performance measurement log
-  that contains the Handle, Token, and Module.
-  The end time of the new record must be set to zero.
-  If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
-  If TimeStamp is zero, the start time in the record is filled in with the value
-  read from the current time stamp.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-
-  @retval EFI_SUCCESS             The data was read correctly from the device.
-  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
-
-**/
-EFI_STATUS
-EFIAPI
-StartGauge (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp
-  );
-
-/**
-  Searches the performance measurement log from the beginning of the log
-  for the first matching record that contains a zero end time and fills in a valid end time.
-
-  Searches the performance measurement log from the beginning of the log
-  for the first record that matches Handle, Token, and Module and has an end time value of zero.
-  If the record can not be found then return EFI_NOT_FOUND.
-  If the record is found and TimeStamp is not zero,
-  then the end time in the record is filled in with the value specified by TimeStamp.
-  If the record is found and TimeStamp is zero, then the end time in the matching record
-  is filled in with the current time stamp value.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-
-  @retval EFI_SUCCESS             The end of  the measurement was recorded.
-  @retval EFI_NOT_FOUND           The specified measurement record could not be found.
-
-**/
-EFI_STATUS
-EFIAPI
-EndGauge (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp
-  );
-
-/**
-  Retrieves a previously logged performance measurement.
-  It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
-  and then eliminate the Identifier.
-
-  Retrieves the performance log entry from the performance log specified by LogEntryKey.
-  If it stands for a valid entry, then EFI_SUCCESS is returned and
-  GaugeDataEntry stores the pointer to that entry.
-
-  @param  LogEntryKey             The key for the previous performance measurement log entry.
-                                  If 0, then the first performance measurement log entry is retrieved.
-  @param  GaugeDataEntry          The indirect pointer to the gauge data entry specified by LogEntryKey
-                                  if the retrieval is successful.
-
-  @retval EFI_SUCCESS             The GuageDataEntry is successfully found based on LogEntryKey.
-  @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  GaugeDataEntry is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-GetGauge (
-  IN  UINTN               LogEntryKey,
-  OUT GAUGE_DATA_ENTRY    **GaugeDataEntry
-  );
-
-
 #endif
diff --git a/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c b/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c
index cb62d522f3d..9ed50d22b8d 100644
--- a/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c
+++ b/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c
@@ -18,22 +18,21 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 
 
 #include <PiDxe.h>
 
-#include <Guid/Performance.h>
+#include <Guid/PerformanceMeasurement.h>
 
 #include <Library/PerformanceLib.h>
 #include <Library/DebugLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/PcdLib.h>
 
 //
 // The cached Performance Protocol and PerformanceEx Protocol interface.
 //
-PERFORMANCE_PROTOCOL        *mPerformance = NULL;
-PERFORMANCE_EX_PROTOCOL     *mPerformanceEx = NULL;
+EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL      *mPerformanceMeasurement = NULL;
 
 /**
   The function caches the pointers to PerformanceEx protocol and Performance Protocol.
 
   The function locates PerformanceEx protocol and Performance Protocol from protocol database.
@@ -41,39 +40,28 @@ PERFORMANCE_EX_PROTOCOL     *mPerformanceEx = NULL;
   @retval EFI_SUCCESS     PerformanceEx protocol or Performance Protocol is successfully located.
   @retval EFI_NOT_FOUND   Both PerformanceEx protocol and Performance Protocol are not located to log performance.
 
 **/
 EFI_STATUS
-GetPerformanceProtocol (
+GetPerformanceMeasurementProtocol (
   VOID
   )
 {
   EFI_STATUS                Status;
-  PERFORMANCE_PROTOCOL      *Performance;
-  PERFORMANCE_EX_PROTOCOL   *PerformanceEx;
+  EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL   *PerformanceMeasurement;
 
-  if (mPerformanceEx != NULL || mPerformance != NULL) {
+  if (mPerformanceMeasurement != NULL) {
     return EFI_SUCCESS;
   }
 
-  Status = gBS->LocateProtocol (&gPerformanceExProtocolGuid, NULL, (VOID **) &PerformanceEx);
+  Status = gBS->LocateProtocol (&gEdkiiPerformanceMeasurementProtocolGuid, NULL, (VOID **) &PerformanceMeasurement);
   if (!EFI_ERROR (Status)) {
-    ASSERT (PerformanceEx != NULL);
+    ASSERT (PerformanceMeasurement != NULL);
     //
-    // Cache PerformanceEx Protocol.
+    // Cache PerformanceMeasurement Protocol.
     //
-    mPerformanceEx = PerformanceEx;
-    return EFI_SUCCESS;
-  }
-
-  Status = gBS->LocateProtocol (&gPerformanceProtocolGuid, NULL, (VOID **) &Performance);
-  if (!EFI_ERROR (Status)) {
-    ASSERT (Performance != NULL);
-    //
-    // Cache performance protocol.
-    //
-    mPerformance = Performance;
+    mPerformanceMeasurement = PerformanceMeasurement;
     return EFI_SUCCESS;
   }
 
   return EFI_NOT_FOUND;
 }
@@ -108,21 +96,28 @@ StartPerformanceMeasurementEx (
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp,
   IN UINT32       Identifier
   )
 {
-  EFI_STATUS  Status;
+  EFI_STATUS    Status;
+  CONST CHAR8*  String;
 
-  Status = GetPerformanceProtocol ();
+  Status = GetPerformanceMeasurementProtocol ();
   if (EFI_ERROR (Status)) {
-    return RETURN_OUT_OF_RESOURCES;
+    return RETURN_NOT_FOUND;
+  }
+
+  if (Token != NULL) {
+    String = Token;
+  } else if (Module != NULL) {
+    String = Module;
+  } else {
+    String = NULL;
   }
 
-  if (mPerformanceEx != NULL) {
-    Status = mPerformanceEx->StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
-  } else if (mPerformance != NULL) {
-    Status = mPerformance->StartGauge (Handle, Token, Module, TimeStamp);
+  if (mPerformanceMeasurement != NULL) {
+    Status = mPerformanceMeasurement->CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);
   } else {
     ASSERT (FALSE);
   }
 
   return (RETURN_STATUS) Status;
@@ -160,21 +155,28 @@ EndPerformanceMeasurementEx (
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp,
   IN UINT32       Identifier
   )
 {
-  EFI_STATUS  Status;
+  EFI_STATUS    Status;
+  CONST CHAR8*  String;
 
-  Status = GetPerformanceProtocol ();
+  Status = GetPerformanceMeasurementProtocol ();
   if (EFI_ERROR (Status)) {
     return RETURN_NOT_FOUND;
   }
 
-  if (mPerformanceEx != NULL) {
-    Status = mPerformanceEx->EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
-  } else if (mPerformance != NULL) {
-    Status = mPerformance->EndGauge (Handle, Token, Module, TimeStamp);
+  if (Token != NULL) {
+    String = Token;
+  } else if (Module != NULL) {
+    String = Module;
+  } else {
+    String = NULL;
+  }
+
+  if (mPerformanceMeasurement != NULL) {
+    Status = mPerformanceMeasurement->CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);
   } else {
     ASSERT (FALSE);
   }
 
   return (RETURN_STATUS) Status;
@@ -231,62 +233,12 @@ GetPerformanceMeasurementEx (
   OUT UINT64      *StartTimeStamp,
   OUT UINT64      *EndTimeStamp,
   OUT UINT32      *Identifier
   )
 {
-  EFI_STATUS            Status;
-  GAUGE_DATA_ENTRY_EX   *GaugeData;
-
-  GaugeData = NULL;
-
-  ASSERT (Handle != NULL);
-  ASSERT (Token != NULL);
-  ASSERT (Module != NULL);
-  ASSERT (StartTimeStamp != NULL);
-  ASSERT (EndTimeStamp != NULL);
-  ASSERT (Identifier != NULL);
-
-  Status = GetPerformanceProtocol ();
-  if (EFI_ERROR (Status)) {
-    return 0;
-  }
-
-  if (mPerformanceEx != NULL) {
-    Status = mPerformanceEx->GetGaugeEx (LogEntryKey++, &GaugeData);
-  } else if (mPerformance != NULL) {
-    Status = mPerformance->GetGauge (LogEntryKey++, (GAUGE_DATA_ENTRY **) &GaugeData);
-  } else {
-    ASSERT (FALSE);
-    return 0;
-  }
-
-  //
-  // Make sure that LogEntryKey is a valid log entry key,
-  //
-  ASSERT (Status != EFI_INVALID_PARAMETER);
-
-  if (EFI_ERROR (Status)) {
-    //
-    // The LogEntryKey is the last entry (equals to the total entry number).
-    //
-    return 0;
-  }
-
-  ASSERT (GaugeData != NULL);
-
-  *Handle         = (VOID *) (UINTN) GaugeData->Handle;
-  *Token          = GaugeData->Token;
-  *Module         = GaugeData->Module;
-  *StartTimeStamp = GaugeData->StartTimeStamp;
-  *EndTimeStamp   = GaugeData->EndTimeStamp;
-  if (mPerformanceEx != NULL) {
-    *Identifier   = GaugeData->Identifier;
-  } else {
-    *Identifier   = 0;
-  }
+  return 0;
 
-  return LogEntryKey;
 }
 
 /**
   Creates a record for the beginning of a performance measurement.
 
@@ -401,12 +353,11 @@ GetPerformanceMeasurement (
   OUT CONST CHAR8 **Module,
   OUT UINT64      *StartTimeStamp,
   OUT UINT64      *EndTimeStamp
   )
 {
-  UINT32 Identifier;
-  return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);
+  return 0;
 }
 
 /**
   Returns TRUE if the performance measurement macros are enabled.
 
diff --git a/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf b/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
index edc63c6f0b6..c7d06a3a1b1 100644
--- a/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+++ b/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
@@ -4,11 +4,11 @@
 #  This library instance provides infrastructure for DXE phase drivers to log performance
 #  data. It consumes PerformanceEx or Performance Protocol published by DxeCorePerformanceLib
 #  to log performance data. If both PerformanceEx and Performance Protocol are not available,
 #  it does not log any performance information.
 #  
-#  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD License
 #  which accompanies this distribution.  The full text of the license may be found at
 #  http://opensource.org/licenses/bsd-license.php
 #  
@@ -46,12 +46,11 @@
   UefiBootServicesTableLib
   DebugLib
 
 
 [Guids]
-  gPerformanceProtocolGuid      ## SOMETIMES_CONSUMES   ## UNDEFINED # Locate protocol
-  gPerformanceExProtocolGuid    ## SOMETIMES_CONSUMES   ## UNDEFINED # Locate protocol
+  gEdkiiPerformanceMeasurementProtocolGuid    ## SOMETIMES_CONSUMES   ## UNDEFINED # Locate protocol
 
 
 [Pcd]
   gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask    ## CONSUMES
 
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
index dbc1166f254..e630773562f 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
@@ -52,25 +52,14 @@ BOOLEAN              mLackSpaceIsReport    = FALSE;
 CHAR8                *mPlatformLanguage    = NULL;
 SPIN_LOCK            mSmmFpdtLock;
 PERFORMANCE_PROPERTY  mPerformanceProperty;
 
 //
-// Interfaces for SMM Performance Protocol.
+// Interfaces for SMM PerformanceMeasurement Protocol.
 //
-PERFORMANCE_PROTOCOL mPerformanceInterface = {
-  StartGauge,
-  EndGauge,
-  GetGauge
-};
-
-//
-// Interfaces for SMM PerformanceEx Protocol.
-//
-PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {
-  StartGaugeEx,
-  EndGaugeEx,
-  GetGaugeEx
+EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
+  CreatePerformanceMeasurement,
 };
 
 /**
 Check whether the Token is a known one which is uesed by core.
 
@@ -641,239 +630,10 @@ InsertFpdtMeasurement (
   mSmmBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;
 
   return EFI_SUCCESS;
 }
 
-/**
-  Adds a record at the end of the performance measurement log
-  that records the start time of a performance measurement.
-
-  Adds a record to the end of the performance measurement log
-  that contains the Handle, Token, Module and Identifier.
-  The end time of the new record must be set to zero.
-  If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
-  If TimeStamp is zero, the start time in the record is filled in with the value
-  read from the current time stamp.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the created record
-                                  is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
-
-  @retval EFI_SUCCESS             The data was read correctly from the device.
-  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
-
-**/
-EFI_STATUS
-EFIAPI
-StartGaugeEx (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp,
-  IN UINT32       Identifier
-  )
-{
-  EFI_STATUS    Status;
-
-  AcquireSpinLock (&mSmmFpdtLock);
-
-  Status = InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);
-
-  ReleaseSpinLock (&mSmmFpdtLock);
-
-  return Status;
-}
-
-/**
-  Searches the performance measurement log from the beginning of the log
-  for the first matching record that contains a zero end time and fills in a valid end time.
-
-  Searches the performance measurement log from the beginning of the log
-  for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
-  If the record can not be found then return EFI_NOT_FOUND.
-  If the record is found and TimeStamp is not zero,
-  then the end time in the record is filled in with the value specified by TimeStamp.
-  If the record is found and TimeStamp is zero, then the end time in the matching record
-  is filled in with the current time stamp value.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the found record
-                                  is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
-
-  @retval EFI_SUCCESS             The end of  the measurement was recorded.
-  @retval EFI_NOT_FOUND           The specified measurement record could not be found.
-
-**/
-EFI_STATUS
-EFIAPI
-EndGaugeEx (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp,
-  IN UINT32       Identifier
-  )
-{
-  EFI_STATUS     Status;
-
-  AcquireSpinLock (&mSmmFpdtLock);
-
-  Status = InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);
-
-  ReleaseSpinLock (&mSmmFpdtLock);
-
-  return Status;
-}
-
-/**
-  Retrieves a previously logged performance measurement.
-  It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
-  and then assign the Identifier with 0.
-
-  !!! Not Support!!!
-
-  Retrieves the performance log entry from the performance log specified by LogEntryKey.
-  If it stands for a valid entry, then EFI_SUCCESS is returned and
-  GaugeDataEntryEx stores the pointer to that entry.
-
-  @param  LogEntryKey             The key for the previous performance measurement log entry.
-                                  If 0, then the first performance measurement log entry is retrieved.
-  @param  GaugeDataEntryEx        The indirect pointer to the extended gauge data entry specified by LogEntryKey
-                                  if the retrieval is successful.
-
-  @retval EFI_SUCCESS             The GuageDataEntryEx is successfully found based on LogEntryKey.
-  @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  GaugeDataEntryEx is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-GetGaugeEx (
-  IN  UINTN                 LogEntryKey,
-  OUT GAUGE_DATA_ENTRY_EX   **GaugeDataEntryEx
-  )
-{
-  return EFI_UNSUPPORTED;
-}
-
-/**
-  Adds a record at the end of the performance measurement log
-  that records the start time of a performance measurement.
-
-  Adds a record to the end of the performance measurement log
-  that contains the Handle, Token, and Module.
-  The end time of the new record must be set to zero.
-  If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
-  If TimeStamp is zero, the start time in the record is filled in with the value
-  read from the current time stamp.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-
-  @retval EFI_SUCCESS             The data was read correctly from the device.
-  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
-
-**/
-EFI_STATUS
-EFIAPI
-StartGauge (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp
-  )
-{
-  return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);
-}
-
-/**
-  Searches the performance measurement log from the beginning of the log
-  for the first matching record that contains a zero end time and fills in a valid end time.
-
-  Searches the performance measurement log from the beginning of the log
-  for the first record that matches Handle, Token, and Module and has an end time value of zero.
-  If the record can not be found then return EFI_NOT_FOUND.
-  If the record is found and TimeStamp is not zero,
-  then the end time in the record is filled in with the value specified by TimeStamp.
-  If the record is found and TimeStamp is zero, then the end time in the matching record
-  is filled in with the current time stamp value.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-
-  @retval EFI_SUCCESS             The end of  the measurement was recorded.
-  @retval EFI_NOT_FOUND           The specified measurement record could not be found.
-
-**/
-EFI_STATUS
-EFIAPI
-EndGauge (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp
-  )
-{
-  return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);
-}
-
-/**
-  Retrieves a previously logged performance measurement.
-  It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
-  and then eliminate the Identifier.
-
-  !!! Not Support!!!
-
-  Retrieves the performance log entry from the performance log specified by LogEntryKey.
-  If it stands for a valid entry, then EFI_SUCCESS is returned and
-  GaugeDataEntry stores the pointer to that entry.
-
-  @param  LogEntryKey             The key for the previous performance measurement log entry.
-                                  If 0, then the first performance measurement log entry is retrieved.
-  @param  GaugeDataEntry          The indirect pointer to the gauge data entry specified by LogEntryKey
-                                  if the retrieval is successful.
-
-  @retval EFI_SUCCESS             The GuageDataEntry is successfully found based on LogEntryKey.
-  @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  GaugeDataEntry is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-GetGauge (
-  IN  UINTN               LogEntryKey,
-  OUT GAUGE_DATA_ENTRY    **GaugeDataEntry
-  )
-{
-  return EFI_UNSUPPORTED;
-}
-
-
 /**
   SmmReadyToBoot protocol notification event handler.
 
   @param  Protocol   Points to the protocol's unique identifier
   @param  Interface  Points to the interface instance
@@ -940,20 +700,13 @@ InitializeSmmCorePerformanceLib (
   // Install the protocol interfaces for SMM performance library instance.
   //
   Handle = NULL;
   Status = gSmst->SmmInstallProtocolInterface (
                     &Handle,
-                    &gSmmPerformanceProtocolGuid,
-                    EFI_NATIVE_INTERFACE,
-                    &mPerformanceInterface
-                    );
-  ASSERT_EFI_ERROR (Status);
-  Status = gSmst->SmmInstallProtocolInterface (
-                    &Handle,
-                    &gSmmPerformanceExProtocolGuid,
+                    &gEdkiiSmmPerformanceMeasurementProtocolGuid,
                     EFI_NATIVE_INTERFACE,
-                    &mPerformanceExInterface
+                    &mPerformanceMeasurementInterface
                     );
   ASSERT_EFI_ERROR (Status);
 
   Status = gSmst->SmmRegisterProtocolNotify (
                     &gEdkiiSmmReadyToBootProtocolGuid,
@@ -1029,10 +782,52 @@ SmmCorePerformanceLibConstructor (
   ASSERT_EFI_ERROR (Status);
 
   return EFI_SUCCESS;
 }
 
+/**
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID.
+  @param Guid              - Pointer to a GUID.
+  @param String            - Pointer to a string describing the measurement.
+  @param TimeStamp         - 64-bit time stamp.
+  @param Address           - Pointer to a location in memory relevant to the measurement.
+  @param Identifier        - Performance identifier describing the type of measurement.
+  @param Attribute         - The attribute of the measurement. According to attribute can create a start
+                             record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+                             or a general record for other Perf macros.
+
+  @retval EFI_SUCCESS           - Successfully created performance record.
+  @retval EFI_OUT_OF_RESOURCES  - Ran out of space to store the records.
+  @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                  pointer or invalid PerfId.
+**/
+EFI_STATUS
+EFIAPI
+CreatePerformanceMeasurement(
+  IN CONST VOID                        *CallerIdentifier, OPTIONAL
+  IN CONST VOID                        *Guid,     OPTIONAL
+  IN CONST CHAR8                       *String,   OPTIONAL
+  IN       UINT64                      TimeStamp, OPTIONAL
+  IN       UINT64                      Address,   OPTIONAL
+  IN       UINT32                      Identifier,
+  IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute
+  )
+{
+  EFI_STATUS   Status;
+
+  AcquireSpinLock (&mSmmFpdtLock);
+  if (Attribute == PerfStartEntry) {
+    Status = InsertFpdtMeasurement (TRUE, CallerIdentifier, String, String, TimeStamp, Identifier);
+  } else if (Attribute == PerfEndEntry) {
+    Status = InsertFpdtMeasurement (FALSE, CallerIdentifier, String, String, TimeStamp, Identifier);
+  }
+  ReleaseSpinLock (&mSmmFpdtLock);
+  return Status;
+}
+
 /**
   Adds a record at the end of the performance measurement log
   that records the start time of a performance measurement.
 
   Adds a record to the end of the performance measurement log
@@ -1064,11 +859,21 @@ StartPerformanceMeasurementEx (
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp,
   IN UINT32       Identifier
   )
 {
-  return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
+  CONST CHAR8     *String;
+
+  if (Token != NULL) {
+    String = Token;
+  } else if (Module != NULL) {
+    String = Module;
+  } else {
+    String = NULL;
+  }
+
+  return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);
 }
 
 /**
   Searches the performance measurement log from the beginning of the log
   for the first matching record that contains a zero end time and fills in a valid end time.
@@ -1103,11 +908,21 @@ EndPerformanceMeasurementEx (
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp,
   IN UINT32       Identifier
   )
 {
-  return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
+  CONST CHAR8     *String;
+
+  if (Token != NULL) {
+    String = Token;
+  } else if (Module != NULL) {
+    String = Module;
+  } else {
+    String = NULL;
+  }
+
+  return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);
 }
 
 /**
   Attempts to retrieve a performance measurement log entry from the performance measurement log.
   It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
@@ -1196,11 +1011,11 @@ StartPerformanceMeasurement (
   IN CONST CHAR8  *Token,   OPTIONAL
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp
   )
 {
-  return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);
+  return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
 }
 
 /**
   Searches the performance measurement log from the beginning of the log
   for the first matching record that contains a zero end time and fills in a valid end time.
@@ -1232,11 +1047,11 @@ EndPerformanceMeasurement (
   IN CONST CHAR8  *Token,   OPTIONAL
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp
   )
 {
-  return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);
+  return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
 }
 
 /**
   Attempts to retrieve a performance measurement log entry from the performance measurement log.
   It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
index 01d8604eb61..61b92836657 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
@@ -64,19 +64,14 @@
 [Protocols]
   gEfiSmmBase2ProtocolGuid                  ## CONSUMES
   gEdkiiSmmReadyToBootProtocolGuid          ## NOTIFY
 
 [Guids]
-  ## PRODUCES ## UNDEFINED # Install protocol
-  ## CONSUMES ## UNDEFINED # SmiHandlerRegister
-  gSmmPerformanceProtocolGuid
-  ## PRODUCES ## UNDEFINED # Install protocol
-  ## CONSUMES ## UNDEFINED # SmiHandlerRegister
-  gSmmPerformanceExProtocolGuid
   ## PRODUCES ## SystemTable
   gPerformanceProtocolGuid
   gEdkiiFpdtExtendedFirmwarePerformanceGuid ## SOMETIMES_PRODUCES ## UNDEFINED # StatusCode Data
   gZeroGuid                                 ## SOMETIMES_CONSUMES ## GUID
+  gEdkiiSmmPerformanceMeasurementProtocolGuid             ## PRODUCES ## UNDEFINED # Install protocol
 
 [Pcd]
   gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask        ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiFpdtStringRecordEnableOnly ## CONSUMES
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h
index 9d24d9ff7a0..76f24984735 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h
@@ -18,10 +18,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #ifndef _SMM_CORE_PERFORMANCE_LIB_INTERNAL_H_
 #define _SMM_CORE_PERFORMANCE_LIB_INTERNAL_H_
 
 
 #include <Guid/Performance.h>
+#include <Guid/PerformanceMeasurement.h>
 #include <Guid/ExtendedFirmwarePerformance.h>
 #include <Guid/FirmwarePerformance.h>
 #include <Guid/ZeroGuid.h>
 #include <Guid/EventGroup.h>
 
@@ -44,202 +45,38 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/SmmBase2.h>
 #include <Protocol/LoadedImage.h>
 #include <Protocol/DevicePathToText.h>
 
 //
-// Interface declarations for SMM PerformanceEx Protocol.
+// Interface declarations for SMM PerformanceMeasurement Protocol.
 //
 /**
-  Adds a record at the end of the performance measurement log
-  that records the start time of a performance measurement.
-
-  Adds a record to the end of the performance measurement log
-  that contains the Handle, Token, Module and Identifier.
-  The end time of the new record must be set to zero.
-  If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
-  If TimeStamp is zero, the start time in the record is filled in with the value
-  read from the current time stamp.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the created record
-                                  is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
-
-  @retval EFI_SUCCESS             The data was read correctly from the device.
-  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
-
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID.
+  @param Guid              - Pointer to a GUID.
+  @param String            - Pointer to a string describing the measurement.
+  @param TimeStamp         - 64-bit time stamp.
+  @param Address           - Pointer to a location in memory relevant to the measurement.
+  @param Identifier        - Performance identifier describing the type of measurement.
+  @param Attribute         - The attribute of the measurement. According to attribute can create a start
+                             record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+                             or a general record for other Perf macros.
+
+  @retval EFI_SUCCESS           - Successfully created performance record.
+  @retval EFI_OUT_OF_RESOURCES  - Ran out of space to store the records.
+  @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                  pointer or invalid PerfId.
 **/
 EFI_STATUS
 EFIAPI
-StartGaugeEx (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp,
-  IN UINT32       Identifier
+CreatePerformanceMeasurement(
+  IN CONST VOID                        *CallerIdentifier, OPTIONAL
+  IN CONST VOID                        *Guid,     OPTIONAL
+  IN CONST CHAR8                       *String,   OPTIONAL
+  IN       UINT64                      TimeStamp, OPTIONAL
+  IN       UINT64                      Address,   OPTIONAL
+  IN       UINT32                      Identifier,
+  IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute
   );
 
-/**
-  Searches the performance measurement log from the beginning of the log
-  for the first matching record that contains a zero end time and fills in a valid end time.
-
-  Searches the performance measurement log from the beginning of the log
-  for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
-  If the record can not be found then return EFI_NOT_FOUND.
-  If the record is found and TimeStamp is not zero,
-  then the end time in the record is filled in with the value specified by TimeStamp.
-  If the record is found and TimeStamp is zero, then the end time in the matching record
-  is filled in with the current time stamp value.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the found record
-                                  is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
-
-  @retval EFI_SUCCESS             The end of  the measurement was recorded.
-  @retval EFI_NOT_FOUND           The specified measurement record could not be found.
-
-**/
-EFI_STATUS
-EFIAPI
-EndGaugeEx (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp,
-  IN UINT32       Identifier
-  );
-
-/**
-  Retrieves a previously logged performance measurement.
-  It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
-  and then assign the Identifier with 0.
-
-  Retrieves the performance log entry from the performance log specified by LogEntryKey.
-  If it stands for a valid entry, then EFI_SUCCESS is returned and
-  GaugeDataEntryEx stores the pointer to that entry.
-
-  @param  LogEntryKey             The key for the previous performance measurement log entry.
-                                  If 0, then the first performance measurement log entry is retrieved.
-  @param  GaugeDataEntryEx        The indirect pointer to the extended gauge data entry specified by LogEntryKey
-                                  if the retrieval is successful.
-
-  @retval EFI_SUCCESS             The GuageDataEntryEx is successfully found based on LogEntryKey.
-  @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  GaugeDataEntryEx is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-GetGaugeEx (
-  IN  UINTN                 LogEntryKey,
-  OUT GAUGE_DATA_ENTRY_EX   **GaugeDataEntryEx
-  );
-
-//
-// Interface declarations for SMM Performance Protocol.
-//
-/**
-  Adds a record at the end of the performance measurement log
-  that records the start time of a performance measurement.
-
-  Adds a record to the end of the performance measurement log
-  that contains the Handle, Token, and Module.
-  The end time of the new record must be set to zero.
-  If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
-  If TimeStamp is zero, the start time in the record is filled in with the value
-  read from the current time stamp.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-
-  @retval EFI_SUCCESS             The data was read correctly from the device.
-  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
-
-**/
-EFI_STATUS
-EFIAPI
-StartGauge (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp
-  );
-
-/**
-  Searches the performance measurement log from the beginning of the log
-  for the first matching record that contains a zero end time and fills in a valid end time.
-
-  Searches the performance measurement log from the beginning of the log
-  for the first record that matches Handle, Token, and Module and has an end time value of zero.
-  If the record can not be found then return EFI_NOT_FOUND.
-  If the record is found and TimeStamp is not zero,
-  then the end time in the record is filled in with the value specified by TimeStamp.
-  If the record is found and TimeStamp is zero, then the end time in the matching record
-  is filled in with the current time stamp value.
-
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  TimeStamp               64-bit time stamp.
-
-  @retval EFI_SUCCESS             The end of  the measurement was recorded.
-  @retval EFI_NOT_FOUND           The specified measurement record could not be found.
-
-**/
-EFI_STATUS
-EFIAPI
-EndGauge (
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       TimeStamp
-  );
-
-/**
-  Retrieves a previously logged performance measurement.
-  It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
-  and then eliminate the Identifier.
-
-  Retrieves the performance log entry from the performance log specified by LogEntryKey.
-  If it stands for a valid entry, then EFI_SUCCESS is returned and
-  GaugeDataEntry stores the pointer to that entry.
-
-  @param  LogEntryKey             The key for the previous performance measurement log entry.
-                                  If 0, then the first performance measurement log entry is retrieved.
-  @param  GaugeDataEntry          The indirect pointer to the gauge data entry specified by LogEntryKey
-                                  if the retrieval is successful.
-
-  @retval EFI_SUCCESS             The GuageDataEntry is successfully found based on LogEntryKey.
-  @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
-  @retval EFI_INVALIDE_PARAMETER  GaugeDataEntry is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-GetGauge (
-  IN  UINTN               LogEntryKey,
-  OUT GAUGE_DATA_ENTRY    **GaugeDataEntry
-  );
-
-
 #endif
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
index 4a08c24789c..fd820c0e49c 100644
--- a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
+++ b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
@@ -16,24 +16,22 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 **/
 
 
-#include <Guid/Performance.h>
+#include <Guid/PerformanceMeasurement.h>
 
 #include <Library/PerformanceLib.h>
 #include <Library/DebugLib.h>
 #include <Library/SmmServicesTableLib.h>
 #include <Library/PcdLib.h>
 #include <Library/BaseMemoryLib.h>
 
 //
 // The cached SMM Performance Protocol and SMM PerformanceEx Protocol interface.
-//
-PERFORMANCE_PROTOCOL        *mPerformance = NULL;
-PERFORMANCE_EX_PROTOCOL     *mPerformanceEx = NULL;
-BOOLEAN                     mPerformanceMeasurementEnabled;
+EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL  *mPerformanceMeasurement = NULL;
+BOOLEAN                                 mPerformanceMeasurementEnabled;
 
 /**
   The constructor function initializes the Performance Measurement Enable flag
 
   @param  ImageHandle   The firmware allocated handle for the EFI image.
@@ -63,42 +61,30 @@ SmmPerformanceLibConstructor (
   @retval EFI_SUCCESS     SMM PerformanceEx protocol or Performance Protocol is successfully located.
   @retval EFI_NOT_FOUND   Both SMM PerformanceEx protocol and Performance Protocol are not located to log performance.
 
 **/
 EFI_STATUS
-GetPerformanceProtocol (
+GetPerformanceMeasurementProtocol (
   VOID
   )
 {
   EFI_STATUS                Status;
-  PERFORMANCE_PROTOCOL      *Performance;
-  PERFORMANCE_EX_PROTOCOL   *PerformanceEx;
+  EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL   *PerformanceMeasurement;
 
-  if (mPerformanceEx != NULL || mPerformance != NULL) {
+  if (mPerformanceMeasurement != NULL) {
     return EFI_SUCCESS;
   }
 
-  Status = gSmst->SmmLocateProtocol (&gSmmPerformanceExProtocolGuid, NULL, (VOID **) &PerformanceEx);
+  Status = gSmst->SmmLocateProtocol (&gEdkiiSmmPerformanceMeasurementProtocolGuid, NULL, (VOID **) &PerformanceMeasurement);
   if (!EFI_ERROR (Status)) {
-    ASSERT (PerformanceEx != NULL);
+    ASSERT (PerformanceMeasurement != NULL);
     //
-    // Cache PerformanceEx Protocol.
+    // Cache PerformanceMeasurement Protocol.
     //
-    mPerformanceEx = PerformanceEx;
+    mPerformanceMeasurement = PerformanceMeasurement;
     return EFI_SUCCESS;
   }
-
-  Status = gSmst->SmmLocateProtocol (&gSmmPerformanceProtocolGuid, NULL, (VOID **) &Performance);
-  if (!EFI_ERROR (Status)) {
-    ASSERT (Performance != NULL);
-    //
-    // Cache performance protocol.
-    //
-    mPerformance = Performance;
-    return EFI_SUCCESS;
-  }
-
   return EFI_NOT_FOUND;
 }
 
 /**
   Creates a record for the beginning of a performance measurement.
@@ -130,21 +116,28 @@ StartPerformanceMeasurementEx (
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp,
   IN UINT32       Identifier
   )
 {
-  EFI_STATUS  Status;
+  EFI_STATUS    Status;
+  CONST CHAR8*  String;
 
-  Status = GetPerformanceProtocol ();
+  Status = GetPerformanceMeasurementProtocol ();
   if (EFI_ERROR (Status)) {
-    return RETURN_OUT_OF_RESOURCES;
+    return RETURN_NOT_FOUND;
   }
 
-  if (mPerformanceEx != NULL) {
-    Status = mPerformanceEx->StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
-  } else if (mPerformance != NULL) {
-    Status = mPerformance->StartGauge (Handle, Token, Module, TimeStamp);
+  if (Token != NULL) {
+    String = Token;
+  } else if (Module != NULL) {
+    String = Module;
+  } else {
+    String = NULL;
+  }
+
+  if (mPerformanceMeasurement != NULL) {
+    Status = mPerformanceMeasurement->CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);
   } else {
     ASSERT (FALSE);
   }
 
   return (RETURN_STATUS) Status;
@@ -182,21 +175,28 @@ EndPerformanceMeasurementEx (
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp,
   IN UINT32       Identifier
   )
 {
-  EFI_STATUS  Status;
+  EFI_STATUS    Status;
+  CONST CHAR8*  String;
 
-  Status = GetPerformanceProtocol ();
+  Status = GetPerformanceMeasurementProtocol ();
   if (EFI_ERROR (Status)) {
     return RETURN_NOT_FOUND;
   }
 
-  if (mPerformanceEx != NULL) {
-    Status = mPerformanceEx->EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
-  } else if (mPerformance != NULL) {
-    Status = mPerformance->EndGauge (Handle, Token, Module, TimeStamp);
+  if (Token != NULL) {
+    String = Token;
+  } else if (Module != NULL) {
+    String = Module;
+  } else {
+    String = NULL;
+  }
+
+  if (mPerformanceMeasurement != NULL) {
+    Status = mPerformanceMeasurement->CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);
   } else {
     ASSERT (FALSE);
   }
 
   return (RETURN_STATUS) Status;
@@ -253,62 +253,11 @@ GetPerformanceMeasurementEx (
   OUT UINT64      *StartTimeStamp,
   OUT UINT64      *EndTimeStamp,
   OUT UINT32      *Identifier
   )
 {
-  EFI_STATUS            Status;
-  GAUGE_DATA_ENTRY_EX   *GaugeData;
-
-  GaugeData = NULL;
-
-  ASSERT (Handle != NULL);
-  ASSERT (Token != NULL);
-  ASSERT (Module != NULL);
-  ASSERT (StartTimeStamp != NULL);
-  ASSERT (EndTimeStamp != NULL);
-  ASSERT (Identifier != NULL);
-
-  Status = GetPerformanceProtocol ();
-  if (EFI_ERROR (Status)) {
-    return 0;
-  }
-
-  if (mPerformanceEx != NULL) {
-    Status = mPerformanceEx->GetGaugeEx (LogEntryKey++, &GaugeData);
-  } else if (mPerformance != NULL) {
-    Status = mPerformance->GetGauge (LogEntryKey++, (GAUGE_DATA_ENTRY **) &GaugeData);
-  } else {
-    ASSERT (FALSE);
-    return 0;
-  }
-
-  //
-  // Make sure that LogEntryKey is a valid log entry key,
-  //
-  ASSERT (Status != EFI_INVALID_PARAMETER);
-
-  if (EFI_ERROR (Status)) {
-    //
-    // The LogEntryKey is the last entry (equals to the total entry number).
-    //
-    return 0;
-  }
-
-  ASSERT (GaugeData != NULL);
-
-  *Handle         = (VOID *) (UINTN) GaugeData->Handle;
-  *Token          = GaugeData->Token;
-  *Module         = GaugeData->Module;
-  *StartTimeStamp = GaugeData->StartTimeStamp;
-  *EndTimeStamp   = GaugeData->EndTimeStamp;
-  if (mPerformanceEx != NULL) {
-    *Identifier   = GaugeData->Identifier;
-  } else {
-    *Identifier   = 0;
-  }
-
-  return LogEntryKey;
+  return 0;
 }
 
 /**
   Creates a record for the beginning of a performance measurement.
 
@@ -423,12 +372,11 @@ GetPerformanceMeasurement (
   OUT CONST CHAR8 **Module,
   OUT UINT64      *StartTimeStamp,
   OUT UINT64      *EndTimeStamp
   )
 {
-  UINT32 Identifier;
-  return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);
+  return 0;
 }
 
 /**
   Returns TRUE if the performance measurement macros are enabled.
 
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
index c3d01a1e51d..174ed3f1e59 100644
--- a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
+++ b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
@@ -4,11 +4,11 @@
 #  This library instance provides infrastructure for SMM drivers to log performance
 #  data. It consumes SMM PerformanceEx or Performance Protocol published by SmmCorePerformanceLib
 #  to log performance data. If both SMM PerformanceEx and Performance Protocol are not available,
 #  it does not log any performance information.
 #  
-#  Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD License
 #  which accompanies this distribution.  The full text of the license may be found at
 #  http://opensource.org/licenses/bsd-license.php
 #  
@@ -48,10 +48,9 @@
   SmmServicesTableLib
   DebugLib
   BaseMemoryLib
 
 [Guids]
-  gSmmPerformanceProtocolGuid           ## SOMETIMES_CONSUMES   ## UNDEFINED # Locate protocol
-  gSmmPerformanceExProtocolGuid         ## SOMETIMES_CONSUMES   ## UNDEFINED # Locate protocol
+  gEdkiiSmmPerformanceMeasurementProtocolGuid          ## SOMETIMES_CONSUMES   ## UNDEFINED # Locate protocol
 
 [Pcd]
   gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask    ## CONSUMES
-- 
2.14.3.windows.1



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch V2 3/9] MdePkg/PerformanceLib.h: Add new Perf macros
  2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
  2018-06-22  8:56 ` [patch V2 1/9] MdeModulePkg: Add PERFORMANCE_MEASUREMENT_PROTOCOL Dandan Bi
  2018-06-22  8:56 ` [patch V2 2/9] MdeModulePkg: Update Performance instances to use new protocol Dandan Bi
@ 2018-06-22  8:56 ` Dandan Bi
  2018-06-22  8:56 ` [patch V2 4/9] MdeModulePkg/ExtendedFirmwarePerf: Remove PerfId definitions Dandan Bi
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Dandan Bi @ 2018-06-22  8:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Michael Kinney

1. Add new Perf macros for performance measurement
and related APIs and definitions in Performance
library class.

2. Update NULL performance library instance in MdePkg.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 MdePkg/Include/Library/PerformanceLib.h            | 408 ++++++++++++++++++++-
 .../BasePerformanceLibNull/PerformanceLib.c        |  57 ++-
 MdePkg/MdePkg.dec                                  |   9 +-
 MdePkg/MdePkg.uni                                  |   6 +
 4 files changed, 477 insertions(+), 3 deletions(-)

diff --git a/MdePkg/Include/Library/PerformanceLib.h b/MdePkg/Include/Library/PerformanceLib.h
index 3ecd62bd201..8a8f5e3694a 100644
--- a/MdePkg/Include/Library/PerformanceLib.h
+++ b/MdePkg/Include/Library/PerformanceLib.h
@@ -1,9 +1,9 @@
 /** @file
   Provides services to log the execution times and retrieve them later.
 
-Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
 http://opensource.org/licenses/bsd-license.php
 
@@ -18,10 +18,49 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 ///
 /// Performance library propery mask bits
 ///
 #define PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED  0x00000001
 
+//
+// Public Progress Identifiers for Event Records.
+//
+#define PERF_EVENT_ID                   0x00
+
+#define MODULE_START_ID                 0x01
+#define MODULE_END_ID                   0x02
+#define MODULE_LOADIMAGE_START_ID       0x03
+#define MODULE_LOADIMAGE_END_ID         0x04
+#define MODULE_DB_START_ID              0x05
+#define MODULE_DB_END_ID                0x06
+#define MODULE_DB_SUPPORT_START_ID      0x07
+#define MODULE_DB_SUPPORT_END_ID        0x08
+#define MODULE_DB_STOP_START_ID         0x09
+#define MODULE_DB_STOP_END_ID           0x0A
+
+#define PERF_EVENTSIGNAL_START_ID       0x10
+#define PERF_EVENTSIGNAL_END_ID         0x11
+#define PERF_CALLBACK_START_ID          0x20
+#define PERF_CALLBACK_END_ID            0x21
+#define PERF_FUNCTION_START_ID          0x30
+#define PERF_FUNCTION_END_ID            0x31
+#define PERF_INMODULE_START_ID          0x40
+#define PERF_INMODULE_END_ID            0x41
+#define PERF_CROSSMODULE_START_ID       0x50
+#define PERF_CROSSMODULE_END_ID         0x51
+
+//
+// Declare bits for PcdPerformanceLibraryPropertyMask and
+// also used as the Type parameter of LogPerformanceMeasurementEnabled().
+//
+#define PERF_CORE_START_IMAGE            0x0002
+#define PERF_CORE_LOAD_IMAGE             0x0004
+#define PERF_CORE_DB_SUPPORT             0x0008
+#define PERF_CORE_DB_START               0x0010
+#define PERF_CORE_DB_STOP                0x0020
+
+#define PERF_GENERAL_TYPE                0x0040
+
 /**
   Creates a record for the beginning of a performance measurement. 
   
   Creates a record that contains the Handle, Token, and Module.
   If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
@@ -269,10 +308,377 @@ BOOLEAN
 EFIAPI
 PerformanceMeasurementEnabled (
   VOID
   );
 
+
+/**
+  Check whether the specified performance measurement can be logged.
+
+  This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+  and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+  @param Type        - Type of the performance measurement entry.
+
+  @retval TRUE         The performance measurement can be logged.
+  @retval FALSE        The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+  IN  CONST UINTN        Type
+  );
+
+/**
+  Create performance record with event description.
+
+  @param CallerIdentifier - Image handle or pointer to caller ID GUID
+  @param Guid             - Pointer to a GUID.
+                            Used for event signal perf and callback perf to cache the event guid.
+  @param String           - Pointer to a string describing the measurement
+  @param Address          - Pointer to a location in memory relevant to the measurement.
+  @param Identifier       - Performance identifier describing the type of measurement.
+
+  @retval RETURN_SUCCESS           - Successfully created performance record
+  @retval RETURN_OUT_OF_RESOURCES  - Ran out of space to store the records
+  @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                     pointer or invalid Identifier.
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+  IN CONST VOID   *CallerIdentifier, OPTIONAL
+  IN CONST VOID   *Guid,    OPTIONAL
+  IN CONST CHAR8  *String,  OPTIONAL
+  IN UINT64       Address,  OPTIONAL
+  IN UINT32       Identifier
+  );
+
+/**
+  Begin Macro to measure the performance of StartImage in core.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT1(dsiable PERF_CORE_START_IMAGE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_START_IMAGE_BEGIN(ModuleHandle) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_CORE_START_IMAGE)) { \
+      LogPerformanceMeasurement (ModuleHandle, NULL, NULL, 0, MODULE_START_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  End Macro to measure the performance of StartImage in core.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT1 (dsiable PERF_CORE_START_IMAGE)of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_START_IMAGE_END(ModuleHandle) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_CORE_START_IMAGE)) { \
+      LogPerformanceMeasurement (ModuleHandle, NULL, NULL, 0, MODULE_END_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  Begin Macro to measure the performance of LoadImage in core.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT2 (dsiable PERF_CORE_LOAD_IAMGE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_LOAD_IMAGE_BEGIN(ModuleHandle) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_CORE_LOAD_IMAGE)) { \
+      LogPerformanceMeasurement (ModuleHandle, NULL, NULL, 0, MODULE_LOADIMAGE_START_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  End Macro to measure the performance of LoadImage in core.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT2 (dsiable PERF_CORE_LOAD_IAMGE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_LOAD_IMAGE_END(ModuleHandle) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_CORE_LOAD_IMAGE)) { \
+      LogPerformanceMeasurement (ModuleHandle, NULL, NULL, 0, MODULE_LOADIMAGE_END_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  Start Macro to measure the performance of DriverBinding Support in core.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT3 (dsiable PERF_CORE_DB_SUPPORT) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_DRIVER_BINDING_SUPPORT_BEGIN(ModuleHandle, ControllerHandle) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_SUPPORT)) { \
+      LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_SUPPORT_START_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  End Macro to measure the performance of DriverBinding Support in core.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT3 (dsiable PERF_CORE_DB_SUPPORT) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_DRIVER_BINDING_SUPPORT_END(ModuleHandle, ControllerHandle) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_SUPPORT)) { \
+      LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_SUPPORT_END_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  Begin Macro to measure the performance of DriverBinding Start in core.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT4 (dsiable PERF_CORE_DB_START) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_DRIVER_BINDING_START_BEGIN(ModuleHandle, ControllerHandle) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_START)) { \
+      LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_START_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  End Macro to measure the performance of DriverBinding Start in core.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT4 (dsiable PERF_CORE_DB_START) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_DRIVER_BINDING_START_END(ModuleHandle, ControllerHandle) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_START)) { \
+      LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_END_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  Start Macro to measure the performance of DriverBinding Stop in core.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT5 (dsiable PERF_CORE_DB_STOP) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_DRIVER_BINDING_STOP_BEGIN(ModuleHandle, ControllerHandle) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_STOP)) { \
+      LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_STOP_START_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  End Macro to measure the performance of DriverBinding Stop in core.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT5 (dsiable PERF_CORE_DB_STOP) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_DRIVER_BINDING_STOP_END(ModuleHandle, ControllerHandle) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_STOP)) { \
+      LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_STOP_END_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  Macro to measure the time from power-on to this macro execution.
+  It can be used to log a meaningful thing which happens at a time point.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_EVENT(EventString) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, EventString , 0, PERF_EVENT_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  Begin Macro to measure the perofrmance of evnent signal behavior in any module.
+  The event guid will be passed with this macro.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_EVENT_SIGNAL_BEGIN(EventGuid) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, EventGuid, __FUNCTION__ , 0, PERF_EVENTSIGNAL_START_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  End Macro to measure the perofrmance of evnent signal behavior in any module.
+  The event guid will be passed with this macro.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_EVENT_SIGNAL_END(EventGuid) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, EventGuid, __FUNCTION__ , 0, PERF_EVENTSIGNAL_END_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  Begin Macro to measure the perofrmance of a callback function in any module.
+  The event guid which trigger the callback function will be passed with this macro.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_CALLBACK_BEGIN(TriggerGuid) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, TriggerGuid, __FUNCTION__ , 0, PERF_CALLBACK_START_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  End Macro to measure the perofrmance of a callback function in any module.
+  The event guid which trigger the callback function will be passed with this macro.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_CALLBACK_END(TriggerGuid) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, TriggerGuid, __FUNCTION__ , 0, PERF_CALLBACK_END_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  Begin Macro to measure the perofrmance of a general function in any module.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_FUNCTION_BEGIN() \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, __FUNCTION__ , 0, PERF_FUNCTION_START_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  End Macro to measure the perofrmance of a general function in any module.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_FUNCTION_END() \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, __FUNCTION__ , 0, PERF_FUNCTION_END_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  Begin Macro to measure the perofrmance of a behavior within one module.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_INMODULE_BEGIN(MeasurementString) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, MeasurementString, 0, PERF_INMODULE_START_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  End Macro to measure the perofrmance of a behavior within one module.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_INMODULE_END(MeasurementString) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, MeasurementString, 0, PERF_INMODULE_END_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  Begin Macro to measure the perofrmance of a behavior in different modules.
+  Such as the performance of PEI phase, DXE phase, BDS phase.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_CROSSMODULE_BEGIN(MeasurementString) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, MeasurementString, 0, PERF_CROSSMODULE_START_ID); \
+    } \
+  } while (FALSE)
+
+/**
+  End Macro to measure the perofrmance of a behavior in different modules.
+  Such as the performance of PEI phase, DXE phase, BDS phase.
+
+  If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
+  and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set.
+  then LogPerformanceMeasurement() is called.
+
+**/
+#define PERF_CROSSMODULE_END(MeasurementString) \
+  do { \
+    if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \
+      LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, MeasurementString, 0, PERF_CROSSMODULE_END_ID); \
+    } \
+  } while (FALSE)
+
 /**
   Macro that calls EndPerformanceMeasurement().
 
   If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set,
   then EndPerformanceMeasurement() is called.
diff --git a/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c b/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c
index e35235d9a29..a68ea90d4f0 100644
--- a/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c
+++ b/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c
@@ -1,9 +1,9 @@
 /** @file
   Base Performance Library which provides no service.
 
-  Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD License
   which accompanies this distribution.  The full text of the license may be found at
   http://opensource.org/licenses/bsd-license.php.
 
@@ -302,5 +302,60 @@ PerformanceMeasurementEnabled (
   VOID
   )
 {
   return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
 }
+
+/**
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID
+  @param Guid              - Pointer to a GUID
+  @param String            - Pointer to a string describing the measurement
+  @param Address           - Pointer to a location in memory relevant to the measurement
+  @param Identifier        - Performance identifier describing the type of measurement
+
+  @retval RETURN_SUCCESS           - Successfully created performance record
+  @retval RETURN_OUT_OF_RESOURCES  - Ran out of space to store the records
+  @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                     pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+  IN CONST VOID   *CallerIdentifier,OPTIONAL
+  IN CONST VOID   *Guid,    OPTIONAL
+  IN CONST CHAR8  *String,  OPTIONAL
+  IN UINT64       Address,  OPTIONAL
+  IN UINT32       Identifier
+  )
+{
+  return RETURN_SUCCESS;
+}
+
+/**
+  Check whether the specified performance measurement can be logged.
+
+  This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+  and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+  @param Type        - Type of the performance measurement entry.
+
+  @retval TRUE         The performance measurement can be logged.
+  @retval FALSE        The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+  IN  CONST UINTN        Type
+  )
+{
+  //
+  // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+  //
+  if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+    return TRUE;
+  }
+  return FALSE;
+}
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 0e64f22f4a7..432de804c5d 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -2167,12 +2167,19 @@
   # @Prompt Value to Clear Memory.
   gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF|UINT8|0x00000008
 
   ## The mask is used to control PerformanceLib behavior.<BR><BR>
   #  BIT0 - Enable Performance Measurement.<BR>
+  #  BIT1 - Disable Start Image Logging.<BR>
+  #  BIT2 - Disable Load Image logging.<BR>
+  #  BIT3 - Disable Binding Support logging.<BR>
+  #  BIT4 - Disable Binding Start logging.<BR>
+  #  BIT5 - Disable Binding Stop logging.<BR>
+  #  BIT6 - Disable all other general Perfs.<BR>
+  #  BIT1-BIT6 are evaluated when BIT0 is set.<BR>
   # @Prompt Performance Measurement Property.
-  # @Expression  0x80000002 | (gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask & 0xFE) == 0
+  # @Expression  0x80000002 | (gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask & 0x80) == 0
   gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0|UINT8|0x00000009
 
   ## The mask is used to control PostCodeLib behavior.<BR><BR>
   #  BIT0 - Enable Post Code.<BR>
   #  BIT1 - Enable Post Code with Description.<BR>
diff --git a/MdePkg/MdePkg.uni b/MdePkg/MdePkg.uni
index a110e453df8..18bb01f2199 100644
--- a/MdePkg/MdePkg.uni
+++ b/MdePkg/MdePkg.uni
@@ -243,10 +243,16 @@
 
 #string STR_gEfiMdePkgTokenSpaceGuid_PcdPerformanceLibraryPropertyMask_PROMPT  #language en-US "Performance Measurement Property"
 
 #string STR_gEfiMdePkgTokenSpaceGuid_PcdPerformanceLibraryPropertyMask_HELP  #language en-US "The mask is used to control PerformanceLib behavior.<BR><BR>\n"
                                                                                              "BIT0 - Enable Performance Measurement.<BR>"
+                                                                                             "BIT1 - Disable Start Image Logging.<BR>"
+                                                                                             "BIT2 - Disable Load Image logging.<BR>"
+                                                                                             "BIT3 - Disable Binding Support logging.<BR>"
+                                                                                             "BIT4 - Disable Binding Start logging.<BR>"
+                                                                                             "BIT5 - Disable Binding Stop logging.<BR>"
+                                                                                             "BIT6 - Disable all other general Perfs.<BR>"
 
 #string STR_gEfiMdePkgTokenSpaceGuid_PcdPostCodePropertyMask_PROMPT  #language en-US "Post Code Property"
 
 #string STR_gEfiMdePkgTokenSpaceGuid_PcdPostCodePropertyMask_HELP  #language en-US "The mask is used to control PostCodeLib behavior.<BR><BR>\n"
                                                                                    "BIT0 - Enable Post Code.<BR>\n"
-- 
2.14.3.windows.1



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch V2 4/9] MdeModulePkg/ExtendedFirmwarePerf: Remove PerfId definitions
  2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
                   ` (2 preceding siblings ...)
  2018-06-22  8:56 ` [patch V2 3/9] MdePkg/PerformanceLib.h: Add new Perf macros Dandan Bi
@ 2018-06-22  8:56 ` Dandan Bi
  2018-06-22  8:56 ` [patch V2 5/9] MdeModulePkg: Update performance library instances Dandan Bi
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Dandan Bi @ 2018-06-22  8:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Star Zeng

Remove the definitions of performance identifier since they
have been added into PerformanceLib.h.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 .../Include/Guid/ExtendedFirmwarePerformance.h     | 25 ----------------------
 1 file changed, 25 deletions(-)

diff --git a/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h b/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h
index f2db02ddf49..465b4082750 100644
--- a/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h
+++ b/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h
@@ -30,35 +30,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define DRIVERBINDING_STOP_TOK          "DB:Stop:"        ///< Driver Binding Stop() function call
 #define LOAD_IMAGE_TOK                  "LoadImage:"      ///< Load a dispatched module
 #define START_IMAGE_TOK                 "StartImage:"     ///< Dispatched Modules Entry Point execution
 #define PEIM_TOK                        "PEIM"            ///< PEIM Modules Entry Point execution
 
-//
-// Public Progress Identifiers for Event Records to map the above known token
-//
-#define MODULE_START_ID                 0x01
-#define MODULE_END_ID                   0x02
-#define MODULE_LOADIMAGE_START_ID       0x03
-#define MODULE_LOADIMAGE_END_ID         0x04
-#define MODULE_DB_START_ID              0x05
-#define MODULE_DB_END_ID                0x06
-#define MODULE_DB_SUPPORT_START_ID      0x07
-#define MODULE_DB_SUPPORT_END_ID        0x08
-#define MODULE_DB_STOP_START_ID         0x09
-#define MODULE_DB_STOP_END_ID           0x0A
-
-#define PERF_EVENTSIGNAL_START_ID       0x10
-#define PERF_EVENTSIGNAL_END_ID         0x11
-#define PERF_CALLBACK_START_ID          0x20
-#define PERF_CALLBACK_END_ID            0x21
-#define PERF_FUNCTION_START_ID          0x30
-#define PERF_FUNCTION_END_ID            0x31
-#define PERF_INMODULE_START_ID          0x40
-#define PERF_INMODULE_END_ID            0x41
-#define PERF_CROSSMODULE_START_ID       0x50
-#define PERF_CROSSMODULE_END_ID         0x51
-
 //
 // Misc defines
 //
 #define FPDT_RECORD_REVISION_1      (0x01)
 
-- 
2.14.3.windows.1



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch V2 5/9] MdeModulePkg: Update performance library instances
  2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
                   ` (3 preceding siblings ...)
  2018-06-22  8:56 ` [patch V2 4/9] MdeModulePkg/ExtendedFirmwarePerf: Remove PerfId definitions Dandan Bi
@ 2018-06-22  8:56 ` Dandan Bi
  2018-06-22  8:56 ` [patch V2 6/9] ShellPkg/dp: Update dp tool to parse new Perf record Dandan Bi
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Dandan Bi @ 2018-06-22  8:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Star Zeng

Update the performance library instances in MdeModulePkg
to implement the APIs used for new added Perf macros.

V2:
Share the common logics of creating FPDT record for
new added Perf macros and existing Perf macros.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 .../Include/Guid/ExtendedFirmwarePerformance.h     |   6 -
 .../DxeCorePerformanceLib/DxeCorePerformanceLib.c  | 864 +++++++++++++++------
 .../DxeCorePerformanceLib.inf                      |   1 +
 .../DxeCorePerformanceLibInternal.h                |   1 +
 .../Library/DxePerformanceLib/DxePerformanceLib.c  |  68 ++
 .../Library/PeiPerformanceLib/PeiPerformanceLib.c  | 632 +++++++++------
 .../SmmCorePerformanceLib/SmmCorePerformanceLib.c  | 645 +++++++++------
 .../Library/SmmPerformanceLib/SmmPerformanceLib.c  |  68 ++
 8 files changed, 1565 insertions(+), 720 deletions(-)

diff --git a/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h b/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h
index 465b4082750..dedb0b82f0d 100644
--- a/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h
+++ b/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h
@@ -218,16 +218,10 @@ typedef struct {
   CHAR8                                       String[0];
 } FPDT_GUID_QWORD_STRING_EVENT_RECORD;
 
 #pragma pack()
 
-typedef struct {
-  UINT16                                      ProgressID;
-  UINT16                                      Type;
-  UINT8                                       RecordSize;
-} FPDT_BASIC_RECORD_INFO;
-
 //
 // Union of all FPDT records
 //
 typedef union {
   EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER  RecordHeader;
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
index 79820605184..efff5134c7b 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
@@ -69,17 +69,19 @@ UINTN           mCachePairCount = 0;
 UINT32  mLoadImageCount       = 0;
 UINT32  mPerformanceLength    = 0;
 UINT32  mMaxPerformanceLength = 0;
 UINT32  mBootRecordSize       = 0;
 UINT32  mBootRecordMaxSize    = 0;
+UINT32  mCachedLength         = 0;
 
 BOOLEAN mFpdtBufferIsReported = FALSE;
 BOOLEAN mLackSpaceIsReported  = FALSE;
 CHAR8   *mPlatformLanguage    = NULL;
 UINT8   *mPerformancePointer  = NULL;
 UINT8   *mBootRecordBuffer    = NULL;
 BOOLEAN  mLockInsertRecord    = FALSE;
+CHAR8   *mDevicePathString    = NULL;
 
 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL  *mDevicePathToText = NULL;
 
 //
 // Interfaces for PerformanceMeasurement Protocol.
@@ -88,10 +90,64 @@ EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
   CreatePerformanceMeasurement,
   };
 
 PERFORMANCE_PROPERTY  mPerformanceProperty;
 
+/**
+  Return the pointer to the FPDT record in the allocated memory.
+
+  @param  RecordSize             The size of FPDT record.
+  @param  FpdtRecordPtr          Pointer the FPDT record in the allocated memory.
+
+  @retval EFI_SUCCESS            Successfully get the pointer to the FPDT record.
+  @retval EFI_OUT_OF_RESOURCES   Ran out of space to store the records.
+**/
+EFI_STATUS
+GetFpdtRecordPtr (
+  IN     UINT8               RecordSize,
+  IN OUT FPDT_RECORD_PTR     *FpdtRecordPtr
+)
+{
+  if (mFpdtBufferIsReported) {
+    //
+    // Append Boot records to the boot performance table.
+    //
+    if (mBootRecordSize + RecordSize > mBootRecordMaxSize) {
+      if (!mLackSpaceIsReported) {
+        DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save boot records\n"));
+        mLackSpaceIsReported = TRUE;
+      }
+      return EFI_OUT_OF_RESOURCES;
+    } else {
+      //
+      // Save boot record into BootPerformance table
+      //
+      FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mBootRecordSize);
+    }
+  } else {
+    //
+    // Check if pre-allocated buffer is full
+    //
+    if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {
+      mPerformancePointer = ReallocatePool (
+                              mPerformanceLength,
+                              mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER,
+                              mPerformancePointer
+                              );
+      if (mPerformancePointer == NULL) {
+         return EFI_OUT_OF_RESOURCES;
+       }
+      mMaxPerformanceLength = mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER;
+    }
+    //
+    // Covert buffer to FPDT Ptr Union type.
+    //
+    FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mPerformanceLength);
+  }
+  return EFI_SUCCESS;
+}
+
 /**
 Check whether the Token is a known one which is uesed by core.
 
 @param  Token      Pointer to a Null-terminated ASCII string
 
@@ -585,282 +641,355 @@ Done:
 
   return Status;
 }
 
 /**
-  Get the FPDT record info.
+  Get the FPDT record identifier.
 
-  @param  IsStart                 TRUE if the performance log is start log.
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  RecordInfo              On return, pointer to the info of the record.
-  @param  UseModuleName           Only useful for FPDT_DYNAMIC_STRING_EVENT_TYPE, indicate that whether need use
-                                  Module name to fill the string field in the FPDT_DYNAMIC_STRING_EVENT_RECORD.
+  @param Attribute                The attribute of the Record.
+                                  PerfStartEntry: Start Record.
+                                  PerfEndEntry: End Record.
+  @param  Handle                  Pointer to environment specific context used to identify the component being measured.
+  @param  String                  Pointer to a Null-terminated ASCII string that identifies the component being measured.
+  @param  ProgressID              On return, pointer to the ProgressID.
 
-  @retval EFI_SUCCESS          Get record info successfully.
-  @retval EFI_UNSUPPORTED      No matched FPDT record.
+  @retval EFI_SUCCESS              Get record info successfully.
+  @retval EFI_INVALID_PARAMETER    No matched FPDT record.
 
 **/
 EFI_STATUS
-GetFpdtRecordInfo (
-  IN BOOLEAN                  IsStart,
-  IN CONST VOID               *Handle,
-  IN CONST CHAR8              *Token,
-  IN CONST CHAR8              *Module,
-  OUT FPDT_BASIC_RECORD_INFO  *RecordInfo,
-  IN OUT BOOLEAN              *UseModuleName
+GetFpdtRecordId (
+  IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute,
+  IN CONST VOID                       *Handle,
+  IN CONST CHAR8                      *String,
+  OUT UINT16                          *ProgressID
   )
 {
-  UINT16              RecordType;
-  UINTN               StringSize;
-
-  RecordType    = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-
   //
-  // Token to Type and Id.
+  // Token to PerfId.
   //
-  if (Token != NULL) {
-    if (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) {                // "StartImage:"
-      *UseModuleName = TRUE;
-      RecordType     = FPDT_GUID_EVENT_TYPE;
-      if (IsStart) {
-        RecordInfo->ProgressID  = MODULE_START_ID;
+  if (String != NULL) {
+    if (AsciiStrCmp (String, START_IMAGE_TOK) == 0) {                // "StartImage:"
+      if (Attribute == PerfStartEntry) {
+        *ProgressID  = MODULE_START_ID;
       } else {
-        RecordInfo->ProgressID  = MODULE_END_ID;
+        *ProgressID  = MODULE_END_ID;
       }
-    } else if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) {          // "LoadImage:"
-      *UseModuleName = TRUE;
-      RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
-      if (IsStart) {
-        RecordInfo->ProgressID  = MODULE_LOADIMAGE_START_ID;
+    } else if (AsciiStrCmp (String, LOAD_IMAGE_TOK) == 0) {          // "LoadImage:"
+      if (Attribute == PerfStartEntry) {
+        *ProgressID  = MODULE_LOADIMAGE_START_ID;
       } else {
-        RecordInfo->ProgressID  = MODULE_LOADIMAGE_END_ID;
+        *ProgressID  = MODULE_LOADIMAGE_END_ID;
       }
-    } else if (AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0) {  // "DB:Start:"
-      *UseModuleName = TRUE;
-      if (IsStart) {
-        RecordInfo->ProgressID  = MODULE_DB_START_ID;
-        RecordType   = FPDT_GUID_QWORD_EVENT_TYPE;
+    } else if (AsciiStrCmp (String, DRIVERBINDING_START_TOK) == 0) {  // "DB:Start:"
+      if (Attribute == PerfStartEntry) {
+        *ProgressID  = MODULE_DB_START_ID;
       } else {
-        RecordInfo->ProgressID  = MODULE_DB_END_ID;
-        RecordType   = FPDT_GUID_QWORD_STRING_EVENT_TYPE;
+        *ProgressID  = MODULE_DB_END_ID;
       }
-    } else if (AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0) { // "DB:Support:"
-      *UseModuleName = TRUE;
+    } else if (AsciiStrCmp (String, DRIVERBINDING_SUPPORT_TOK) == 0) { // "DB:Support:"
       if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
         return RETURN_UNSUPPORTED;
       }
-      RecordType     = FPDT_GUID_QWORD_EVENT_TYPE;
-      if (IsStart) {
-        RecordInfo->ProgressID  = MODULE_DB_SUPPORT_START_ID;
+      if (Attribute == PerfStartEntry) {
+        *ProgressID  = MODULE_DB_SUPPORT_START_ID;
       } else {
-        RecordInfo->ProgressID  = MODULE_DB_SUPPORT_END_ID;
+        *ProgressID  = MODULE_DB_SUPPORT_END_ID;
       }
-    } else if (AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0) {    // "DB:Stop:"
-      *UseModuleName = TRUE;
+    } else if (AsciiStrCmp (String, DRIVERBINDING_STOP_TOK) == 0) {    // "DB:Stop:"
       if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
          return RETURN_UNSUPPORTED;
       }
-      RecordType     = FPDT_GUID_QWORD_EVENT_TYPE;
-      if (IsStart) {
-        RecordInfo->ProgressID  = MODULE_DB_STOP_START_ID;
+      if (Attribute == PerfStartEntry) {
+        *ProgressID  = MODULE_DB_STOP_START_ID;
       } else {
-        RecordInfo->ProgressID  = MODULE_DB_STOP_END_ID;
+        *ProgressID  = MODULE_DB_STOP_END_ID;
       }
-    } else if (AsciiStrCmp (Token, PEI_TOK) == 0 ||                   // "PEI"
-               AsciiStrCmp (Token, DXE_TOK) == 0 ||                   // "DXE"
-               AsciiStrCmp (Token, BDS_TOK) == 0) {                   // "BDS"
-      if (IsStart) {
-        RecordInfo->ProgressID  = PERF_CROSSMODULE_START_ID;
+    } else if (AsciiStrCmp (String, PEI_TOK) == 0 ||                   // "PEI"
+               AsciiStrCmp (String, DXE_TOK) == 0 ||                   // "DXE"
+               AsciiStrCmp (String, BDS_TOK) == 0) {                   // "BDS"
+      if (Attribute == PerfStartEntry) {
+        *ProgressID  = PERF_CROSSMODULE_START_ID;
       } else {
-        RecordInfo->ProgressID  = PERF_CROSSMODULE_END_ID;
+        *ProgressID  = PERF_CROSSMODULE_END_ID;
       }
     } else {                                                          // Pref used in Modules.
-      if (IsStart) {
-        RecordInfo->ProgressID  = PERF_INMODULE_START_ID;
+      if (Attribute == PerfStartEntry) {
+        *ProgressID  = PERF_INMODULE_START_ID;
       } else {
-        RecordInfo->ProgressID  = PERF_INMODULE_END_ID;
+        *ProgressID  = PERF_INMODULE_END_ID;
       }
     }
-  } else if (Handle!= NULL || Module != NULL) {                       // Pref used in Modules.
-    if (IsStart) {
-      RecordInfo->ProgressID    = PERF_INMODULE_START_ID;
+  } else if (Handle!= NULL) {                                         // Pref used in Modules.
+    if (Attribute == PerfStartEntry) {
+      *ProgressID    = PERF_INMODULE_START_ID;
     } else {
-      RecordInfo->ProgressID    = PERF_INMODULE_END_ID;
+      *ProgressID    = PERF_INMODULE_END_ID;
     }
   } else {
-    return EFI_UNSUPPORTED;
+    return EFI_INVALID_PARAMETER;
   }
+  return EFI_SUCCESS;
+}
+
+/**
+  Copies the string from Source into Destination and updates Length with the
+  size of the string.
+
+  @param Destination - destination of the string copy
+  @param Source      - pointer to the source string which will get copied
+  @param Length      - pointer to a length variable to be updated
+
+**/
+VOID
+CopyStringIntoPerfRecordAndUpdateLength (
+  IN OUT CHAR8  *Destination,
+  IN     CONST CHAR8  *Source,
+  IN OUT UINT8  *Length
+  )
+{
+  UINTN  StringLen;
+  UINTN  DestMax;
+
+  ASSERT (Source != NULL);
 
-  //
-  // Get Record size baesed on the record type.
-  // When PcdEdkiiFpdtStringRecordEnableOnly is TRUE, all records are with type of FPDT_DYNAMIC_STRING_EVENT_TYPE.
-  //
   if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
-    RecordType               = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-    RecordInfo->RecordSize   = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE;
+    DestMax = STRING_SIZE;
   } else {
-    switch (RecordType) {
-    case FPDT_GUID_EVENT_TYPE:
-      RecordInfo->RecordSize = sizeof (FPDT_GUID_EVENT_RECORD);
-      break;
-
-    case FPDT_DYNAMIC_STRING_EVENT_TYPE:
-      if (*UseModuleName) {
-        StringSize  = STRING_SIZE;
-      } else if (Token  != NULL) {
-        StringSize  = AsciiStrSize (Token);
-      } else if (Module != NULL) {
-        StringSize  = AsciiStrSize (Module);
-      } else {
-        StringSize  = STRING_SIZE;
-      }
-      if (StringSize > STRING_SIZE) {
-        StringSize   = STRING_SIZE;
-      }
-      RecordInfo->RecordSize = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + StringSize);
-      break;
+    DestMax = AsciiStrSize (Source);
+    if (DestMax > STRING_SIZE) {
+      DestMax = STRING_SIZE;
+    }
+  }
+  StringLen = AsciiStrLen (Source);
+  if (StringLen >= DestMax) {
+    StringLen = DestMax -1;
+  }
+
+  AsciiStrnCpyS(Destination, DestMax, Source, StringLen);
+  *Length += (UINT8)DestMax;
+
+  return;
+}
+
+/**
+  Get a string description for device for the given controller handle and update record
+  length. If ComponentName2 GetControllerName is supported, the value is included in the string,
+  followed by device path, otherwise just device path.
 
-    case FPDT_GUID_QWORD_EVENT_TYPE:
-      RecordInfo->RecordSize = (UINT8)sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
-      break;
+  @param Handle              - Image handle
+  @param ControllerHandle    - Controller handle.
+  @param ComponentNameString - Pointer to a location where the string will be saved
+  @param Length              - Pointer to record length to be updated
 
-    case FPDT_GUID_QWORD_STRING_EVENT_TYPE:
-      RecordInfo->RecordSize = (UINT8)sizeof (FPDT_GUID_QWORD_STRING_EVENT_RECORD);
-      break;
+  @retval EFI_SUCCESS     - Successfully got string description for device
+  @retval EFI_UNSUPPORTED - Neither ComponentName2 ControllerName nor DevicePath were found
 
-    default:
+**/
+EFI_STATUS
+GetDeviceInfoFromHandleAndUpdateLength (
+  IN CONST VOID        *Handle,
+  IN EFI_HANDLE        ControllerHandle,
+  OUT CHAR8            *ComponentNameString,
+  IN OUT UINT8         *Length
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL      *DevicePathProtocol;
+  EFI_COMPONENT_NAME2_PROTOCOL  *ComponentName2;
+  EFI_STATUS                    Status;
+  CHAR16                        *StringPtr;
+  CHAR8                         *AsciiStringPtr;
+  UINTN                         ControllerNameStringSize;
+  UINTN                         DevicePathStringSize;
+
+  ControllerNameStringSize = 0;
+
+  Status = gBS->HandleProtocol (
+                  (EFI_HANDLE) Handle,
+                  &gEfiComponentName2ProtocolGuid,
+                  (VOID **) &ComponentName2
+                  );
+
+  if (!EFI_ERROR(Status)) {
+    //
+    // Get the current platform language setting
+    //
+    if (mPlatformLanguage == NULL) {
+      GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&mPlatformLanguage, NULL);
+    }
+
+    Status = ComponentName2->GetControllerName (
+                               ComponentName2,
+                               ControllerHandle,
+                               NULL,
+                               mPlatformLanguage != NULL ? mPlatformLanguage : "en-US",
+                               &StringPtr
+                               );
+  }
+
+  if (!EFI_ERROR (Status)) {
+    //
+    // This will produce the size of the unicode string, which is twice as large as the ASCII one
+    // This must be an even number, so ok to divide by 2
+    //
+    ControllerNameStringSize = StrSize(StringPtr) / 2;
+
+    //
+    // The + 1 is because we want to add a space between the ControllerName and the device path
+    //
+    if ((ControllerNameStringSize + (*Length) + 1) > FPDT_MAX_PERF_RECORD_SIZE) {
       //
-      // Record is unsupported yet, return EFI_UNSUPPORTED
+      // Only copy enough to fill FPDT_MAX_PERF_RECORD_SIZE worth of the record
       //
-      return EFI_UNSUPPORTED;
+      ControllerNameStringSize = FPDT_MAX_PERF_RECORD_SIZE - (*Length) - 1;
     }
+
+    UnicodeStrToAsciiStrS(StringPtr, ComponentNameString, ControllerNameStringSize);
+
+    //
+    // Add a space in the end of the ControllerName
+    //
+    AsciiStringPtr = ComponentNameString + ControllerNameStringSize - 1;
+    *AsciiStringPtr = 0x20;
+    AsciiStringPtr++;
+    *AsciiStringPtr = 0;
+    ControllerNameStringSize++;
+
+    *Length += (UINT8)ControllerNameStringSize;
   }
 
-  RecordInfo->Type = RecordType;
-  return EFI_SUCCESS;
+  //
+  // This function returns the device path protocol from the handle specified by Handle.  If Handle is
+  // NULL or Handle does not contain a device path protocol, then NULL is returned.
+  //
+  DevicePathProtocol = DevicePathFromHandle(ControllerHandle);
+
+  if (DevicePathProtocol != NULL) {
+    StringPtr = ConvertDevicePathToText (DevicePathProtocol, TRUE, FALSE);
+    if (StringPtr != NULL) {
+      //
+      // This will produce the size of the unicode string, which is twice as large as the ASCII one
+      // This must be an even number, so ok to divide by 2
+      //
+      DevicePathStringSize = StrSize(StringPtr) / 2;
+
+      if ((DevicePathStringSize + (*Length)) > FPDT_MAX_PERF_RECORD_SIZE) {
+        //
+        // Only copy enough to fill FPDT_MAX_PERF_RECORD_SIZE worth of the record
+        //
+        DevicePathStringSize = FPDT_MAX_PERF_RECORD_SIZE - (*Length);
+      }
+
+      if (ControllerNameStringSize != 0) {
+        AsciiStringPtr = ComponentNameString + ControllerNameStringSize - 1;
+      } else {
+        AsciiStringPtr = ComponentNameString;
+      }
+
+      UnicodeStrToAsciiStrS(StringPtr, AsciiStringPtr, DevicePathStringSize);
+      *Length += (UINT8)DevicePathStringSize;
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_UNSUPPORTED;
 }
 
 /**
-  Add performance log to FPDT boot record table.
+  Create performance record with event description and a timestamp.
 
-  @param  IsStart                 TRUE if the performance log is start log.
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  Ticker                  64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the created record
-                                  is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID.
+  @param Guid              - Pointer to a GUID.
+  @param String            - Pointer to a string describing the measurement.
+  @param Ticker            - 64-bit time stamp.
+  @param Address           - Pointer to a location in memory relevant to the measurement.
+  @param PerfId            - Performance identifier describing the type of measurement.
+  @param Attribute         - The attribute of the measurement. According to attribute can create a start
+                             record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+                             or a general record for other Perf macros.
 
-  @retval EFI_SUCCESS             Add FPDT boot record.
-  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
-  @retval EFI_UNSUPPORTED         No matched FPDT record.
+  @retval EFI_SUCCESS           - Successfully created performance record.
+  @retval EFI_OUT_OF_RESOURCES  - Ran out of space to store the records.
+  @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                  pointer or invalid PerfId.
+
+  @retval EFI_SUCCESS           - Successfully created performance record
+  @retval EFI_OUT_OF_RESOURCES  - Ran out of space to store the records
+  @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                  pointer or invalid PerfId
 
 **/
 EFI_STATUS
-InsertFpdtMeasurement (
-  IN BOOLEAN      IsStart,
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       Ticker,
-  IN UINT32       Identifier
+InsertFpdtRecord (
+  IN CONST VOID                        *CallerIdentifier,  OPTIONAL
+  IN CONST VOID                        *Guid,    OPTIONAL
+  IN CONST CHAR8                       *String,  OPTIONAL
+  IN       UINT64                      Ticker,
+  IN       UINT64                      Address,  OPTIONAL
+  IN       UINT16                      PerfId,
+  IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute
   )
 {
   EFI_GUID                     ModuleGuid;
   CHAR8                        ModuleName[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];
-  EFI_STATUS                   Status;
   FPDT_RECORD_PTR              FpdtRecordPtr;
-  FPDT_BASIC_RECORD_INFO       RecordInfo;
+  FPDT_RECORD_PTR              CachedFpdtRecordPtr;
   UINT64                       TimeStamp;
-  UINTN                        DestMax;
-  UINTN                        StrLength;
   CONST CHAR8                  *StringPtr;
-  BOOLEAN                      UseModuleName;
+  UINTN                        DestMax;
+  UINTN                        StringLen;
+  EFI_STATUS                   Status;
+  UINT16                       ProgressId;
 
   StringPtr     = NULL;
-  UseModuleName = FALSE;
+  ProgressId    = 0;
   ZeroMem (ModuleName, sizeof (ModuleName));
 
   //
-  // Get record info (type, size, ProgressID and Module Guid).
-  //
-  Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo, &UseModuleName);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
-  // !!! Note: If the Perf is not the known Token used in the core but have same
-  // ID with the core Token, this case will not be supported.
-  // And in currtnt usage mode, for the unkown ID, there is a general rule:
-  // If it is start pref: the lower 4 bits of the ID should be 0.
-  // If it is end pref: the lower 4 bits of the ID should not be 0.
-  // If input ID doesn't follow the rule, we will adjust it.
+  // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.
+  //    notes: For other Perf macros (Attribute == PerfEntry), their Id is known.
   //
-  if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
-    return EFI_UNSUPPORTED;
-  } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
-    if (IsStart && ((Identifier & 0x000F) != 0)) {
-      Identifier &= 0xFFF0;
-    } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {
-      Identifier += 1;
-    }
-    RecordInfo.ProgressID = (UINT16)Identifier;
-  }
-
-  if (mFpdtBufferIsReported) {
+  if (Attribute != PerfEntry) {
     //
-    // Append Boot records to the boot performance table.
+    // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.
+    // !!! Note: If the Perf is not the known Token used in the core but have same
+    // ID with the core Token, this case will not be supported.
+    // And in currtnt usage mode, for the unkown ID, there is a general rule:
+    // If it is start pref: the lower 4 bits of the ID should be 0.
+    // If it is end pref: the lower 4 bits of the ID should not be 0.
+    // If input ID doesn't follow the rule, we will adjust it.
     //
-    if (mBootRecordSize + RecordInfo.RecordSize > mBootRecordMaxSize) {
-      if (!mLackSpaceIsReported) {
-        DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save boot records\n"));
-        mLackSpaceIsReported = TRUE;
+    if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+      return EFI_INVALID_PARAMETER;
+    } else if ((PerfId != 0) && (!IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+      if ((Attribute == PerfStartEntry) && ((PerfId & 0x000F) != 0)) {
+        PerfId &= 0xFFF0;
+      } else if ((Attribute == PerfEndEntry) && ((PerfId & 0x000F) == 0)) {
+        PerfId += 1;
       }
-      return EFI_OUT_OF_RESOURCES;
-    } else {
+    } else if (PerfId == 0) {
       //
-      // Save boot record into BootPerformance table
+      // Get ProgressID form the String Token.
       //
-      FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mBootRecordSize);
-      mBootRecordSize += RecordInfo.RecordSize;
-      mAcpiBootPerformanceTable->Header.Length += RecordInfo.RecordSize;
-    }
-  } else {
-    //
-    // Check if pre-allocated buffer is full
-    //
-    if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {
-      mPerformancePointer = ReallocatePool (
-                              mPerformanceLength,
-                              mPerformanceLength + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER,
-                              mPerformancePointer
-                              );
-
-      if (mPerformancePointer == NULL) {
-        return EFI_OUT_OF_RESOURCES;
+      Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &ProgressId);
+      if (EFI_ERROR (Status)) {
+        return Status;
       }
-      mMaxPerformanceLength = mPerformanceLength + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER;
+      PerfId = ProgressId;
     }
-    //
-    // Covert buffer to FPDT Ptr Union type.
-    //
-    FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mPerformanceLength);
-    mPerformanceLength += RecordInfo.RecordSize;
   }
 
   //
-  // Get the TimeStamp.
+  // 2. Get the buffer to store the FPDT record.
+  //
+  Status = GetFpdtRecordPtr (FPDT_MAX_PERF_RECORD_SIZE, &FpdtRecordPtr);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  //3. Get the TimeStamp.
   //
   if (Ticker == 0) {
     Ticker    = GetPerformanceCounter ();
     TimeStamp = GetTimeInNanoSecond (Ticker);
   } else if (Ticker == 1) {
@@ -868,85 +997,252 @@ InsertFpdtMeasurement (
   } else {
     TimeStamp = GetTimeInNanoSecond (Ticker);
   }
 
   //
-  // Get the ModuleName and ModuleGuid form the handle.
-  //
-  GetModuleInfoFromHandle ((EFI_HANDLE *)Handle, ModuleName, sizeof (ModuleName), &ModuleGuid);
-
-  //
-  // Fill in the record information.
+  // 4. Fill in the FPDT record according to different Performance Identifier.
   //
-  switch (RecordInfo.Type) {
-  case FPDT_GUID_EVENT_TYPE:
-    FpdtRecordPtr.GuidEvent->Header.Type                = FPDT_GUID_EVENT_TYPE;
-    FpdtRecordPtr.GuidEvent->Header.Length              = RecordInfo.RecordSize;
-    FpdtRecordPtr.GuidEvent->Header.Revision            = FPDT_RECORD_REVISION_1;
-    FpdtRecordPtr.GuidEvent->ProgressID                 = RecordInfo.ProgressID;
-    FpdtRecordPtr.GuidEvent->Timestamp                  = TimeStamp;
-    CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+  switch (PerfId) {
+  case MODULE_START_ID:
+  case MODULE_END_ID:
+    GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+    StringPtr = ModuleName;
+    //
+    // Cache the offset of start image start record and use to update the start image end record if needed.
+    //
+    if (Attribute == PerfEntry && PerfId == MODULE_START_ID) {
+      if (mFpdtBufferIsReported) {
+        mCachedLength = mBootRecordSize;
+      } else {
+        mCachedLength = mPerformanceLength;
+      }
+    }
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.GuidEvent->Header.Type                = FPDT_GUID_EVENT_TYPE;
+      FpdtRecordPtr.GuidEvent->Header.Length              = sizeof (FPDT_GUID_EVENT_RECORD);
+      FpdtRecordPtr.GuidEvent->Header.Revision            = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.GuidEvent->ProgressID                 = PerfId;
+      FpdtRecordPtr.GuidEvent->Timestamp                  = TimeStamp;
+      CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+      if (CallerIdentifier == NULL && PerfId == MODULE_END_ID && mCachedLength != 0) {
+        if (mFpdtBufferIsReported) {
+          CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mCachedLength);
+        } else {
+          CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mCachedLength);
+        }
+        CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &CachedFpdtRecordPtr.GuidEvent->Guid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+        mCachedLength = 0;
+      }
+    }
     break;
 
-  case FPDT_DYNAMIC_STRING_EVENT_TYPE:
-    FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-    FpdtRecordPtr.DynamicStringEvent->Header.Length     = RecordInfo.RecordSize;
-    FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
-    FpdtRecordPtr.DynamicStringEvent->ProgressID        = RecordInfo.ProgressID;
-    FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
-    CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
-
-    if (UseModuleName) {
-      StringPtr     = ModuleName;
-    } else if (Token != NULL) {
-      StringPtr     = Token;
-    } else if (Module != NULL) {
-      StringPtr     = Module;
-    } else if (ModuleName != NULL) {
-      StringPtr     = ModuleName;
+  case MODULE_LOADIMAGE_START_ID:
+  case MODULE_LOADIMAGE_END_ID:
+    GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+    StringPtr = ModuleName;
+    if (PerfId == MODULE_LOADIMAGE_START_ID) {
+      mLoadImageCount ++;
+      //
+      // Cache the offset of load image start record and use to be updated by the load image end record if needed.
+      //
+      if (CallerIdentifier == NULL && Attribute == PerfEntry) {
+        if (mFpdtBufferIsReported) {
+          mCachedLength = mBootRecordSize;
+        } else {
+          mCachedLength = mPerformanceLength;
+        }
+      }
     }
-    if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {
-      StrLength     = AsciiStrLen (StringPtr);
-      DestMax       = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);
-      if (StrLength >= DestMax) {
-        StrLength   = DestMax -1;
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.GuidQwordEvent->Header.Type           = FPDT_GUID_QWORD_EVENT_TYPE;
+      FpdtRecordPtr.GuidQwordEvent->Header.Length         = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
+      FpdtRecordPtr.GuidQwordEvent->Header.Revision       = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.GuidQwordEvent->ProgressID            = PerfId;
+      FpdtRecordPtr.GuidQwordEvent->Timestamp             = TimeStamp;
+      FpdtRecordPtr.GuidQwordEvent->Qword                 = mLoadImageCount;
+      CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
+      if (PerfId == MODULE_LOADIMAGE_END_ID && mCachedLength != 0) {
+        if (mFpdtBufferIsReported) {
+          CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mCachedLength);
+        } else {
+          CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mCachedLength);
+        }
+        CopyMem (&CachedFpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.GuidQwordEvent->Guid));
+        mCachedLength = 0;
       }
-      AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);
-    } else {
-      AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");
     }
     break;
 
-  case FPDT_GUID_QWORD_EVENT_TYPE:
-    FpdtRecordPtr.GuidQwordEvent->Header.Type           = FPDT_GUID_QWORD_EVENT_TYPE;
-    FpdtRecordPtr.GuidQwordEvent->Header.Length         = RecordInfo.RecordSize;
-    FpdtRecordPtr.GuidQwordEvent->Header.Revision       = FPDT_RECORD_REVISION_1;
-    FpdtRecordPtr.GuidQwordEvent->ProgressID            = RecordInfo.ProgressID;
-    FpdtRecordPtr.GuidQwordEvent->Timestamp             = TimeStamp;
-    CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
-    if ((MODULE_LOADIMAGE_START_ID == RecordInfo.ProgressID) && AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) {
-      mLoadImageCount++;
-      FpdtRecordPtr.GuidQwordEvent->Qword               = mLoadImageCount;
+  case MODULE_DB_START_ID:
+  case MODULE_DB_SUPPORT_START_ID:
+  case MODULE_DB_SUPPORT_END_ID:
+  case MODULE_DB_STOP_START_ID:
+  case MODULE_DB_STOP_END_ID:
+    GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+    StringPtr = ModuleName;
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.GuidQwordEvent->Header.Type           = FPDT_GUID_QWORD_EVENT_TYPE;
+      FpdtRecordPtr.GuidQwordEvent->Header.Length         = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
+      FpdtRecordPtr.GuidQwordEvent->Header.Revision       = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.GuidQwordEvent->ProgressID            = PerfId;
+      FpdtRecordPtr.GuidQwordEvent->Timestamp             = TimeStamp;
+      FpdtRecordPtr.GuidQwordEvent->Qword                 = Address;
+      CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
     }
     break;
 
-  case FPDT_GUID_QWORD_STRING_EVENT_TYPE:
-    FpdtRecordPtr.GuidQwordStringEvent->Header.Type     = FPDT_GUID_QWORD_STRING_EVENT_TYPE;
-    FpdtRecordPtr.GuidQwordStringEvent->Header.Length   = RecordInfo.RecordSize;
-    FpdtRecordPtr.GuidQwordStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
-    FpdtRecordPtr.GuidQwordStringEvent->ProgressID      = RecordInfo.ProgressID;
-    FpdtRecordPtr.GuidQwordStringEvent->Timestamp       = TimeStamp;
-    CopyMem (&FpdtRecordPtr.GuidQwordStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordStringEvent->Guid));
+  case MODULE_DB_END_ID:
+    GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+    StringPtr = ModuleName;
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.GuidQwordStringEvent->Header.Type     = FPDT_GUID_QWORD_STRING_EVENT_TYPE;
+      FpdtRecordPtr.GuidQwordStringEvent->Header.Length   = sizeof (FPDT_GUID_QWORD_STRING_EVENT_RECORD);;
+      FpdtRecordPtr.GuidQwordStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.GuidQwordStringEvent->ProgressID      = PerfId;
+      FpdtRecordPtr.GuidQwordStringEvent->Timestamp       = TimeStamp;
+      FpdtRecordPtr.GuidQwordStringEvent->Qword           = Address;
+      CopyMem (&FpdtRecordPtr.GuidQwordStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordStringEvent->Guid));
+      if (Address != 0) {
+        GetDeviceInfoFromHandleAndUpdateLength(CallerIdentifier, (EFI_HANDLE)(UINTN)Address, FpdtRecordPtr.GuidQwordStringEvent->String, &FpdtRecordPtr.GuidQwordStringEvent->Header.Length);
+      }
+    }
     break;
 
-  default:
+  case PERF_EVENTSIGNAL_START_ID:
+  case PERF_EVENTSIGNAL_END_ID:
+  case PERF_CALLBACK_START_ID:
+  case PERF_CALLBACK_END_ID:
+    if (String == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
     //
-    // Record is not supported in current DXE phase, return EFI_ABORTED
+    // Cache the event guid in string event record when PcdEdkiiFpdtStringRecordEnableOnly == TRUE
     //
-    return EFI_UNSUPPORTED;
+    CopyGuid (&ModuleGuid, Guid);
+    StringPtr = String;
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.DualGuidStringEvent->Header.Type      = FPDT_DUAL_GUID_STRING_EVENT_TYPE;
+      FpdtRecordPtr.DualGuidStringEvent->Header.Length    = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);
+      FpdtRecordPtr.DualGuidStringEvent->Header.Revision  = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.DualGuidStringEvent->ProgressID       = PerfId;
+      FpdtRecordPtr.DualGuidStringEvent->Timestamp        = TimeStamp;
+      CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid1, CallerIdentifier, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));
+      CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));
+      CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DualGuidStringEvent->String, StringPtr, &FpdtRecordPtr.DualGuidStringEvent->Header.Length);
+    }
+    break;
+
+  case PERF_EVENT_ID:
+  case PERF_FUNCTION_START_ID:
+  case PERF_FUNCTION_END_ID:
+  case PERF_INMODULE_START_ID:
+  case PERF_INMODULE_END_ID:
+  case PERF_CROSSMODULE_START_ID:
+  case PERF_CROSSMODULE_END_ID:
+    GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+    if (String != NULL) {
+      StringPtr = String;
+    } else {
+      StringPtr = ModuleName;
+    }
+    if (AsciiStrLen (StringPtr) == 0) {
+      StringPtr = "unknown name";
+    }
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+      FpdtRecordPtr.DynamicStringEvent->Header.Length     = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+      FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.DynamicStringEvent->ProgressID        = PerfId;
+      FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
+      CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+      CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+    }
+    break;
+
+  default:
+    if (Attribute != PerfEntry) {
+      GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+      if (String != NULL) {
+        StringPtr = String;
+      } else {
+        StringPtr = ModuleName;
+      }
+      if (AsciiStrLen (StringPtr) == 0) {
+        StringPtr = "unknown name";
+      }
+      if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+        FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+        FpdtRecordPtr.DynamicStringEvent->Header.Length     = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+        FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
+        FpdtRecordPtr.DynamicStringEvent->ProgressID        = PerfId;
+        FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
+        CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+        CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+      }
+    } else {
+      return EFI_INVALID_PARAMETER;
+    }
+    break;
+  }
+
+  //
+  // 4.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.
+  //
+  if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+    if (StringPtr == NULL ||PerfId == MODULE_DB_SUPPORT_START_ID || PerfId == MODULE_DB_SUPPORT_END_ID) {
+      return EFI_INVALID_PARAMETER;
+    }
+    FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+    FpdtRecordPtr.DynamicStringEvent->Header.Length     = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+    FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
+    FpdtRecordPtr.DynamicStringEvent->ProgressID        = PerfId;
+    FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
+    CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+    if (AsciiStrLen (StringPtr) == 0) {
+      StringPtr = "unknown name";
+    }
+    CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+
+    if ((PerfId == MODULE_LOADIMAGE_START_ID) || (PerfId == MODULE_END_ID)) {
+      FpdtRecordPtr.DynamicStringEvent->Header.Length = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)+ STRING_SIZE);
+    }
+    if ((PerfId == MODULE_LOADIMAGE_END_ID || PerfId == MODULE_END_ID) && mCachedLength != 0) {
+      if (mFpdtBufferIsReported) {
+        CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mCachedLength);
+      } else {
+        CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mCachedLength);
+      }
+      if (PerfId == MODULE_LOADIMAGE_END_ID) {
+        DestMax = CachedFpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+        StringLen = AsciiStrLen (StringPtr);
+        if (StringLen >= DestMax) {
+          StringLen = DestMax -1;
+        }
+        CopyMem (&CachedFpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
+        AsciiStrnCpyS (CachedFpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StringLen);
+      } else if (PerfId == MODULE_END_ID) {
+        DestMax = FpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+        StringLen = AsciiStrLen (CachedFpdtRecordPtr.DynamicStringEvent->String);
+        if (StringLen >= DestMax) {
+          StringLen = DestMax -1;
+        }
+        CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &CachedFpdtRecordPtr.DynamicStringEvent->Guid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
+        AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, CachedFpdtRecordPtr.DynamicStringEvent->String, StringLen);
+      }
+      mCachedLength = 0;
+    }
   }
 
+  //
+  // 5. Update the length of the used buffer after fill in the record.
+  //
+  if (mFpdtBufferIsReported) {
+    mBootRecordSize += FpdtRecordPtr.RecordHeader->Length;
+    mAcpiBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;
+  } else {
+    mPerformanceLength += FpdtRecordPtr.RecordHeader->Length;
+  }
   return EFI_SUCCESS;
 }
 
 /**
   Dumps all the PEI performance.
@@ -1158,15 +1454,12 @@ CreatePerformanceMeasurement (
   if (mLockInsertRecord) {
     return EFI_INVALID_PARAMETER;
   }
   mLockInsertRecord = TRUE;
 
-  if (Attribute == PerfStartEntry) {
-    Status = InsertFpdtMeasurement (TRUE, CallerIdentifier, String, String, TimeStamp, Identifier);
-  } else if (Attribute == PerfEndEntry) {
-    Status = InsertFpdtMeasurement (FALSE, CallerIdentifier, String, String, TimeStamp, Identifier);
-  }
+  Status = InsertFpdtRecord (CallerIdentifier, Guid, String, TimeStamp, Address, (UINT16)Identifier, Attribute);
+
   mLockInsertRecord = FALSE;
 
   return Status;
 }
 
@@ -1470,5 +1763,60 @@ PerformanceMeasurementEnabled (
   VOID
   )
 {
   return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
 }
+
+/**
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID
+  @param Guid              - Pointer to a GUID
+  @param String            - Pointer to a string describing the measurement
+  @param Address           - Pointer to a location in memory relevant to the measurement
+  @param Identifier        - Performance identifier describing the type of measurement
+
+  @retval RETURN_SUCCESS           - Successfully created performance record
+  @retval RETURN_OUT_OF_RESOURCES  - Ran out of space to store the records
+  @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                     pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+  IN CONST VOID   *CallerIdentifier,
+  IN CONST VOID   *Guid,    OPTIONAL
+  IN CONST CHAR8  *String,  OPTIONAL
+  IN UINT64       Address, OPTIONAL
+  IN UINT32       Identifier
+  )
+{
+  return (RETURN_STATUS)CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
+}
+
+/**
+  Check whether the specified performance measurement can be logged.
+
+  This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+  and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+  @param Type        - Type of the performance measurement entry.
+
+  @retval TRUE         The performance measurement can be logged.
+  @retval FALSE        The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+  IN  CONST UINTN        Type
+  )
+{
+  //
+  // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+  //
+  if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+    return TRUE;
+  }
+  return FALSE;
+}
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
index 68cd76da5b3..3e77f9cd57a 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
@@ -59,10 +59,11 @@
   DebugLib
   UefiLib
   ReportStatusCodeLib
   DxeServicesLib
   PeCoffGetEntryPointLib
+  DevicePathLib
 
 [Protocols]
   gEfiSmmCommunicationProtocolGuid              ## SOMETIMES_CONSUMES
 
 
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
index f9800e34941..a96f4081503 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
@@ -40,10 +40,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/HobLib.h>
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/TimerLib.h>
 #include <Library/PcdLib.h>
+#include <Library/DevicePathLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiRuntimeServicesTableLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/UefiLib.h>
 #include <Library/ReportStatusCodeLib.h>
diff --git a/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c b/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c
index 9ed50d22b8d..664e8261af9 100644
--- a/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c
+++ b/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c
@@ -376,5 +376,73 @@ PerformanceMeasurementEnabled (
   VOID
   )
 {
   return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
 }
+
+/**
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID
+  @param Guid              - Pointer to a GUID
+  @param String            - Pointer to a string describing the measurement
+  @param Address           - Pointer to a location in memory relevant to the measurement
+  @param Identifier        - Performance identifier describing the type of measurement
+
+  @retval RETURN_SUCCESS           - Successfully created performance record
+  @retval RETURN_OUT_OF_RESOURCES  - Ran out of space to store the records
+  @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                     pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+  IN CONST VOID   *CallerIdentifier,
+  IN CONST VOID   *Guid,    OPTIONAL
+  IN CONST CHAR8  *String,  OPTIONAL
+  IN  UINT64       Address, OPTIONAL
+  IN UINT32       Identifier
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = GetPerformanceMeasurementProtocol ();
+  if (EFI_ERROR (Status)) {
+    return RETURN_OUT_OF_RESOURCES;
+  }
+
+  if (mPerformanceMeasurement != NULL) {
+    Status = mPerformanceMeasurement->CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
+  } else {
+    ASSERT (FALSE);
+  }
+
+  return (RETURN_STATUS) Status;
+}
+
+/**
+  Check whether the specified performance measurement can be logged.
+
+  This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+  and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+  @param Type        - Type of the performance measurement entry.
+
+  @retval TRUE         The performance measurement can be logged.
+  @retval FALSE        The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+  IN  CONST UINTN        Type
+  )
+{
+  //
+  // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+  //
+  if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+    return TRUE;
+  }
+  return FALSE;
+}
diff --git a/MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.c b/MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.c
index f770a35a995..cd1b0e34ef7 100644
--- a/MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.c
+++ b/MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.c
@@ -21,21 +21,100 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 
 #include <PiPei.h>
 
 #include <Guid/ExtendedFirmwarePerformance.h>
+#include <Guid/PerformanceMeasurement.h>
 
 #include <Library/PerformanceLib.h>
 #include <Library/DebugLib.h>
 #include <Library/HobLib.h>
 #include <Library/BaseLib.h>
 #include <Library/TimerLib.h>
 #include <Library/PcdLib.h>
 #include <Library/BaseMemoryLib.h>
 
 #define  STRING_SIZE            (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))
-#define  MAX_RECORD_SIZE        (sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE)
+#define  PEI_MAX_RECORD_SIZE    (sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD) + STRING_SIZE)
+
+
+/**
+  Return the pointer to the FPDT record in the allocated memory.
+
+  @param  RecordSize                The size of FPDT record.
+  @param  FpdtRecordPtr             Pointer the FPDT record in the allocated memory.
+  @param  PeiPerformanceLogHeader   Pointer to the header of the PEI Performance records in the GUID Hob.
+
+  @retval EFI_SUCCESS               Successfully get the pointer to the FPDT record.
+  @retval EFI_OUT_OF_RESOURCES      Ran out of space to store the records.
+**/
+EFI_STATUS
+GetFpdtRecordPtr (
+  IN     UINT8                     RecordSize,
+  IN OUT FPDT_RECORD_PTR           *FpdtRecordPtr,
+  IN OUT FPDT_PEI_EXT_PERF_HEADER  **PeiPerformanceLogHeader
+)
+{
+  UINT16                                PeiPerformanceLogEntries;
+  UINTN                                 PeiPerformanceSize;
+  UINT8                                 *PeiFirmwarePerformance;
+  EFI_HOB_GUID_TYPE                     *GuidHob;
+
+  //
+  // Get the number of PeiPerformanceLogEntries form PCD.
+  //
+  PeiPerformanceLogEntries = (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?
+                                       PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :
+                                       PcdGet8 (PcdMaxPeiPerformanceLogEntries));
+
+  //
+  // Create GUID HOB Data.
+  //
+  GuidHob = GetFirstGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid);
+  PeiFirmwarePerformance = NULL;
+  while (GuidHob != NULL) {
+    //
+    // PEI Performance HOB was found, then return the existing one.
+    //
+    PeiFirmwarePerformance  = (UINT8*)GET_GUID_HOB_DATA (GuidHob);
+    *PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;
+    if (!(*PeiPerformanceLogHeader)->HobIsFull && (*PeiPerformanceLogHeader)->SizeOfAllEntries + RecordSize > (UINTN)(PeiPerformanceLogEntries * PEI_MAX_RECORD_SIZE)) {
+      (*PeiPerformanceLogHeader)->HobIsFull = TRUE;
+    }
+    if (!(*PeiPerformanceLogHeader)->HobIsFull && (*PeiPerformanceLogHeader)->SizeOfAllEntries + RecordSize <= (UINTN)(PeiPerformanceLogEntries * PEI_MAX_RECORD_SIZE)) {
+      FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER) + (*PeiPerformanceLogHeader)->SizeOfAllEntries);
+      break;
+    }
+    //
+    // Previous HOB is used, then find next one.
+    //
+    GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));
+  }
+
+  if (GuidHob == NULL) {
+    //
+    // PEI Performance HOB was not found, then build one.
+    //
+    PeiPerformanceSize      = sizeof (FPDT_PEI_EXT_PERF_HEADER) +
+                              PEI_MAX_RECORD_SIZE * PeiPerformanceLogEntries;
+    PeiFirmwarePerformance  = (UINT8*)BuildGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, PeiPerformanceSize);
+    if (PeiFirmwarePerformance != NULL) {
+      ZeroMem (PeiFirmwarePerformance, PeiPerformanceSize);
+      (*PeiPerformanceLogHeader) = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;
+      FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER));
+    }
+  }
+
+  if (PeiFirmwarePerformance == NULL) {
+    //
+    // there is no enough resource to store performance data
+    //
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  return EFI_SUCCESS;
+}
 
 /**
 Check whether the Token is a known one which is uesed by core.
 
 @param  Token      Pointer to a Null-terminated ASCII string
@@ -98,252 +177,197 @@ IsKnownID (
     return FALSE;
   }
 }
 
 /**
-  Get the FPDT record info.
+  Get the FPDT record identifier.
 
-  @param  IsStart                 TRUE if the performance log is start log.
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  RecordInfo              On return, pointer to the info of the record.
+  @param Attribute                The attribute of the Record.
+                                  PerfStartEntry: Start Record.
+                                  PerfEndEntry: End Record.
+  @param  Handle                  Pointer to environment specific context used to identify the component being measured.
+  @param  String                  Pointer to a Null-terminated ASCII string that identifies the component being measured.
+  @param  ProgressID              On return, pointer to the ProgressID.
 
-  @retval EFI_SUCCESS             Get record info successfully.
-  @retval EFI_UNSUPPORTED         No matched FPDT record.
+  @retval EFI_SUCCESS              Get record info successfully.
+  @retval EFI_INVALID_PARAMETER    No matched FPDT record.
 
 **/
 EFI_STATUS
-GetFpdtRecordInfo (
-  IN BOOLEAN                 IsStart,
+GetFpdtRecordId (
+  IN BOOLEAN                 Attribute,
   IN CONST VOID              *Handle,
-  IN CONST CHAR8             *Token,
-  IN CONST CHAR8             *Module,
-  OUT FPDT_BASIC_RECORD_INFO *RecordInfo
+  IN CONST CHAR8             *String,
+  OUT UINT16                 *ProgressID
   )
 {
-  UINTN     StringSize;
-  UINT16    RecordType;
-
-  RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-
   //
   // Get the ProgressID based on the Token.
   // When PcdEdkiiFpdtStringRecordEnableOnly is TRUE, all records are with type of FPDT_DYNAMIC_STRING_EVENT_TYPE.
   //
-  if (Token != NULL) {
-    if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) {               // "LoadImage:"
-      if (IsStart) {
-        RecordInfo->ProgressID = MODULE_LOADIMAGE_START_ID;
+  if (String != NULL) {
+    if (AsciiStrCmp (String, LOAD_IMAGE_TOK) == 0) {               // "LoadImage:"
+      if (Attribute == PerfStartEntry) {
+        *ProgressID = MODULE_LOADIMAGE_START_ID;
       } else {
-        RecordInfo->ProgressID = MODULE_LOADIMAGE_END_ID;
+        *ProgressID = MODULE_LOADIMAGE_END_ID;
       }
-      if(!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
-        RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
-      }
-    } else if (AsciiStrCmp (Token, SEC_TOK) == 0 ||               // "SEC"
-               AsciiStrCmp (Token, PEI_TOK) == 0) {               // "PEI"
-      if (IsStart) {
-        RecordInfo->ProgressID = PERF_CROSSMODULE_START_ID;
+    } else if (AsciiStrCmp (String, SEC_TOK) == 0 ||               // "SEC"
+               AsciiStrCmp (String, PEI_TOK) == 0) {               // "PEI"
+      if (Attribute == PerfStartEntry) {
+        *ProgressID = PERF_CROSSMODULE_START_ID;
       } else {
-        RecordInfo->ProgressID = PERF_CROSSMODULE_END_ID;
+        *ProgressID = PERF_CROSSMODULE_END_ID;
       }
-    } else if (AsciiStrCmp (Token, PEIM_TOK) == 0) {              // "PEIM"
-      if (IsStart) {
-        RecordInfo->ProgressID = MODULE_START_ID;
+    } else if (AsciiStrCmp (String, PEIM_TOK) == 0) {              // "PEIM"
+      if (Attribute == PerfStartEntry) {
+        *ProgressID = MODULE_START_ID;
       } else {
-        RecordInfo->ProgressID = MODULE_END_ID;
-      }
-      if(!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
-        RecordType = FPDT_GUID_EVENT_TYPE;
+        *ProgressID = MODULE_END_ID;
       }
     } else {                                                      //Pref used in Modules.
-      if (IsStart) {
-        RecordInfo->ProgressID = PERF_INMODULE_START_ID;
+      if (Attribute == PerfStartEntry) {
+        *ProgressID = PERF_INMODULE_START_ID;
       } else {
-        RecordInfo->ProgressID = PERF_INMODULE_END_ID;
+        *ProgressID = PERF_INMODULE_END_ID;
       }
     }
-  } else if (Module != NULL || Handle != NULL) {                  //Pref used in Modules.
-    if (IsStart) {
-      RecordInfo->ProgressID = PERF_INMODULE_START_ID;
+  } else if (Handle != NULL) {                                    //Pref used in Modules.
+    if (Attribute == PerfStartEntry) {
+      *ProgressID = PERF_INMODULE_START_ID;
     } else {
-      RecordInfo->ProgressID = PERF_INMODULE_END_ID;
+      *ProgressID = PERF_INMODULE_END_ID;
     }
   } else {
-    return EFI_UNSUPPORTED;
+    return EFI_INVALID_PARAMETER;
   }
 
-  //
-  // Get the Guid and string.
-  //
-  if(PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
-    RecordInfo->RecordSize = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE;
-  } else {
-    switch (RecordType) {
-    case FPDT_GUID_EVENT_TYPE:
-      RecordInfo->RecordSize = sizeof (FPDT_GUID_EVENT_RECORD);
-      break;
+  return EFI_SUCCESS;
+}
 
-    case FPDT_GUID_QWORD_EVENT_TYPE:
-      RecordInfo->RecordSize = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
-      break;
+/**
+  Copies the string from Source into Destination and updates Length with the
+  size of the string.
 
-    case FPDT_DYNAMIC_STRING_EVENT_TYPE:
-      if (Token != NULL) {
-        StringSize = AsciiStrSize (Token);
-      } else if (Module != NULL) {
-        StringSize = AsciiStrSize (Module);
-      } else {
-        StringSize = STRING_SIZE;
-      }
-      RecordInfo->RecordSize  = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + StringSize);
-      break;
+  @param Destination - destination of the string copy
+  @param Source      - pointer to the source string which will get copied
+  @param Length      - pointer to a length variable to be updated
 
-    default:
-      //
-      // Other type is unsupported in PEI phase yet, return EFI_UNSUPPORTED
-      //
-      return EFI_UNSUPPORTED;
+**/
+VOID
+CopyStringIntoPerfRecordAndUpdateLength (
+  IN OUT CHAR8  *Destination,
+  IN     CONST CHAR8  *Source,
+  IN OUT UINT8  *Length
+  )
+{
+  UINTN  StringLen;
+  UINTN  DestMax;
+
+  ASSERT (Source != NULL);
+
+  if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+    DestMax = STRING_SIZE;
+  } else {
+    DestMax = AsciiStrSize (Source);
+    if (DestMax > STRING_SIZE) {
+      DestMax = STRING_SIZE;
     }
   }
-  RecordInfo->Type = RecordType;
-  return EFI_SUCCESS;
+  StringLen = AsciiStrLen (Source);
+  if (StringLen >= DestMax) {
+    StringLen = DestMax -1;
+  }
+
+  AsciiStrnCpyS(Destination, DestMax, Source, StringLen);
+  *Length += (UINT8)DestMax;
+
+  return;
 }
 
+
 /**
   Convert PEI performance log to FPDT String boot record.
 
-  @param  IsStart                 TRUE if the performance log is start log.
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  Ticker                  64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the created record
-                                  is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
-
-  @retval EFI_SUCCESS              Add FPDT boot record.
-  @retval EFI_OUT_OF_RESOURCES     There are not enough resources to record the measurement.
-  @retval EFI_UNSUPPORTED          No matched FPDT record.
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID.
+  @param Guid              - Pointer to a GUID.
+  @param String            - Pointer to a string describing the measurement.
+  @param Ticker            - 64-bit time stamp.
+  @param Address           - Pointer to a location in memory relevant to the measurement.
+  @param PerfId            - Performance identifier describing the type of measurement.
+  @param Attribute         - The attribute of the measurement. According to attribute can create a start
+                             record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+                             or a general record for other Perf macros.
+
+  @retval EFI_SUCCESS           - Successfully created performance record.
+  @retval EFI_OUT_OF_RESOURCES  - Ran out of space to store the records.
+  @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                  pointer or invalid PerfId.
 
 **/
 EFI_STATUS
-InsertPeiFpdtMeasurement (
-  IN BOOLEAN      IsStart,
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       Ticker,
-  IN UINT32       Identifier
+InsertFpdtRecord (
+  IN CONST VOID                        *CallerIdentifier,  OPTIONAL
+  IN CONST VOID                        *Guid,    OPTIONAL
+  IN CONST CHAR8                       *String,  OPTIONAL
+  IN       UINT64                      Ticker,
+  IN       UINT64                      Address,  OPTIONAL
+  IN       UINT16                      PerfId,
+  IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute
   )
 {
-  EFI_HOB_GUID_TYPE                     *GuidHob;
-  UINTN                                 PeiPerformanceSize;
-  UINT8                                 *PeiFirmwarePerformance;
-  FPDT_PEI_EXT_PERF_HEADER              *PeiPerformanceLogHeader;
   FPDT_RECORD_PTR                       FpdtRecordPtr;
-  FPDT_BASIC_RECORD_INFO                RecordInfo;
   CONST VOID                            *ModuleGuid;
-  UINTN                                 DestMax;
-  UINTN                                 StrLength;
   CONST CHAR8                           *StringPtr;
   EFI_STATUS                            Status;
-  UINT16                                PeiPerformanceLogEntries;
   UINT64                                TimeStamp;
+  FPDT_PEI_EXT_PERF_HEADER              *PeiPerformanceLogHeader;
 
   StringPtr = NULL;
   FpdtRecordPtr.RecordHeader = NULL;
   PeiPerformanceLogHeader = NULL;
 
   //
-  // Get record info (type, size, ProgressID and Module Guid).
-  //
-  Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
-  // !!! Note: If the Perf is not the known Token used in the core but have same
-  // ID with the core Token, this case will not be supported.
-  // And in currtnt usage mode, for the unkown ID, there is a general rule:
-  // If it is start pref: the lower 4 bits of the ID should be 0.
-  // If it is end pref: the lower 4 bits of the ID should not be 0.
-  // If input ID doesn't follow the rule, we will adjust it.
+  // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.
+  //    notes: For other Perf macros (Attribute == PerfEntry), their Id is known.
   //
-  if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
-    return EFI_UNSUPPORTED;
-  } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
-    if (IsStart && ((Identifier & 0x000F) != 0)) {
-      Identifier &= 0xFFF0;
-    } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {
-      Identifier += 1;
-    }
-    RecordInfo.ProgressID = (UINT16)Identifier;
-  }
-
-  //
-  // Get the number of PeiPerformanceLogEntries form PCD.
-  //
-  PeiPerformanceLogEntries = (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?
-                                       PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :
-                                       PcdGet8 (PcdMaxPeiPerformanceLogEntries));
-
-  //
-  // Create GUID HOB Data.
-  //
-  GuidHob = GetFirstGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid);
-  PeiFirmwarePerformance = NULL;
-  while (GuidHob != NULL) {
-    //
-    // PEI Performance HOB was found, then return the existing one.
-    //
-    PeiFirmwarePerformance  = (UINT8*)GET_GUID_HOB_DATA (GuidHob);
-    PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;
-    if (!PeiPerformanceLogHeader->HobIsFull && PeiPerformanceLogHeader->SizeOfAllEntries + RecordInfo.RecordSize > PeiPerformanceLogEntries * MAX_RECORD_SIZE) {
-      PeiPerformanceLogHeader->HobIsFull = TRUE;
-    }
-    if (!PeiPerformanceLogHeader->HobIsFull && PeiPerformanceLogHeader->SizeOfAllEntries + RecordInfo.RecordSize <= PeiPerformanceLogEntries * MAX_RECORD_SIZE) {
-      FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER) + PeiPerformanceLogHeader->SizeOfAllEntries);
-      break;
-    }
-    //
-    // Previous HOB is used, then find next one.
-    //
-    GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));
-  }
-
-  if (GuidHob == NULL) {
+  if (Attribute != PerfEntry) {
     //
-    // PEI Performance HOB was not found, then build one.
+    // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.
+    // !!! Note: If the Perf is not the known Token used in the core but have same
+    // ID with the core Token, this case will not be supported.
+    // And in currtnt usage mode, for the unkown ID, there is a general rule:
+    // If it is start pref: the lower 4 bits of the ID should be 0.
+    // If it is end pref: the lower 4 bits of the ID should not be 0.
+    // If input ID doesn't follow the rule, we will adjust it.
     //
-    PeiPerformanceSize      = sizeof (FPDT_PEI_EXT_PERF_HEADER) +
-                              MAX_RECORD_SIZE * PeiPerformanceLogEntries;
-    PeiFirmwarePerformance  = (UINT8*)BuildGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, PeiPerformanceSize);
-    if (PeiFirmwarePerformance != NULL) {
-      ZeroMem (PeiFirmwarePerformance, PeiPerformanceSize);
+    if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+      return EFI_UNSUPPORTED;
+    } else if ((PerfId != 0) && (!IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+      if (Attribute == PerfStartEntry && ((PerfId & 0x000F) != 0)) {
+        PerfId &= 0xFFF0;
+      } else if ((Attribute == PerfEndEntry) && ((PerfId & 0x000F) == 0)) {
+        PerfId += 1;
+      }
+    } else if (PerfId == 0) {
+      Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &PerfId);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
     }
-    PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;
-    FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER));
   }
 
-  if (PeiFirmwarePerformance == NULL) {
-    //
-    // there is no enough resource to store performance data
-    //
-    return EFI_OUT_OF_RESOURCES;
+  //
+  // 2. Get the buffer to store the FPDT record.
+  //
+  Status = GetFpdtRecordPtr (PEI_MAX_RECORD_SIZE, &FpdtRecordPtr, &PeiPerformanceLogHeader);
+  if (EFI_ERROR (Status)) {
+    return Status;
   }
 
   //
-  // Get the TimeStamp.
+  // 3 Get the TimeStamp.
   //
   if (Ticker == 0) {
     Ticker    = GetPerformanceCounter ();
     TimeStamp = GetTimeInNanoSecond (Ticker);
   } else if (Ticker == 1) {
@@ -351,74 +375,142 @@ InsertPeiFpdtMeasurement (
   } else {
     TimeStamp = GetTimeInNanoSecond (Ticker);
   }
 
   //
-  // Get the ModuleGuid.
+  // 4.Get the ModuleGuid.
   //
-  if (Handle != NULL) {
-    ModuleGuid = Handle;
+  if (CallerIdentifier != NULL) {
+    ModuleGuid = CallerIdentifier;
   } else {
     ModuleGuid = &gEfiCallerIdGuid;
   }
 
-  switch (RecordInfo.Type) {
-  case FPDT_GUID_EVENT_TYPE:
-    FpdtRecordPtr.GuidEvent->Header.Type       = FPDT_GUID_EVENT_TYPE;
-    FpdtRecordPtr.GuidEvent->Header.Length     = RecordInfo.RecordSize;;
-    FpdtRecordPtr.GuidEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
-    FpdtRecordPtr.GuidEvent->ProgressID        = RecordInfo.ProgressID;
-    FpdtRecordPtr.GuidEvent->Timestamp         = TimeStamp;
-    CopyMem (&FpdtRecordPtr.GuidEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
-    PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;
+  //
+  // 5. Fill in the FPDT record according to different Performance Identifier.
+  //
+  switch (PerfId) {
+  case MODULE_START_ID:
+  case MODULE_END_ID:
+    StringPtr = PEIM_TOK;
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.GuidEvent->Header.Type       = FPDT_GUID_EVENT_TYPE;
+      FpdtRecordPtr.GuidEvent->Header.Length     = sizeof (FPDT_GUID_EVENT_RECORD);
+      FpdtRecordPtr.GuidEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.GuidEvent->ProgressID        = PerfId;
+      FpdtRecordPtr.GuidEvent->Timestamp         = TimeStamp;
+      CopyMem (&FpdtRecordPtr.GuidEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
+    }
     break;
 
-  case FPDT_GUID_QWORD_EVENT_TYPE:
-    FpdtRecordPtr.GuidQwordEvent->Header.Type     = FPDT_GUID_QWORD_EVENT_TYPE;
-    FpdtRecordPtr.GuidQwordEvent->Header.Length   = RecordInfo.RecordSize;;
-    FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
-    FpdtRecordPtr.GuidQwordEvent->ProgressID      = RecordInfo.ProgressID;
-    FpdtRecordPtr.GuidQwordEvent->Timestamp       = TimeStamp;
-    PeiPerformanceLogHeader->LoadImageCount++;
-    FpdtRecordPtr.GuidQwordEvent->Qword           = PeiPerformanceLogHeader->LoadImageCount;
-    CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
-    PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;
+  case MODULE_LOADIMAGE_START_ID:
+  case MODULE_LOADIMAGE_END_ID:
+    StringPtr = LOAD_IMAGE_TOK;
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.GuidQwordEvent->Header.Type     = FPDT_GUID_QWORD_EVENT_TYPE;
+      FpdtRecordPtr.GuidQwordEvent->Header.Length   = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
+      FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.GuidQwordEvent->ProgressID      = PerfId;
+      FpdtRecordPtr.GuidQwordEvent->Timestamp       = TimeStamp;
+      if (PerfId == MODULE_LOADIMAGE_START_ID) {
+        PeiPerformanceLogHeader->LoadImageCount++;
+      }
+      FpdtRecordPtr.GuidQwordEvent->Qword           = PeiPerformanceLogHeader->LoadImageCount;
+      CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
+    }
     break;
 
-  case FPDT_DYNAMIC_STRING_EVENT_TYPE:
-    FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-    FpdtRecordPtr.DynamicStringEvent->Header.Length     = RecordInfo.RecordSize;
-    FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
-    FpdtRecordPtr.DynamicStringEvent->ProgressID        = RecordInfo.ProgressID;
-    FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
-    CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
-    PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;
-
-    if (Token != NULL) {
-      StringPtr                     = Token;
-    } else if (Module != NULL) {
-      StringPtr                     = Module;
+  case PERF_EVENTSIGNAL_START_ID:
+  case PERF_EVENTSIGNAL_END_ID:
+  case PERF_CALLBACK_START_ID:
+  case PERF_CALLBACK_END_ID:
+    if (String != NULL && AsciiStrLen (String) != 0) {
+      StringPtr = String;
+    } else {
+      StringPtr = "unknown name";
     }
-    if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {
-      DestMax                       = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);
-      StrLength                     = AsciiStrLen (StringPtr);
-      if (StrLength >= DestMax) {
-        StrLength                   = DestMax -1;
-      }
-      AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.DualGuidStringEvent->Header.Type      = FPDT_DUAL_GUID_STRING_EVENT_TYPE;
+      FpdtRecordPtr.DualGuidStringEvent->Header.Length    = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);
+      FpdtRecordPtr.DualGuidStringEvent->Header.Revision  = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.DualGuidStringEvent->ProgressID       = PerfId;
+      FpdtRecordPtr.DualGuidStringEvent->Timestamp        = TimeStamp;
+      CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid1, ModuleGuid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));
+      CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));
+    }
+    break;
+
+  case PERF_EVENT_ID:
+  case PERF_FUNCTION_START_ID:
+  case PERF_FUNCTION_END_ID:
+  case PERF_INMODULE_START_ID:
+  case PERF_INMODULE_END_ID:
+  case PERF_CROSSMODULE_START_ID:
+  case PERF_CROSSMODULE_END_ID:
+    if (String != NULL && AsciiStrLen (String) != 0) {
+      StringPtr = String;
     } else {
-      AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");
+      StringPtr = "unknown name";
+    }
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+      FpdtRecordPtr.DynamicStringEvent->Header.Length     = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+      FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.DynamicStringEvent->ProgressID        = PerfId;
+      FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
+      CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
+      CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
     }
     break;
 
   default:
-    //
-    // Record is not supported in current PEI phase, return EFI_ABORTED
-    //
-    return EFI_UNSUPPORTED;
+    if (Attribute != PerfEntry) {
+     if (String != NULL && AsciiStrLen (String) != 0) {
+       StringPtr = String;
+     } else {
+       StringPtr = "unknown name";
+     }
+     if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+       FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+       FpdtRecordPtr.DynamicStringEvent->Header.Length     = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+       FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
+       FpdtRecordPtr.DynamicStringEvent->ProgressID        = PerfId;
+       FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
+       CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+       CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+     }
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+   break;
+  }
+
+  //
+  // 5.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.
+  //
+  if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+    FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+    FpdtRecordPtr.DynamicStringEvent->Header.Length     = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+    FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
+    FpdtRecordPtr.DynamicStringEvent->ProgressID        = PerfId;
+    FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
+    if (Guid != NULL) {
+      //
+      // Cache the event guid in string event record.
+      //
+      CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, Guid, sizeof (EFI_GUID));
+    } else {
+      CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
+    }
+    CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
   }
 
+  //
+  // 6. Update the length of the used buffer after fill in the record.
+  //
+  PeiPerformanceLogHeader->SizeOfAllEntries += FpdtRecordPtr.RecordHeader->Length;
+
   return EFI_SUCCESS;
 }
 
 /**
   Creates a record for the beginning of a performance measurement.
@@ -452,11 +544,22 @@ StartPerformanceMeasurementEx (
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp,
   IN UINT32       Identifier
   )
 {
-  return InsertPeiFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);
+  CONST CHAR8     *String;
+
+  if (Token != NULL) {
+    String = Token;
+  } else if (Module != NULL) {
+    String = Module;
+  } else {
+    String = NULL;
+  }
+
+  return (RETURN_STATUS)InsertFpdtRecord (Handle, NULL, String, TimeStamp, 0, (UINT16)Identifier, PerfStartEntry);
+
 }
 
 /**
 
   Creates a record for the end of a performance measurement.
@@ -487,11 +590,21 @@ EndPerformanceMeasurementEx (
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp,
   IN UINT32       Identifier
   )
 {
-  return InsertPeiFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);
+  CONST CHAR8     *String;
+
+  if (Token != NULL) {
+    String = Token;
+  } else if (Module != NULL) {
+    String = Module;
+  } else {
+    String = NULL;
+  }
+
+  return (RETURN_STATUS)InsertFpdtRecord (Handle, NULL, String, TimeStamp, 0, (UINT16)Identifier, PerfEndEntry);
 }
 
 /**
   Attempts to retrieve a performance measurement log entry from the performance measurement log.
   It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
@@ -580,11 +693,11 @@ StartPerformanceMeasurement (
   IN CONST CHAR8  *Token,   OPTIONAL
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp
   )
 {
-  return InsertPeiFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, 0);
+  return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
 }
 
 /**
 
   Creates a record for the end of a performance measurement.
@@ -612,11 +725,11 @@ EndPerformanceMeasurement (
   IN CONST CHAR8  *Token,   OPTIONAL
   IN CONST CHAR8  *Module,  OPTIONAL
   IN UINT64       TimeStamp
   )
 {
-  return InsertPeiFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, 0);
+  return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
 }
 
 /**
   Attempts to retrieve a performance measurement log entry from the performance measurement log.
   It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
@@ -690,5 +803,60 @@ PerformanceMeasurementEnabled (
   VOID
   )
 {
   return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
 }
+
+/**
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID
+  @param Guid              - Pointer to a GUID
+  @param String            - Pointer to a string describing the measurement
+  @param Address           - Pointer to a location in memory relevant to the measurement
+  @param Identifier        - Performance identifier describing the type of measurement
+
+  @retval RETURN_SUCCESS           - Successfully created performance record
+  @retval RETURN_OUT_OF_RESOURCES  - Ran out of space to store the records
+  @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                     pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+  IN CONST VOID   *CallerIdentifier,
+  IN CONST VOID   *Guid,    OPTIONAL
+  IN CONST CHAR8  *String,  OPTIONAL
+  IN UINT64       Address, OPTIONAL
+  IN UINT32       Identifier
+  )
+{
+  return (RETURN_STATUS)InsertFpdtRecord (CallerIdentifier, Guid, String, 0, Address, (UINT16)Identifier, PerfEntry);
+}
+
+/**
+  Check whether the specified performance measurement can be logged.
+
+  This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+  and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+  @param Type        - Type of the performance measurement entry.
+
+  @retval TRUE         The performance measurement can be logged.
+  @retval FALSE        The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+  IN  CONST UINTN        Type
+  )
+{
+  //
+  // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+  //
+  if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+    return TRUE;
+  }
+  return FALSE;
+}
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
index e630773562f..0c00fb51e82 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
@@ -45,23 +45,83 @@ typedef struct {
 HANDLE_GUID_MAP      mCacheHandleGuidTable[CACHE_HANDLE_GUID_COUNT];
 UINTN                mCachePairCount = 0;
 
 UINT32               mPerformanceLength    = 0;
 UINT32               mMaxPerformanceLength = 0;
+UINT32               mLoadImageCount       = 0;
 BOOLEAN              mFpdtDataIsReported   = FALSE;
 BOOLEAN              mLackSpaceIsReport    = FALSE;
 CHAR8                *mPlatformLanguage    = NULL;
 SPIN_LOCK            mSmmFpdtLock;
 PERFORMANCE_PROPERTY  mPerformanceProperty;
+UINT32               mCachedLength         = 0;
 
 //
 // Interfaces for SMM PerformanceMeasurement Protocol.
 //
 EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
   CreatePerformanceMeasurement,
 };
 
+/**
+  Return the pointer to the FPDT record in the allocated memory.
+
+  @param  RecordSize             The size of FPDT record.
+  @param  FpdtRecordPtr          Pointer the FPDT record in the allocated memory.
+
+  @retval EFI_SUCCESS            Successfully get the pointer to the FPDT record.
+  @retval EFI_OUT_OF_RESOURCES   Ran out of space to store the records.
+**/
+EFI_STATUS
+GetFpdtRecordPtr (
+  IN     UINT8               RecordSize,
+  IN OUT FPDT_RECORD_PTR     *FpdtRecordPtr
+)
+{
+  if (mFpdtDataIsReported) {
+    //
+    // Append Boot records after Smm boot performance records have been reported.
+    //
+    if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {
+      if (!mLackSpaceIsReport) {
+        DEBUG ((DEBUG_INFO, "SmmCorePerformanceLib: No enough space to save boot records\n"));
+        mLackSpaceIsReport = TRUE;
+      }
+      return EFI_OUT_OF_RESOURCES;
+    } else {
+      //
+      // Covert buffer to FPDT Ptr Union type.
+      //
+      FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
+    }
+  } else {
+    //
+    // Check if pre-allocated buffer is full
+    //
+    if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {
+      mSmmBootPerformanceTable = ReallocatePool (
+                                   mPerformanceLength,
+                                   mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordSize + FIRMWARE_RECORD_BUFFER,
+                                   mSmmBootPerformanceTable
+                              );
+
+      if (mSmmBootPerformanceTable == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+      mSmmBootPerformanceTable->Header.Length = sizeof (SMM_BOOT_PERFORMANCE_TABLE) + mPerformanceLength;
+      mMaxPerformanceLength = mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordSize + FIRMWARE_RECORD_BUFFER;
+    }
+    //
+    // Covert buffer to FPDT Ptr Union type.
+    //
+    FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
+  }
+  FpdtRecordPtr->RecordHeader->Length = 0;
+  return EFI_SUCCESS;
+}
+
+
 /**
 Check whether the Token is a known one which is uesed by core.
 
 @param  Token      Pointer to a Null-terminated ASCII string
 
@@ -123,117 +183,63 @@ IsKnownID (
     return FALSE;
   }
 }
 
 /**
-  Get the FPDT record info.
+  Get the FPDT record identifier.
 
-  @param  IsStart                 TRUE if the performance log is start log.
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  RecordInfo              On return, pointer to the info of the record.
-  @param  UseModuleName           Only useful for FPDT_DYNAMIC_STRING_EVENT_TYPE, indicate that whether need use
-                                  Module name to fill the string field in the FPDT_DYNAMIC_STRING_EVENT_RECORD.
+  @param Attribute                The attribute of the Record.
+                                  PerfStartEntry: Start Record.
+                                  PerfEndEntry: End Record.
+  @param  Handle                  Pointer to environment specific context used to identify the component being measured.
+  @param  String                  Pointer to a Null-terminated ASCII string that identifies the component being measured.
+  @param  ProgressID              On return, pointer to the ProgressID.
 
-  @retval EFI_SUCCESS             Get record info successfully.
-  @retval EFI_UNSUPPORTED         No matched FPDT record.
+  @retval EFI_SUCCESS              Get record info successfully.
+  @retval EFI_INVALID_PARAMETER    No matched FPDT record.
 
 **/
 EFI_STATUS
-GetFpdtRecordInfo (
-  IN BOOLEAN                  IsStart,
-  IN CONST VOID               *Handle,
-  IN CONST CHAR8              *Token,
-  IN CONST CHAR8              *Module,
-  OUT FPDT_BASIC_RECORD_INFO  *RecordInfo,
-  IN OUT BOOLEAN              *UseModuleName
+GetFpdtRecordId (
+  IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute,
+  IN CONST VOID                        *Handle,
+  IN CONST CHAR8                       *String,
+  OUT UINT16                           *ProgressID
   )
 {
-  UINT16              RecordType;
-  UINTN               StringSize;
-
-  RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-
   //
-  // Token to Type and Id.
+  // Token to Id.
   //
-  if (Token != NULL) {
-    if (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) {              // "StartImage:"
-      *UseModuleName = TRUE;
-      RecordType     = FPDT_GUID_EVENT_TYPE;
-      if (IsStart) {
-        RecordInfo->ProgressID  = MODULE_START_ID;
+  if (String != NULL) {
+    if (AsciiStrCmp (String, START_IMAGE_TOK) == 0) {              // "StartImage:"
+      if (Attribute == PerfStartEntry) {
+        *ProgressID  = MODULE_START_ID;
       } else {
-        RecordInfo->ProgressID  = MODULE_END_ID;
+        *ProgressID  = MODULE_END_ID;
       }
-    } else if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) {        // "LoadImage:"
-      *UseModuleName = TRUE;
-      RecordType     = FPDT_GUID_QWORD_EVENT_TYPE;
-      if (IsStart) {
-        RecordInfo->ProgressID  = MODULE_LOADIMAGE_START_ID;
+    } else if (AsciiStrCmp (String, LOAD_IMAGE_TOK) == 0) {        // "LoadImage:"
+      if (Attribute == PerfStartEntry) {
+        *ProgressID  = MODULE_LOADIMAGE_START_ID;
       } else {
-        RecordInfo->ProgressID  = MODULE_LOADIMAGE_END_ID;
+        *ProgressID  = MODULE_LOADIMAGE_END_ID;
       }
     } else {                                                      // Pref used in Modules
-      if (IsStart) {
-        RecordInfo->ProgressID  = PERF_INMODULE_START_ID;
+      if (Attribute == PerfStartEntry) {
+        *ProgressID  = PERF_INMODULE_START_ID;
       } else {
-        RecordInfo->ProgressID  = PERF_INMODULE_END_ID;
+        *ProgressID  = PERF_INMODULE_END_ID;
       }
     }
-  } else if (Handle != NULL || Module != NULL) {                 // Pref used in Modules
-    if (IsStart) {
-      RecordInfo->ProgressID    = PERF_INMODULE_START_ID;
+  } else if (Handle != NULL) {                                    // Pref used in Modules
+    if (Attribute == PerfStartEntry) {
+      *ProgressID    = PERF_INMODULE_START_ID;
     } else {
-      RecordInfo->ProgressID    = PERF_INMODULE_END_ID;
+      *ProgressID    = PERF_INMODULE_END_ID;
     }
   } else {
     return EFI_UNSUPPORTED;
   }
-
-  if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
-    RecordType               = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-    RecordInfo->RecordSize   = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE;
-  } else {
-    switch (RecordType) {
-    case FPDT_GUID_EVENT_TYPE:
-      RecordInfo->RecordSize  = sizeof (FPDT_GUID_EVENT_RECORD);
-      break;
-
-    case FPDT_DYNAMIC_STRING_EVENT_TYPE:
-      if (*UseModuleName) {
-        StringSize   = STRING_SIZE;
-      } else if (Token != NULL) {
-        StringSize  = AsciiStrSize (Token);
-      } else if (Module != NULL) {
-        StringSize  = AsciiStrSize (Module);
-      } else {
-        StringSize  = STRING_SIZE;
-      }
-      if (StringSize > STRING_SIZE) {
-        StringSize  = STRING_SIZE;
-      }
-      RecordInfo->RecordSize  = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + StringSize);
-      break;
-
-    case FPDT_GUID_QWORD_EVENT_TYPE:
-      RecordInfo->RecordSize  = (UINT8)sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
-      break;
-
-    default:
-      //
-      // Record type is unsupported in SMM phase.
-      //
-      return EFI_UNSUPPORTED;
-    }
-  }
-
-  RecordInfo->Type = RecordType;
   return EFI_SUCCESS;
 }
 
 /**
   Get a human readable module name and module guid for the given image handle.
@@ -435,123 +441,144 @@ Done:
 
   return Status;
 }
 
 /**
-  Add performance log to FPDT boot record table.
+  Copies the string from Source into Destination and updates Length with the
+  size of the string.
 
-  @param  IsStart                 TRUE if the performance log is start log.
-  @param  Handle                  Pointer to environment specific context used
-                                  to identify the component being measured.
-  @param  Token                   Pointer to a Null-terminated ASCII string
-                                  that identifies the component being measured.
-  @param  Module                  Pointer to a Null-terminated ASCII string
-                                  that identifies the module being measured.
-  @param  Ticker                  64-bit time stamp.
-  @param  Identifier              32-bit identifier. If the value is 0, the created record
-                                  is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
+  @param Destination - destination of the string copy
+  @param Source      - pointer to the source string which will get copied
+  @param Length      - pointer to a length variable to be updated
+
+**/
+VOID
+CopyStringIntoPerfRecordAndUpdateLength (
+  IN OUT CHAR8  *Destination,
+  IN     CONST CHAR8  *Source,
+  IN OUT UINT8  *Length
+  )
+{
+  UINTN  StringLen;
+  UINTN  DestMax;
+
+  ASSERT (Source != NULL);
+
+  if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+    DestMax = STRING_SIZE;
+  } else {
+    DestMax = AsciiStrSize (Source);
+    if (DestMax > STRING_SIZE) {
+      DestMax = STRING_SIZE;
+    }
+  }
+  StringLen = AsciiStrLen (Source);
+  if (StringLen >= DestMax) {
+    StringLen = DestMax -1;
+  }
 
-  @retval EFI_SUCCESS             Add FPDT boot record.
-  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
-  @retval EFI_UNSUPPORTED         No matched FPDT record.
+  AsciiStrnCpyS(Destination, DestMax, Source, StringLen);
+  *Length += (UINT8)DestMax;
+
+  return;
+}
+
+/**
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID.
+  @param Guid              - Pointer to a GUID.
+  @param String            - Pointer to a string describing the measurement.
+  @param Ticker            - 64-bit time stamp.
+  @param Address           - Pointer to a location in memory relevant to the measurement.
+  @param PerfId            - Performance identifier describing the type of measurement.
+  @param Attribute         - The attribute of the measurement. According to attribute can create a start
+                             record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+                             or a general record for other Perf macros.
+
+  @retval EFI_SUCCESS           - Successfully created performance record.
+  @retval EFI_OUT_OF_RESOURCES  - Ran out of space to store the records.
+  @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                  pointer or invalid PerfId.
+
+  @retval EFI_SUCCESS           - Successfully created performance record
+  @retval EFI_OUT_OF_RESOURCES  - Ran out of space to store the records
+  @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                  pointer or invalid PerfId
 
 **/
 EFI_STATUS
-InsertFpdtMeasurement (
-  IN BOOLEAN      IsStart,
-  IN CONST VOID   *Handle,  OPTIONAL
-  IN CONST CHAR8  *Token,   OPTIONAL
-  IN CONST CHAR8  *Module,  OPTIONAL
-  IN UINT64       Ticker,
-  IN UINT32       Identifier
+InsertFpdtRecord (
+  IN CONST VOID                        *CallerIdentifier,  OPTIONAL
+  IN CONST VOID                        *Guid,    OPTIONAL
+  IN CONST CHAR8                       *String,  OPTIONAL
+  IN       UINT64                      Ticker,
+  IN       UINT64                      Address,  OPTIONAL
+  IN       UINT16                      PerfId,
+  IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute
   )
+
 {
+  EFI_STATUS                   Status;
   EFI_GUID                     ModuleGuid;
   CHAR8                        ModuleName[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];
-  EFI_STATUS                   Status;
   FPDT_RECORD_PTR              FpdtRecordPtr;
+  FPDT_RECORD_PTR              CachedFpdtRecordPtr;
   UINT64                       TimeStamp;
-  FPDT_BASIC_RECORD_INFO       RecordInfo;
-  UINTN                        DestMax;
-  UINTN                        StrLength;
   CONST CHAR8                  *StringPtr;
-  BOOLEAN                      UseModuleName;
+  UINTN                        DestMax;
+  UINTN                        StringLen;
+  UINT16                       ProgressId;
 
   StringPtr     = NULL;
-  UseModuleName = FALSE;
   ZeroMem (ModuleName, sizeof (ModuleName));
 
   //
-  // Get record info includes type, size, ProgressID.
-  //
-  Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo, &UseModuleName);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
-  // !!! Note: If the Perf is not the known Token used in the core but have same
-  // ID with the core Token, this case will not be supported.
-  // And in currtnt usage mode, for the unkown ID, there is a general rule:
-  // If it is start pref: the lower 4 bits of the ID should be 0.
-  // If it is end pref: the lower 4 bits of the ID should not be 0.
-  // If input ID doesn't follow the rule, we will adjust it.
+  // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.
+  //    notes: For other Perf macros (Attribute == PerfEntry), their Id is known.
   //
-  if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
-    return EFI_UNSUPPORTED;
-  } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
-    if (IsStart && ((Identifier & 0x000F) != 0)) {
-      Identifier &= 0xFFF0;
-    } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {
-      Identifier += 1;
-    }
-    RecordInfo.ProgressID = (UINT16)Identifier;
-  }
-
-  if (mFpdtDataIsReported) {
+  if (Attribute != PerfEntry) {
     //
-    // Append Boot records after Smm boot performance records have been reported.
+    // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.
+    // !!! Note: If the Perf is not the known Token used in the core but have same
+    // ID with the core Token, this case will not be supported.
+    // And in currtnt usage mode, for the unkown ID, there is a general rule:
+    // If it is start pref: the lower 4 bits of the ID should be 0.
+    // If it is end pref: the lower 4 bits of the ID should not be 0.
+    // If input ID doesn't follow the rule, we will adjust it.
     //
-    if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {
-      if (!mLackSpaceIsReport) {
-        DEBUG ((DEBUG_INFO, "SmmCorePerformanceLib: No enough space to save boot records\n"));
-        mLackSpaceIsReport = TRUE;
+    if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+      return EFI_INVALID_PARAMETER;
+    } else if ((PerfId != 0) && (!IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+      if ((Attribute == PerfStartEntry) && ((PerfId & 0x000F) != 0)) {
+        PerfId &= 0xFFF0;
+      } else if ((Attribute == PerfEndEntry) && ((PerfId & 0x000F) == 0)) {
+        PerfId += 1;
       }
-      return EFI_OUT_OF_RESOURCES;
-    } else {
+    }
+    if (PerfId == 0) {
       //
-      // Covert buffer to FPDT Ptr Union type.
+      // Get ProgressID form the String Token.
       //
-      FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
-    }
-  } else {
-    //
-    // Check if pre-allocated buffer is full
-    //
-    if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {
-      mSmmBootPerformanceTable = ReallocatePool (
-                                   mPerformanceLength,
-                                   mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER,
-                                   mSmmBootPerformanceTable
-                              );
-
-      if (mSmmBootPerformanceTable == NULL) {
-        return EFI_OUT_OF_RESOURCES;
+      Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &ProgressId);
+      if (EFI_ERROR (Status)) {
+        return Status;
       }
-      mSmmBootPerformanceTable->Header.Length = sizeof (SMM_BOOT_PERFORMANCE_TABLE) + mPerformanceLength;
-      mMaxPerformanceLength = mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER;
+      PerfId = ProgressId;
     }
-    //
-    // Covert buffer to FPDT Ptr Union type.
-    //
-    FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
   }
-  FpdtRecordPtr.RecordHeader->Length = 0;
 
   //
-  // Get the TimeStamp.
+  // 2. Get the buffer to store the FPDT record.
+  //
+  Status = GetFpdtRecordPtr (FPDT_MAX_PERF_RECORD_SIZE, &FpdtRecordPtr);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // 3. Get the TimeStamp.
   //
   if (Ticker == 0) {
     Ticker    = GetPerformanceCounter ();
     TimeStamp = GetTimeInNanoSecond (Ticker);
   } else if (Ticker == 1) {
@@ -559,74 +586,190 @@ InsertFpdtMeasurement (
   } else {
     TimeStamp = GetTimeInNanoSecond (Ticker);
   }
 
   //
-  // Get the ModuleName and ModuleGuid form the handle.
+  // 4. Fill in the FPDT record according to different Performance Identifier.
   //
-  GetModuleInfoFromHandle ((EFI_HANDLE *)Handle, ModuleName, sizeof (ModuleName), &ModuleGuid);
+  switch (PerfId) {
+  case MODULE_START_ID:
+  case MODULE_END_ID:
+    GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+    StringPtr = ModuleName;
+    //
+    // Cache the offset of start image start record and use to update the start image end record if needed.
+    //
+    if (PerfId == MODULE_START_ID && Attribute == PerfEntry) {
+      mCachedLength = mSmmBootPerformanceTable->Header.Length;
+    }
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.GuidEvent->Header.Type                = FPDT_GUID_EVENT_TYPE;
+      FpdtRecordPtr.GuidEvent->Header.Length              = sizeof (FPDT_GUID_EVENT_RECORD);
+      FpdtRecordPtr.GuidEvent->Header.Revision            = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.GuidEvent->ProgressID                 = PerfId;
+      FpdtRecordPtr.GuidEvent->Timestamp                  = TimeStamp;
+      CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+      if (CallerIdentifier == NULL && PerfId == MODULE_END_ID && mCachedLength != 0) {
+        CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mCachedLength);
+        CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &CachedFpdtRecordPtr.GuidEvent->Guid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+        mCachedLength = 0;
+      }
+    }
+    break;
 
-  //
-  // Fill in the record information.
-  //
-  switch (RecordInfo.Type) {
-  case FPDT_GUID_EVENT_TYPE:
-    FpdtRecordPtr.GuidEvent->Header.Type                = FPDT_GUID_EVENT_TYPE;
-    FpdtRecordPtr.GuidEvent->Header.Length              = RecordInfo.RecordSize;
-    FpdtRecordPtr.GuidEvent->Header.Revision            = FPDT_RECORD_REVISION_1;
-    FpdtRecordPtr.GuidEvent->ProgressID                 = RecordInfo.ProgressID;
-    FpdtRecordPtr.GuidEvent->Timestamp                  = TimeStamp;
-    CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+  case MODULE_LOADIMAGE_START_ID:
+  case MODULE_LOADIMAGE_END_ID:
+    GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+    StringPtr = ModuleName;
+    if (PerfId == MODULE_LOADIMAGE_START_ID) {
+      mLoadImageCount++;
+      //
+      // Cache the offset of load image start record and use to be updated by the load image end record if needed.
+      //
+      if (CallerIdentifier == NULL && Attribute == PerfEntry) {
+        mCachedLength = mSmmBootPerformanceTable->Header.Length;
+      }
+    }
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.GuidQwordEvent->Header.Type           = FPDT_GUID_QWORD_EVENT_TYPE;
+      FpdtRecordPtr.GuidQwordEvent->Header.Length         = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
+      FpdtRecordPtr.GuidQwordEvent->Header.Revision       = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.GuidQwordEvent->ProgressID            = PerfId;
+      FpdtRecordPtr.GuidQwordEvent->Timestamp             = TimeStamp;
+      FpdtRecordPtr.GuidQwordEvent->Qword                 = mLoadImageCount;
+      CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
+      if (PerfId == MODULE_LOADIMAGE_END_ID && mCachedLength != 0) {
+        CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mCachedLength);
+        CopyMem (&CachedFpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.GuidQwordEvent->Guid));
+        mCachedLength = 0;
+      }
+    }
     break;
 
-  case FPDT_DYNAMIC_STRING_EVENT_TYPE:
-    FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-    FpdtRecordPtr.DynamicStringEvent->Header.Length     = RecordInfo.RecordSize;
-    FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
-    FpdtRecordPtr.DynamicStringEvent->ProgressID        = RecordInfo.ProgressID;
-    FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
-    CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+  case PERF_EVENTSIGNAL_START_ID:
+  case PERF_EVENTSIGNAL_END_ID:
+  case PERF_CALLBACK_START_ID:
+  case PERF_CALLBACK_END_ID:
+    if (String == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+    //
+    // Cache the event guid in string event record when PcdEdkiiFpdtStringRecordEnableOnly == TRUE
+    //
+    CopyGuid (&ModuleGuid, Guid);
+    StringPtr = String;
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.DualGuidStringEvent->Header.Type      = FPDT_DUAL_GUID_STRING_EVENT_TYPE;
+      FpdtRecordPtr.DualGuidStringEvent->Header.Length    = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);
+      FpdtRecordPtr.DualGuidStringEvent->Header.Revision  = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.DualGuidStringEvent->ProgressID       = PerfId;
+      FpdtRecordPtr.DualGuidStringEvent->Timestamp        = TimeStamp;
+      CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid1, CallerIdentifier, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));
+      CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));
+      CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DualGuidStringEvent->String, StringPtr, &FpdtRecordPtr.DualGuidStringEvent->Header.Length);
+    }
+    break;
 
-    if (UseModuleName) {
-      StringPtr     = ModuleName;
-    } else if (Token != NULL) {
-      StringPtr     = Token;
-    } else if (Module != NULL) {
-      StringPtr     = Module;
-    } else if (ModuleName != NULL) {
-      StringPtr     = ModuleName;
+  case PERF_EVENT_ID:
+  case PERF_FUNCTION_START_ID:
+  case PERF_FUNCTION_END_ID:
+  case PERF_INMODULE_START_ID:
+  case PERF_INMODULE_END_ID:
+  case PERF_CROSSMODULE_START_ID:
+  case PERF_CROSSMODULE_END_ID:
+    GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+    if (String != NULL) {
+      StringPtr = String;
+    } else {
+      StringPtr = ModuleName;
+    }
+    if (AsciiStrLen (StringPtr) == 0) {
+      StringPtr = "unknown name";
     }
-    if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {
-      StrLength     = AsciiStrLen (StringPtr);
-      DestMax       = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);
-      if (StrLength >= DestMax) {
-        StrLength   = DestMax -1;
+    if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+      FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+      FpdtRecordPtr.DynamicStringEvent->Header.Length     = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+      FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
+      FpdtRecordPtr.DynamicStringEvent->ProgressID        = PerfId;
+      FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
+      CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+      CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+    }
+    break;
+
+  default:
+    if (Attribute != PerfEntry) {
+      GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+      if (String != NULL) {
+        StringPtr = String;
+      } else {
+        StringPtr = ModuleName;
+      }
+      if (AsciiStrLen (StringPtr) == 0) {
+        StringPtr = "unknown name";
+      }
+      if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+        FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+        FpdtRecordPtr.DynamicStringEvent->Header.Length     = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+        FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
+        FpdtRecordPtr.DynamicStringEvent->ProgressID        = PerfId;
+        FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
+        CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+        CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
       }
-      AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);
     } else {
-      AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");
+      return EFI_INVALID_PARAMETER;
     }
     break;
+  }
 
-  case FPDT_GUID_QWORD_EVENT_TYPE:
-    FpdtRecordPtr.GuidQwordEvent->Header.Type           = FPDT_GUID_QWORD_EVENT_TYPE;
-    FpdtRecordPtr.GuidQwordEvent->Header.Length         = RecordInfo.RecordSize;
-    FpdtRecordPtr.GuidQwordEvent->Header.Revision       = FPDT_RECORD_REVISION_1;
-    FpdtRecordPtr.GuidQwordEvent->ProgressID            = RecordInfo.ProgressID;
-    FpdtRecordPtr.GuidQwordEvent->Timestamp             = TimeStamp;
-    CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
-    break;
+  //
+  // 4.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.
+  //
+  if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+    if (StringPtr == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+    FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+    FpdtRecordPtr.DynamicStringEvent->Header.Length     = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+    FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
+    FpdtRecordPtr.DynamicStringEvent->ProgressID        = PerfId;
+    FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
+    CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+    if (AsciiStrLen (StringPtr) == 0) {
+      StringPtr = "unknown name";
+    }
+    CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
 
-  default:
-    //
-    // Record is not supported in current SMM phase, return EFI_UNSUPPORTED
-    //
-    return EFI_UNSUPPORTED;
+    if ((PerfId == MODULE_LOADIMAGE_START_ID) || (PerfId == MODULE_END_ID)) {
+      FpdtRecordPtr.DynamicStringEvent->Header.Length = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)+ STRING_SIZE);
+    }
+    if ((PerfId == MODULE_LOADIMAGE_END_ID || PerfId == MODULE_END_ID) && mCachedLength != 0) {
+      CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mCachedLength);
+      if (PerfId == MODULE_LOADIMAGE_END_ID) {
+        DestMax = CachedFpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+        StringLen = AsciiStrLen (StringPtr);
+        if (StringLen >= DestMax) {
+          StringLen = DestMax -1;
+        }
+        CopyMem (&CachedFpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
+        AsciiStrnCpyS (CachedFpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StringLen);
+      } else if (PerfId == MODULE_END_ID) {
+        DestMax = FpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+        StringLen = AsciiStrLen (CachedFpdtRecordPtr.DynamicStringEvent->String);
+        if (StringLen >= DestMax) {
+          StringLen = DestMax -1;
+        }
+        CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &CachedFpdtRecordPtr.DynamicStringEvent->Guid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
+        AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, CachedFpdtRecordPtr.DynamicStringEvent->String, StringLen);
+      }
+      mCachedLength = 0;
+    }
   }
 
   //
-  // Update the cached FPDT record buffer.
+  // 5. Update the length of the used buffer after fill in the record.
   //
   mPerformanceLength += FpdtRecordPtr.RecordHeader->Length;
   mSmmBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;
 
   return EFI_SUCCESS;
@@ -814,16 +957,14 @@ CreatePerformanceMeasurement(
   IN       PERF_MEASUREMENT_ATTRIBUTE  Attribute
   )
 {
   EFI_STATUS   Status;
 
+  Status = EFI_SUCCESS;
+
   AcquireSpinLock (&mSmmFpdtLock);
-  if (Attribute == PerfStartEntry) {
-    Status = InsertFpdtMeasurement (TRUE, CallerIdentifier, String, String, TimeStamp, Identifier);
-  } else if (Attribute == PerfEndEntry) {
-    Status = InsertFpdtMeasurement (FALSE, CallerIdentifier, String, String, TimeStamp, Identifier);
-  }
+  Status = InsertFpdtRecord (CallerIdentifier, Guid, String, TimeStamp, Address, (UINT16)Identifier, Attribute);
   ReleaseSpinLock (&mSmmFpdtLock);
   return Status;
 }
 
 /**
@@ -1125,5 +1266,61 @@ PerformanceMeasurementEnabled (
   VOID
   )
 {
   return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
 }
+
+/**
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID
+  @param Guid              - Pointer to a GUID
+  @param String            - Pointer to a string describing the measurement
+  @param Address           - Pointer to a location in memory relevant to the measurement
+  @param Identifier        - Performance identifier describing the type of measurement
+
+  @retval RETURN_SUCCESS           - Successfully created performance record
+  @retval RETURN_OUT_OF_RESOURCES  - Ran out of space to store the records
+  @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                     pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+  IN CONST VOID   *CallerIdentifier,
+  IN CONST VOID   *Guid,    OPTIONAL
+  IN CONST CHAR8  *String,  OPTIONAL
+  IN UINT64       Address, OPTIONAL
+  IN UINT32       Identifier
+  )
+{
+  return (RETURN_STATUS)CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
+}
+
+/**
+  Check whether the specified performance measurement can be logged.
+
+  This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+  and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+  @param Type        - Type of the performance measurement entry.
+
+  @retval TRUE         The performance measurement can be logged.
+  @retval FALSE        The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+  IN  CONST UINTN        Type
+  )
+{
+  //
+  // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+  //
+  if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
index fd820c0e49c..830037befa6 100644
--- a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
+++ b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
@@ -395,5 +395,73 @@ PerformanceMeasurementEnabled (
   VOID
   )
 {
   return mPerformanceMeasurementEnabled;
 }
+
+/**
+  Create performance record with event description and a timestamp.
+
+  @param CallerIdentifier  - Image handle or pointer to caller ID GUID
+  @param Guid              - Pointer to a GUID
+  @param String            - Pointer to a string describing the measurement
+  @param Address           - Pointer to a location in memory relevant to the measurement
+  @param Identifier        - Performance identifier describing the type of measurement
+
+  @retval RETURN_SUCCESS           - Successfully created performance record
+  @retval RETURN_OUT_OF_RESOURCES  - Ran out of space to store the records
+  @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+                                     pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+  IN CONST VOID   *CallerIdentifier,
+  IN CONST VOID   *Guid,    OPTIONAL
+  IN CONST CHAR8  *String,  OPTIONAL
+  IN UINT64       Address, OPTIONAL
+  IN UINT32       Identifier
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = GetPerformanceMeasurementProtocol ();
+  if (EFI_ERROR (Status)) {
+    return RETURN_OUT_OF_RESOURCES;
+  }
+
+  if (mPerformanceMeasurement != NULL) {
+    Status = mPerformanceMeasurement->CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
+  } else {
+    ASSERT (FALSE);
+  }
+
+  return (RETURN_STATUS) Status;
+}
+
+/**
+  Check whether the specified performance measurement can be logged.
+
+  This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+  and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+  @param Type        - Type of the performance measurement entry.
+
+  @retval TRUE         The performance measurement can be logged.
+  @retval FALSE        The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+  IN  CONST UINTN        Type
+  )
+{
+  //
+  // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+  //
+  if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+    return TRUE;
+  }
+  return FALSE;
+}
-- 
2.14.3.windows.1



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch V2 6/9] ShellPkg/dp: Update dp tool to parse new Perf record
  2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
                   ` (4 preceding siblings ...)
  2018-06-22  8:56 ` [patch V2 5/9] MdeModulePkg: Update performance library instances Dandan Bi
@ 2018-06-22  8:56 ` Dandan Bi
  2018-06-22  8:56 ` [patch V2 7/9] MdeModulePkg: Use new added Perf macros Dandan Bi
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Dandan Bi @ 2018-06-22  8:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Ruiyu Ni

Since performance library instances have been updated
to create new FPDT records for new Perf macros.
So enhance dp tool to parse the new FPDT records.
Enhancement mainly includes:
1. parse the single records for PERF_EVENT macro
2. Parse the new added FPDT_DUAL_GUID_STRING_EVENT_RECORD

Cc: Liming Gao <liming.gao@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c      | 75 +++++++++++++++++++---
 ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h      |  1 +
 .../DynamicCommand/DpDynamicCommand/DpInternal.h   | 14 ++++
 ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c |  4 +-
 .../DynamicCommand/DpDynamicCommand/DpUtilities.c  | 31 +++++++++
 5 files changed, 113 insertions(+), 12 deletions(-)

diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c b/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c
index 38766613175..925341303a4 100644
--- a/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c
+++ b/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c
@@ -428,15 +428,29 @@ GetMeasurementInfo (
       break;
     default:
       ASSERT(FALSE);
     }
 
-    if (AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0) {
-      Measurement->Handle         = &(((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Guid);
+    if (Measurement->Token != NULL && AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0) {
+      Measurement->Handle         = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);
     } else {
       GetHandleFormModuleGuid(ModuleGuid, &StartHandle);
-      Measurement->Handle         = StartHandle;
+      Measurement->Handle = StartHandle;
+      //
+      // When no perf entry to record the PEI and DXE phase,
+      // For start image, we need detect the PEIM and non PEIM here.
+      //
+      if (Measurement->Token == NULL) {
+        if (StartHandle == NULL && !IsZeroGuid (ModuleGuid)) {
+          Measurement->Token      = ALit_PEIM;
+          Measurement->Module     = ALit_PEIM;
+          Measurement->Handle     = ModuleGuid;
+        } else {
+          Measurement->Token      = ALit_START_IMAGE;
+          Measurement->Module     = ALit_START_IMAGE;
+        }
+      }
     }
     break;
 
   case FPDT_DYNAMIC_STRING_EVENT_TYPE:
     ModuleGuid                    = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);
@@ -481,15 +495,27 @@ GetMeasurementInfo (
       break;
     }
 
     Measurement->Module           = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String;
 
-    if (AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0) {
+    if (Measurement->Token != NULL && AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0) {
       Measurement->Handle         = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);
     } else {
       GetHandleFormModuleGuid(ModuleGuid, &StartHandle);
       Measurement->Handle = StartHandle;
+      //
+      // When no perf entry to record the PEI and DXE phase,
+      // For start image, we need detect the PEIM and non PEIM here.
+      //
+      if (Measurement->Token == NULL  && (Measurement->Identifier == MODULE_START_ID || Measurement->Identifier == MODULE_END_ID)) {
+        if (StartHandle == NULL && !IsZeroGuid (ModuleGuid)) {
+          Measurement->Token      = ALit_PEIM;
+          Measurement->Handle     = ModuleGuid;
+        } else {
+          Measurement->Token      = ALit_START_IMAGE;
+        }
+      }
     }
     break;
 
   case FPDT_GUID_QWORD_EVENT_TYPE:
     ModuleGuid                    = &(((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Guid);
@@ -551,10 +577,24 @@ GetMeasurementInfo (
     }
     GetHandleFormModuleGuid(ModuleGuid, &StartHandle);
     Measurement->Handle = StartHandle;
     break;
 
+  case FPDT_DUAL_GUID_STRING_EVENT_TYPE:
+    ModuleGuid                    = &(((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Guid1);
+    Measurement->Identifier       = ((UINT32)((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);
+    if (IsStart) {
+      Measurement->StartTimeStamp = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;
+    } else {
+      Measurement->EndTimeStamp   = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;
+    }
+    Measurement->Token            = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String;
+    Measurement->Module           = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String;
+    GetHandleFormModuleGuid(ModuleGuid, &StartHandle);
+    Measurement->Handle = StartHandle;
+    break;
+
   default:
     break;
   }
 }
 
@@ -578,10 +618,18 @@ SearchMeasurement (
           (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&
           (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0)) {
         mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;
         break;
       }
+    } else if (EndMeasureMent->Identifier == PERF_CROSSMODULE_END_ID) {
+      if (mMeasurementList[Index].EndTimeStamp == 0 &&
+         (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&
+         (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0) &&
+         mMeasurementList[Index].Identifier == PERF_CROSSMODULE_START_ID) {
+        mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;
+        break;
+      }
     } else {
       if (mMeasurementList[Index].EndTimeStamp == 0 && mMeasurementList[Index].Handle == EndMeasureMent->Handle &&
          (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&
          (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0)) {
         mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;
@@ -618,29 +666,36 @@ BuildMeasurementList (
     RecordHeader      = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER*) PerformanceTablePtr;
     StartRecordEvent  = (UINT8 *)RecordHeader;
     StartProgressId   = ((FPDT_GUID_EVENT_RECORD *)StartRecordEvent)->ProgressID;
 
     //
+    // If the record with ProgressId 0, the record doesn't appear in pairs. The timestamp in the record is the EndTimeStamp, its StartTimeStamp is 0.
     // If the record is the start record, fill the info to the measurement in the mMeasurementList.
     // If the record is the end record, find the related start measurement in the mMeasurementList and fill the EndTimeStamp.
     //
-    if (((StartProgressId >= PERF_EVENTSIGNAL_START_ID && ((StartProgressId & 0x000F) == 0)) ||
+    if (StartProgressId == 0) {
+      GetMeasurementInfo (RecordHeader, FALSE, &(mMeasurementList[mMeasurementNum]));
+      mMeasurementNum ++;
+    } else if (((StartProgressId >= PERF_EVENTSIGNAL_START_ID && ((StartProgressId & 0x000F) == 0)) ||
         (StartProgressId < PERF_EVENTSIGNAL_START_ID && ((StartProgressId & 0x0001) != 0)))) {
       //
       // Since PEIM and StartImage has same Type and ID when PCD PcdEdkiiFpdtStringRecordEnableOnly = FALSE
       // So we need to identify these two kinds of record through different phase.
       //
-      if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_PEI) == 0) {
-        mPeiPhase = TRUE;
-      } else if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_DXE) == 0) {
-        mDxePhase = TRUE;
-        mPeiPhase = FALSE;
+      if(StartProgressId == PERF_CROSSMODULE_START_ID ){
+        if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_PEI) == 0) {
+          mPeiPhase = TRUE;
+        } else if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_DXE) == 0) {
+          mDxePhase = TRUE;
+          mPeiPhase = FALSE;
+        }
       }
       // Get measurement info form the start record to the mMeasurementList.
       GetMeasurementInfo (RecordHeader, TRUE, &(mMeasurementList[mMeasurementNum]));
       mMeasurementNum ++;
     } else {
+      ZeroMem(&MeasureMent, sizeof(MEASUREMENT_RECORD));
       GetMeasurementInfo (RecordHeader, FALSE, &MeasureMent);
       SearchMeasurement (&MeasureMent);
     }
     TableLength         += RecordHeader->Length;
     PerformanceTablePtr += RecordHeader->Length;
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h b/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h
index aae021334d6..96bc89db8dc 100644
--- a/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h
+++ b/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h
@@ -39,10 +39,11 @@
 #include <Library/PcdLib.h>
 #include <Library/SortLib.h>
 #include <Library/HiiLib.h>
 #include <Library/FileHandleLib.h>
 #include <Library/UefiHiiServicesLib.h>
+#include <Library/Performancelib.h>
 
 extern EFI_HANDLE mDpHiiHandle;
 
 #define DP_MAJOR_VERSION        2
 #define DP_MINOR_VERSION        5
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h b/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h
index 8dd3076cc71..d8bc7453d2d 100644
--- a/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h
+++ b/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h
@@ -83,10 +83,24 @@ GetDuration (
 BOOLEAN
 IsPhase(
   IN MEASUREMENT_RECORD *Measurement
   );
 
+/**
+  Determine whether the Measurement record is for core code.
+
+  @param[in] Measurement  A pointer to the Measurement record to test.
+
+  @retval     TRUE        The measurement record is used for core.
+  @retval     FALSE       The measurement record is NOT used for core.
+
+**/
+BOOLEAN
+IsCorePerf(
+  IN MEASUREMENT_RECORD        *Measurement
+  );
+
 /** 
   Get the file name portion of the Pdb File Name.
   
   The portion of the Pdb File Name between the last backslash and
   either a following period or the end of the string is converted
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c b/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c
index 7f7d296946f..675cbc3fd14 100644
--- a/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c
+++ b/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c
@@ -602,11 +602,11 @@ ProcessHandles(
       Count++;
       Duration = GetDuration (&Measurement);
       ElapsedTime = DurationInMicroSeconds ( Duration );
       if ((ElapsedTime < mInterestThreshold)                 ||
           (Measurement.EndTimeStamp == 0)                    ||
-          (Measurement.Handle == NULL)                       ||
+          (!IsCorePerf (&Measurement))                       ||
           ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
          ) { // Ignore "uninteresting" or excluded records
         continue;
       }
       mGaugeString[0] = 0;    // Empty driver name by default
@@ -792,11 +792,11 @@ ProcessGlobal(
     AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString));
     AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));
     mGaugeString[25] = 0;
     mUnicodeToken[31] = 0;
     if ( ! ( IsPhase( &Measurement)  ||
-        (Measurement.Handle != NULL)      ||
+        IsCorePerf (&Measurement)      ||
         (Measurement.EndTimeStamp == 0)
         ))
     {
       Duration = GetDuration (&Measurement);
       ElapsedTime = DurationInMicroSeconds ( Duration );
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c b/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c
index 39f71a044c3..5c6ab209d5a 100644
--- a/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c
+++ b/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c
@@ -106,10 +106,41 @@ IsPhase(
              (AsciiStrCmp (Measurement->Token, ALit_BDS) == 0))
             );
   return RetVal;
 }
 
+/**
+  Determine whether the Measurement record is for core code.
+
+  @param[in] Measurement  A pointer to the Measurement record to test.
+
+  @retval     TRUE        The measurement record is used for core.
+  @retval     FALSE       The measurement record is NOT used for core.
+
+**/
+BOOLEAN
+IsCorePerf(
+  IN MEASUREMENT_RECORD        *Measurement
+  )
+{
+  BOOLEAN   RetVal;
+
+  RetVal = (BOOLEAN)(
+            ((Measurement->Identifier == MODULE_START_ID)            ||
+             (Measurement->Identifier == MODULE_END_ID)              ||
+             (Measurement->Identifier == MODULE_LOADIMAGE_START_ID)  ||
+             (Measurement->Identifier == MODULE_LOADIMAGE_END_ID)    ||
+             (Measurement->Identifier == MODULE_DB_START_ID)         ||
+             (Measurement->Identifier == MODULE_DB_END_ID)           ||
+             (Measurement->Identifier == MODULE_DB_SUPPORT_START_ID) ||
+             (Measurement->Identifier == MODULE_DB_SUPPORT_END_ID)   ||
+             (Measurement->Identifier == MODULE_DB_STOP_START_ID)    ||
+             (Measurement->Identifier == MODULE_DB_STOP_START_ID))
+            );
+  return RetVal;
+}
+
 /** 
   Get the file name portion of the Pdb File Name.
   
   The portion of the Pdb File Name between the last backslash and
   either a following period or the end of the string is converted
-- 
2.14.3.windows.1



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch V2 7/9] MdeModulePkg: Use new added Perf macros
  2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
                   ` (5 preceding siblings ...)
  2018-06-22  8:56 ` [patch V2 6/9] ShellPkg/dp: Update dp tool to parse new Perf record Dandan Bi
@ 2018-06-22  8:56 ` Dandan Bi
  2018-06-22  8:56 ` [patch V2 8/9] SecurityPkg: " Dandan Bi
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Dandan Bi @ 2018-06-22  8:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Star Zeng, Eric Dong

Replace old Perf macros with the new added ones.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c      |  7 +++++
 MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c            |  8 ++----
 MdeModulePkg/Core/Dxe/Hand/DriverSupport.c         |  8 +++---
 MdeModulePkg/Core/Dxe/Image/Image.c                | 30 +++++-----------------
 MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c      |  8 +++---
 MdeModulePkg/Core/Pei/PeiMain/PeiMain.c            | 17 ++++++------
 MdeModulePkg/Core/PiSmmCore/Dispatcher.c           | 15 ++++-------
 MdeModulePkg/Core/PiSmmCore/PiSmmCore.c            |  4 +--
 MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c   |  2 +-
 .../Library/UefiBootManagerLib/BmConsole.c         |  9 +++----
 MdeModulePkg/Universal/BdsDxe/BdsEntry.c           | 21 ++++++++-------
 11 files changed, 53 insertions(+), 76 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
index 088cd810631..4c6ca761a60 100644
--- a/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
+++ b/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
@@ -417,10 +417,11 @@ CoreDispatcher (
   LIST_ENTRY                      *Link;
   EFI_CORE_DRIVER_ENTRY           *DriverEntry;
   BOOLEAN                         ReadyToRun;
   EFI_EVENT                       DxeDispatchEvent;
   
+  PERF_FUNCTION_BEGIN ();
 
   if (gDispatcherRunning) {
     //
     // If the dispatcher is running don't let it be restarted.
     //
@@ -582,10 +583,12 @@ CoreDispatcher (
   //
   CoreCloseEvent (DxeDispatchEvent);
 
   gDispatcherRunning = FALSE;
 
+  PERF_FUNCTION_END ();
+
   return ReturnStatus;
 }
 
 
 /**
@@ -1435,17 +1438,21 @@ CoreFwVolEventProtocolNotify (
 VOID
 CoreInitializeDispatcher (
   VOID
   )
 {
+  PERF_FUNCTION_BEGIN ();
+
   mFwVolEvent = EfiCreateProtocolNotifyEvent (
                   &gEfiFirmwareVolume2ProtocolGuid,
                   TPL_CALLBACK,
                   CoreFwVolEventProtocolNotify,
                   NULL,
                   &mFwVolEventRegistration
                   );
+
+  PERF_FUNCTION_END ();
 }
 
 //
 // Function only used in debug builds
 //
diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
index 07c74034624..3f753738a27 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
+++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
@@ -299,12 +299,12 @@ DxeMain (
 
   //
   // Call constructor for all libraries
   //
   ProcessLibraryConstructorList (gDxeCoreImageHandle, gDxeCoreST);
-  PERF_END   (NULL,"PEI", NULL, 0) ;
-  PERF_START (NULL,"DXE", NULL, 0) ;
+  PERF_CROSSMODULE_END   ("PEI");
+  PERF_CROSSMODULE_BEGIN ("DXE");
 
   //
   // Report DXE Core image information to the PE/COFF Extra Action Library
   //
   ZeroMem (&ImageContext, sizeof (ImageContext));
@@ -497,20 +497,16 @@ DxeMain (
   ASSERT_EFI_ERROR (Status);
 
   //
   // Initialize the DXE Dispatcher
   //
-  PERF_START (NULL,"CoreInitializeDispatcher", "DxeMain", 0) ;
   CoreInitializeDispatcher ();
-  PERF_END (NULL,"CoreInitializeDispatcher", "DxeMain", 0) ;
 
   //
   // Invoke the DXE Dispatcher
   //
-  PERF_START (NULL, "CoreDispatcher", "DxeMain", 0);
   CoreDispatcher ();
-  PERF_END (NULL, "CoreDispatcher", "DxeMain", 0);
 
   //
   // Display Architectural protocols that were not loaded if this is DEBUG build
   //
   DEBUG_CODE_BEGIN ();
diff --git a/MdeModulePkg/Core/Dxe/Hand/DriverSupport.c b/MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
index 33dd0bd0b7c..ab3cc0c07e5 100644
--- a/MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
+++ b/MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
@@ -625,32 +625,32 @@ CoreConnectSingleController (
     DriverBinding = NULL;
     DriverFound = FALSE;
     for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
       if (SortedDriverBindingProtocols[Index] != NULL) {
         DriverBinding = SortedDriverBindingProtocols[Index];
-        PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
+        PERF_DRIVER_BINDING_SUPPORT_BEGIN (DriverBinding->DriverBindingHandle, ControllerHandle);
         Status = DriverBinding->Supported(
                                   DriverBinding,
                                   ControllerHandle,
                                   RemainingDevicePath
                                   );
-        PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
+        PERF_DRIVER_BINDING_SUPPORT_END (DriverBinding->DriverBindingHandle, ControllerHandle);
         if (!EFI_ERROR (Status)) {
           SortedDriverBindingProtocols[Index] = NULL;
           DriverFound = TRUE;
 
           //
           // A driver was found that supports ControllerHandle, so attempt to start the driver
           // on ControllerHandle.
           //
-          PERF_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
+          PERF_DRIVER_BINDING_START_BEGIN (DriverBinding->DriverBindingHandle, ControllerHandle);
           Status = DriverBinding->Start (
                                     DriverBinding,
                                     ControllerHandle,
                                     RemainingDevicePath
                                     );
-          PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
+          PERF_DRIVER_BINDING_START_END (DriverBinding->DriverBindingHandle, ControllerHandle);
 
           if (!EFI_ERROR (Status)) {
             //
             // The driver was successfully started on ControllerHandle, so set a flag
             //
diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c
index c49ddfcc81d..adeb4bf313a 100644
--- a/MdeModulePkg/Core/Dxe/Image/Image.c
+++ b/MdeModulePkg/Core/Dxe/Image/Image.c
@@ -1434,17 +1434,13 @@ CoreLoadImage (
   IN UINTN                      SourceSize,
   OUT EFI_HANDLE                *ImageHandle
   )
 {
   EFI_STATUS    Status;
-  UINT64        Tick;
   EFI_HANDLE    Handle;
 
-  Tick = 0;
-  PERF_CODE (
-    Tick = GetPerformanceCounter ();
-  );
+  PERF_LOAD_IMAGE_BEGIN (NULL);
 
   Status = CoreLoadImageCommon (
              BootPolicy,
              ParentImageHandle,
              FilePath,
@@ -1463,12 +1459,11 @@ CoreLoadImage (
     // ImageHandle will be valid only Status is success. 
     //
     Handle = *ImageHandle;
   }
 
-  PERF_START (Handle, "LoadImage:", NULL, Tick);
-  PERF_END (Handle, "LoadImage:", NULL, 0);
+  PERF_LOAD_IMAGE_END (Handle);
 
   return Status;
 }
 
 
@@ -1524,17 +1519,13 @@ CoreLoadImageEx (
   OUT EFI_PHYSICAL_ADDRESS             *EntryPoint         OPTIONAL,
   IN  UINT32                           Attribute
   )
 {
   EFI_STATUS    Status;
-  UINT64        Tick;
   EFI_HANDLE    Handle;
 
-  Tick = 0;
-  PERF_CODE (
-    Tick = GetPerformanceCounter ();
-  );
+  PERF_LOAD_IMAGE_BEGIN (NULL);
 
   Status = CoreLoadImageCommon (
            TRUE,
            ParentImageHandle,
            FilePath,
@@ -1553,12 +1544,11 @@ CoreLoadImageEx (
     // ImageHandle will be valid only Status is success. 
     //
     Handle = *ImageHandle;
   }
 
-  PERF_START (Handle, "LoadImage:", NULL, Tick);
-  PERF_END (Handle, "LoadImage:", NULL, 0);
+  PERF_LOAD_IMAGE_END (Handle);
 
   return Status;
 }
 
 
@@ -1592,14 +1582,12 @@ CoreStartImage (
   EFI_STATUS                    Status;
   LOADED_IMAGE_PRIVATE_DATA     *Image;
   LOADED_IMAGE_PRIVATE_DATA     *LastImage;
   UINT64                        HandleDatabaseKey;
   UINTN                         SetJumpFlag;
-  UINT64                        Tick;
   EFI_HANDLE                    Handle;
 
-  Tick = 0;
   Handle = ImageHandle;
 
   Image = CoreLoadedImageInfo (ImageHandle);
   if (Image == NULL  ||  Image->Started) {
     return EFI_INVALID_PARAMETER;
@@ -1619,13 +1607,11 @@ CoreStartImage (
     DEBUG ((EFI_D_ERROR, "Image type %s can't be started ", GetMachineTypeName(Image->Machine)));
     DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));
     return EFI_UNSUPPORTED;
   }
 
-  PERF_CODE (
-    Tick = GetPerformanceCounter ();
-  );
+  PERF_START_IMAGE_BEGIN (Handle);
 
 
   //
   // Push the current start image context, and
   // link the current image to the head.   This is the
@@ -1645,12 +1631,11 @@ CoreStartImage (
   if (Image->JumpBuffer == NULL) {
     //
     // Image may be unloaded after return with failure,
     // then ImageHandle may be invalid, so use NULL handle to record perf log.
     //
-    PERF_START (NULL, "StartImage:", NULL, Tick);
-    PERF_END (NULL, "StartImage:", NULL, 0);
+    PERF_START_IMAGE_END (NULL);
 
     //
     // Pop the current start image context
     //
     mCurrentImage = LastImage;
@@ -1761,12 +1746,11 @@ CoreStartImage (
   }
 
   //
   // Done
   //
-  PERF_START (Handle, "StartImage:", NULL, Tick);
-  PERF_END (Handle, "StartImage:", NULL, 0);
+  PERF_START_IMAGE_END (Handle);
   return Status;
 }
 
 /**
   Terminates the currently loaded EFI image and returns control to boot services.
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index 0ac3fdde6a9..c4f629dadff 100644
--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -998,13 +998,13 @@ PeiDispatcher (
             //
             // Call the PEIM entry point
             //
             PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
 
-            PERF_START (PeimFileHandle, "PEIM", NULL, 0);
+            PERF_START_IMAGE_BEGIN (PeimFileHandle);
             PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->Ps);
-            PERF_END (PeimFileHandle, "PEIM", NULL, 0);
+            PERF_START_IMAGE_END (PeimFileHandle);
           }
 
           //
           // Process the Notify list and dispatch any notifies for
           // newly installed PPIs.
@@ -1107,11 +1107,11 @@ PeiDispatcher (
               if (Status == EFI_SUCCESS) {
                 //
                 // The PEIM has its dependencies satisfied, and its entry point
                 // has been found, so invoke it.
                 //
-                PERF_START (PeimFileHandle, "PEIM", NULL, 0);
+                PERF_START_IMAGE_BEGIN (PeimFileHandle);
 
                 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
                   EFI_PROGRESS_CODE,
                   (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
                   (VOID *)(&PeimFileHandle),
@@ -1143,11 +1143,11 @@ PeiDispatcher (
                   EFI_PROGRESS_CODE,
                   (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END),
                   (VOID *)(&PeimFileHandle),
                   sizeof (PeimFileHandle)
                   );
-                PERF_END (PeimFileHandle, "PEIM", NULL, 0);
+                PERF_START_IMAGE_END (PeimFileHandle);
 
               }
             }
 
             PeiCheckAndSwitchStack (SecCoreData, Private);
diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
index 775bf18ce93..a52e6f02017 100644
--- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
+++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
@@ -350,22 +350,21 @@ PeiCore (
   
   //
   // Update performance measurements 
   //
   if (OldCoreData == NULL) {
-    PERF_START (NULL, "SEC", NULL, 1);
-    PERF_END   (NULL, "SEC", NULL, 0);
+    PERF_EVENT ("SEC"); // Means the end of SEC phase.
 
     //
     // If first pass, start performance measurement.
     //
-    PERF_START (NULL,"PEI",    NULL, 0);
-    PERF_START (NULL,"PreMem", NULL, 0);
+    PERF_CROSSMODULE_BEGIN ("PEI");
+    PERF_INMODULE_BEGIN ("PreMem");
 
   } else {
-    PERF_END   (NULL,"PreMem",  NULL, 0);
-    PERF_START (NULL,"PostMem", NULL, 0);
+    PERF_INMODULE_END ("PreMem");
+    PERF_INMODULE_BEGIN ("PostMem");
   }
 
   //
   // Complete PEI Core Service initialization
   //  
@@ -409,19 +408,19 @@ PeiCore (
     }
 
     //
     // Alert any listeners that there is permanent memory available
     //
-    PERF_START (NULL,"DisMem", NULL, 0);
+    PERF_INMODULE_BEGIN ("DisMem");
     Status = PeiServicesInstallPpi (&mMemoryDiscoveredPpi);
 
     //
     // Process the Notify list and dispatch any notifies for the Memory Discovered PPI
     //
     ProcessNotifyList (&PrivateData);
 
-    PERF_END (NULL,"DisMem", NULL, 0);
+    PERF_INMODULE_END ("DisMem");
   }
 
   //
   // Call PEIM dispatcher
   //
@@ -435,11 +434,11 @@ PeiCore (
   }
 
   //
   // Measure PEI Core execution time.
   //
-  PERF_END (NULL, "PostMem", NULL, 0);
+  PERF_INMODULE_END ("PostMem");
 
   //
   // Lookup DXE IPL PPI
   //
   Status = PeiServicesLocatePpi (
diff --git a/MdeModulePkg/Core/PiSmmCore/Dispatcher.c b/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
index f32bbbd1b4b..0b3b5924d38 100644
--- a/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
+++ b/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
@@ -319,17 +319,13 @@ SmmLoadImage (
   EFI_DEVICE_PATH_PROTOCOL       *FilePath;
   EFI_DEVICE_PATH_PROTOCOL       *OriginalFilePath;
   EFI_DEVICE_PATH_PROTOCOL       *HandleFilePath;
   EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;
   PE_COFF_LOADER_IMAGE_CONTEXT   ImageContext;
-  UINT64                         Tick;
 
-  Tick = 0;
-  PERF_CODE (
-    Tick = GetPerformanceCounter ();
-  );
-   
+  PERF_LOAD_IMAGE_BEGIN (DriverEntry->ImageHandle);
+
   Buffer               = NULL;
   Size                 = 0;
   Fv                   = DriverEntry->Fv;
   NameGuid             = &DriverEntry->FileName;
   FilePath             = DriverEntry->FvFileDevicePath;
@@ -639,12 +635,11 @@ SmmLoadImage (
              &gEfiLoadedImageProtocolGuid,
              EFI_NATIVE_INTERFACE,
              &DriverEntry->SmmLoadedImage
              );
 
-  PERF_START (DriverEntry->ImageHandle, "LoadImage:", NULL, Tick);
-  PERF_END (DriverEntry->ImageHandle, "LoadImage:", NULL, 0);
+  PERF_LOAD_IMAGE_END (DriverEntry->ImageHandle);
 
   //
   // Print the load address and the PDB file name if it is available
   //
 
@@ -907,13 +902,13 @@ SmmDispatcher (
 
       //
       // For each SMM driver, pass NULL as ImageHandle
       //
       RegisterSmramProfileImage (DriverEntry, TRUE);
-      PERF_START (DriverEntry->ImageHandle, "StartImage:", NULL, 0);
+      PERF_START_IMAGE_BEGIN (DriverEntry->ImageHandle);
       Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint)(DriverEntry->ImageHandle, gST);
-      PERF_END (DriverEntry->ImageHandle, "StartImage:", NULL, 0);
+      PERF_START_IMAGE_END (DriverEntry->ImageHandle);
       if (EFI_ERROR(Status)){
         UnregisterSmramProfileImage (DriverEntry, TRUE);
         SmmFreePages(DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);
         //
         // Uninstall LoadedImage
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
index 686b9b45a55..45f40e0e60c 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
@@ -642,11 +642,11 @@ SmmEntryPoint (
   BOOLEAN                     InLegacyBoot;
   BOOLEAN                     IsOverlapped;
   VOID                        *CommunicationBuffer;
   UINTN                       BufferSize;
 
-  PERF_START (NULL, "SMM", NULL, 0) ;
+  PERF_INMODULE_BEGIN ("SMM");
 
   //
   // Update SMST with contents of the SmmEntryContext structure
   //
   gSmmCoreSmst.SmmStartupThisAp      = SmmEntryContext->SmmStartupThisAp;
@@ -737,11 +737,11 @@ SmmEntryPoint (
     // Clear the InSmm flag as we are going to leave SMM
     //
     gSmmCorePrivate->InSmm = FALSE;
   }
 
-  PERF_END (NULL, "SMM", NULL, 0) ;
+  PERF_INMODULE_END ("SMM");
 }
 
 /**
   Install LoadedImage protocol for SMM Core.
 **/
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
index b842d5824ae..59bd1e4c6c0 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
@@ -43,11 +43,11 @@ BmEndOfBdsPerfCode (
   )
 {
   //
   // Record the performance data for End of BDS
   //
-  PERF_END(NULL, "BDS", NULL, 0);
+  PERF_CROSSMODULE_END("BDS");
 
   return ;
 }
 
 /**
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c b/MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c
index 80511814eec..d85b603d64a 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c
@@ -720,27 +720,24 @@ EfiBootManagerConnectAllDefaultConsoles (
 
   Status = EfiBootManagerConnectConsoleVariable (ConOut);
   if (!EFI_ERROR (Status)) {
     OneConnected = TRUE;
   }
-  PERF_START (NULL, "ConOutReady", "BDS", 1);
-  PERF_END   (NULL, "ConOutReady", "BDS", 0);
+  PERF_EVENT ("ConOutReady");
 
   
   Status = EfiBootManagerConnectConsoleVariable (ConIn);
   if (!EFI_ERROR (Status)) {
     OneConnected = TRUE;
   }
-  PERF_START (NULL, "ConInReady", "BDS", 1);
-  PERF_END   (NULL, "ConInReady", "BDS", 0);
+  PERF_EVENT ("ConInReady");
 
   Status = EfiBootManagerConnectConsoleVariable (ErrOut);
   if (!EFI_ERROR (Status)) {
     OneConnected = TRUE;
   }
-  PERF_START (NULL, "ErrOutReady", "BDS", 1);
-  PERF_END   (NULL, "ErrOutReady", "BDS", 0);
+  PERF_EVENT ("ErrOutReady");
 
   SystemTableUpdated = FALSE;
   //
   // Fill console handles in System Table if no console device assignd.
   //
diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
index 3191a986304..acb25abfcd4 100644
--- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
+++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
@@ -723,12 +723,12 @@ BdsEntry (
   BootSuccess     = FALSE;
 
   //
   // Insert the performance probe
   //
-  PERF_END (NULL, "DXE", NULL, 0);
-  PERF_START (NULL, "BDS", NULL, 0);
+  PERF_CROSSMODULE_END("DXE");
+  PERF_CROSSMODULE_BEGIN("BDS");
   DEBUG ((EFI_D_INFO, "[Bds] Entry...\n"));
 
   //
   // Fill in FirmwareVendor and FirmwareRevision from PCDs
   //
@@ -886,13 +886,13 @@ BdsEntry (
   // > Register new Driver#### or Boot####
   // > Register new Key####: e.g.: F12 
   // > Signal ReadyToLock event
   // > Authentication action: 1. connect Auth devices; 2. Identify auto logon user.
   //
-  PERF_START (NULL, "PlatformBootManagerBeforeConsole", "BDS", 0);
+  PERF_INMODULE_BEGIN("PlatformBootManagerBeforeConsole");
   PlatformBootManagerBeforeConsole ();
-  PERF_END   (NULL, "PlatformBootManagerBeforeConsole", "BDS", 0);
+  PERF_INMODULE_END("PlatformBootManagerBeforeConsole");
 
   //
   // Initialize hotkey service
   //
   EfiBootManagerStartHotkeyService (&HotkeyTriggered);
@@ -905,21 +905,21 @@ BdsEntry (
   EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
 
   //
   // Connect consoles
   //
-  PERF_START (NULL, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);
+  PERF_INMODULE_BEGIN("EfiBootManagerConnectAllDefaultConsoles");
   if (PcdGetBool (PcdConInConnectOnDemand)) {
     EfiBootManagerConnectConsoleVariable (ConOut);
     EfiBootManagerConnectConsoleVariable (ErrOut);
     //
     // Do not connect ConIn devices when lazy ConIn feature is ON.
     //
   } else {
     EfiBootManagerConnectAllDefaultConsoles ();
   }
-  PERF_END   (NULL, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);
+  PERF_INMODULE_END("EfiBootManagerConnectAllDefaultConsoles");
 
   //
   // Do the platform specific action after the console is ready
   // Possible things that can be done in PlatformBootManagerAfterConsole:
   // > Console post action:
@@ -928,13 +928,13 @@ BdsEntry (
   // > Run diagnostics like memory testing
   // > Connect certain devices
   // > Dispatch aditional option roms
   // > Special boot: e.g.: USB boot, enter UI
   // 
-  PERF_START (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);
+  PERF_INMODULE_BEGIN("PlatformBootManagerAfterConsole");
   PlatformBootManagerAfterConsole ();
-  PERF_END   (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);
+  PERF_INMODULE_END("PlatformBootManagerAfterConsole");
   //
   // Boot to Boot Manager Menu when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
   //
   DataSize = sizeof (UINT64);
   Status = gRT->GetVariable (
@@ -1023,14 +1023,13 @@ BdsEntry (
     EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
 
     //
     // Execute Key####
     //
-    PERF_START (NULL, "BdsWait", "BDS", 0);
+    PERF_INMODULE_BEGIN ("BdsWait");
     BdsWait (HotkeyTriggered);
-    PERF_END   (NULL, "BdsWait", "BDS", 0);
-
+    PERF_INMODULE_END ("BdsWait");
     //
     // BdsReadKeys() can be removed after all keyboard drivers invoke callback in timer callback.
     //
     BdsReadKeys ();
 
-- 
2.14.3.windows.1



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch V2 8/9] SecurityPkg: Use new added Perf macros
  2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
                   ` (6 preceding siblings ...)
  2018-06-22  8:56 ` [patch V2 7/9] MdeModulePkg: Use new added Perf macros Dandan Bi
@ 2018-06-22  8:56 ` Dandan Bi
  2018-07-03 23:29   ` Zhang, Chao B
  2018-06-22  8:56 ` [patch V2 9/9] UefiCpuPkg: " Dandan Bi
  2018-06-25  8:02 ` [patch V2 0/9] Add new " Gao, Liming
  9 siblings, 1 reply; 12+ messages in thread
From: Dandan Bi @ 2018-06-22  8:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Chao Zhang

Replace old Perf macros with the new added ones.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 .../DxeRsa2048Sha256GuidedSectionExtractLib.c            | 16 ++++++++--------
 .../PeiRsa2048Sha256GuidedSectionExtractLib.c            | 16 ++++++++--------
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c b/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c
index 39768fbac22..d6f4207a506 100644
--- a/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c
+++ b/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c
@@ -161,13 +161,13 @@ Rsa2048Sha256GuidedSectionHandler (
     // Get the RSA 2048 SHA 256 information.
     //
     CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION2_HEADER *) InputSection)->CertBlockRsa2048Sha256;
     OutputBufferSize       = SECTION2_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
     if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
-      PERF_START (NULL, "RsaCopy", "DXE", 0);
+      PERF_INMODULE_BEGIN ("DxeRsaCopy");
       CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER), OutputBufferSize);
-      PERF_END (NULL, "RsaCopy", "DXE", 0);
+      PERF_INMODULE_END ("DxeRsaCopy");
     } else {
       *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
     }
 
     //
@@ -189,13 +189,13 @@ Rsa2048Sha256GuidedSectionHandler (
     // Get the RSA 2048 SHA 256 information.
     //
     CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION_HEADER *)InputSection)->CertBlockRsa2048Sha256;
     OutputBufferSize       = SECTION_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION_HEADER);
     if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
-      PERF_START (NULL, "RsaCopy", "DXE", 0);
+      PERF_INMODULE_BEGIN ("DxeRsaCopy");
       CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER), OutputBufferSize);
-      PERF_END (NULL, "RsaCopy", "DXE", 0);
+      PERF_INMODULE_END ("DxeRsaCopy");
     } else {
       *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER);
     }
 
     //
@@ -325,13 +325,13 @@ Rsa2048Sha256GuidedSectionHandler (
   if (!CryptoStatus) {
     DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Init() failed\n"));
     *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
     goto Done;
   }
-  PERF_START (NULL, "RsaShaData", "DXE", 0);
+  PERF_INMODULE_BEGIN ("DxeRsaShaData");
   CryptoStatus = Sha256Update (HashContext, *OutputBuffer, OutputBufferSize);
-  PERF_END (NULL, "RsaShaData", "DXE", 0);
+  PERF_INMODULE_END ("DxeRsaShaData");
   if (!CryptoStatus) {
     DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Update() failed\n"));
     *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
     goto Done;
   }
@@ -343,19 +343,19 @@ Rsa2048Sha256GuidedSectionHandler (
   }
 
   //
   // Verify the RSA 2048 SHA 256 signature.
   //
-  PERF_START (NULL, "RsaVerify", "DXE", 0);
+  PERF_INMODULE_BEGIN ("DxeRsaVerify");
   CryptoStatus = RsaPkcs1Verify (
                    Rsa, 
                    Digest, 
                    SHA256_DIGEST_SIZE, 
                    CertBlockRsa2048Sha256->Signature, 
                    sizeof (CertBlockRsa2048Sha256->Signature)
                    );
-  PERF_END (NULL, "RsaVerify", "DXE", 0);
+  PERF_INMODULE_END ("DxeRsaVerify");
   if (!CryptoStatus) {
     //
     // If RSA 2048 SHA 256 signature verification fails, AUTH tested failed bit is set.
     //
     DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaPkcs1Verify() failed\n"));
diff --git a/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c b/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c
index ba1c700ad03..2272308ddca 100644
--- a/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c
+++ b/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c
@@ -158,13 +158,13 @@ Rsa2048Sha256GuidedSectionHandler (
     // Get the RSA 2048 SHA 256 information.
     //
     CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION2_HEADER *) InputSection)->CertBlockRsa2048Sha256;
     OutputBufferSize       = SECTION2_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
     if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
-      PERF_START (NULL, "RsaCopy", "PEI", 0);
+      PERF_INMODULE_BEGIN ("PeiRsaCopy");
       CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER), OutputBufferSize);
-      PERF_END (NULL, "RsaCopy", "PEI", 0);
+      PERF_INMODULE_END ("PeiRsaCopy");
     } else {
       *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
     }
 
     //
@@ -186,13 +186,13 @@ Rsa2048Sha256GuidedSectionHandler (
     // Get the RSA 2048 SHA 256 information.
     //
     CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION_HEADER *)InputSection)->CertBlockRsa2048Sha256;
     OutputBufferSize       = SECTION_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION_HEADER);
     if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
-      PERF_START (NULL, "RsaCopy", "PEI", 0);
+      PERF_INMODULE_BEGIN ("PeiRsaCopy");
       CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER), OutputBufferSize);
-      PERF_END (NULL, "RsaCopy", "PEI", 0);
+      PERF_INMODULE_END ("PeiRsaCopy");
     } else {
       *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER);
     }
 
     //
@@ -309,13 +309,13 @@ Rsa2048Sha256GuidedSectionHandler (
   if (!CryptoStatus) {
     DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Sha256Init() failed\n"));
     *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
     goto Done;
   }
-  PERF_START (NULL, "RsaShaData", "PEI", 0);
+  PERF_INMODULE_BEGIN ("PeiRsaShaData");
   CryptoStatus = Sha256Update (HashContext, *OutputBuffer, OutputBufferSize);
-  PERF_END (NULL, "RsaShaData", "PEI", 0);
+  PERF_INMODULE_END ("PeiRsaShaData");
   if (!CryptoStatus) {
     DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Sha256Update() failed\n"));
     *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
     goto Done;
   }
@@ -327,19 +327,19 @@ Rsa2048Sha256GuidedSectionHandler (
   }
 
   //
   // Verify the RSA 2048 SHA 256 signature.
   //
-  PERF_START (NULL, "RsaVerify", "PEI", 0);
+  PERF_INMODULE_BEGIN ("PeiRsaVerify");
   CryptoStatus = RsaPkcs1Verify (
                    Rsa, 
                    Digest, 
                    SHA256_DIGEST_SIZE, 
                    CertBlockRsa2048Sha256->Signature, 
                    sizeof (CertBlockRsa2048Sha256->Signature)
                    );
-  PERF_END (NULL, "RsaVerify", "PEI", 0);
+  PERF_INMODULE_END ("PeiRsaVerify");
   if (!CryptoStatus) {
     //
     // If RSA 2048 SHA 256 signature verification fails, AUTH tested failed bit is set.
     //
     DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: RsaPkcs1Verify() failed\n"));
-- 
2.14.3.windows.1



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch V2 9/9] UefiCpuPkg: Use new added Perf macros
  2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
                   ` (7 preceding siblings ...)
  2018-06-22  8:56 ` [patch V2 8/9] SecurityPkg: " Dandan Bi
@ 2018-06-22  8:56 ` Dandan Bi
  2018-06-25  8:02 ` [patch V2 0/9] Add new " Gao, Liming
  9 siblings, 0 replies; 12+ messages in thread
From: Dandan Bi @ 2018-06-22  8:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Eric Dong

Replace old Perf macros with the new added ones.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
index 4ae168a2c3c..d3cb07cd2d0 100644
--- a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
+++ b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
@@ -428,21 +428,21 @@ S3ResumeBootOs (
   // NOTE: Because Debug Timer interrupt and system interrupts will be disabled 
   // in BootScriptExecuteDxe, the rest code in S3ResumeBootOs() cannot be halted
   // by soft debugger.
   //
 
-  PERF_END (NULL, "ScriptExec", NULL, 0);
+  PERF_INMODULE_END ("ScriptExec");
 
   //
   // Install BootScriptDonePpi
   //
-  PERF_START_EX (NULL, "BootScriptDonePpi", NULL, 0, PERF_INMODULE_START_ID);
+  PERF_INMODULE_BEGIN ("BootScriptDonePpi");
 
   Status = PeiServicesInstallPpi (&mPpiListPostScriptTable);
   ASSERT_EFI_ERROR (Status);
 
-  PERF_END_EX (NULL, "BootScriptDonePpi", NULL, 0, PERF_INMODULE_END_ID);
+  PERF_INMODULE_END ("BootScriptDonePpi");
 
   //
   // Get ACPI Table Address
   //
   Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable));
@@ -462,26 +462,26 @@ S3ResumeBootOs (
   }
 
   //
   // Install EndOfPeiPpi
   //
-  PERF_START_EX (NULL, "EndOfPeiPpi", NULL, 0, PERF_INMODULE_START_ID);
+  PERF_INMODULE_BEGIN("EndOfPeiPpi");
 
   Status = PeiServicesInstallPpi (&mPpiListEndOfPeiTable);
   ASSERT_EFI_ERROR (Status);
 
-  PERF_END_EX (NULL, "EndOfPeiPpi", NULL, 0, PERF_INMODULE_END_ID);
+  PERF_INMODULE_END("EndOfPeiPpi");
 
-  PERF_START_EX (NULL, "EndOfS3Resume", NULL, 0, PERF_INMODULE_START_ID);
+  PERF_INMODULE_BEGIN("EndOfS3Resume");
 
   DEBUG ((DEBUG_INFO, "Signal EndOfS3Resume\n"));
   //
   // Signal EndOfS3Resume to SMM.
   //
   SignalToSmmByCommunication (&gEdkiiEndOfS3ResumeGuid);
 
-  PERF_END_EX (NULL, "EndOfS3Resume", NULL, 0, PERF_INMODULE_END_ID);
+  PERF_INMODULE_END ("EndOfS3Resume");
 
   //
   // report status code on S3 resume
   //
   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE);
@@ -878,11 +878,11 @@ S3ResumeExecuteBootScript (
   //
   // Report Status Code to indicate S3 boot script execution
   //
   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_S3_BOOT_SCRIPT);
 
-  PERF_START (NULL, "ScriptExec", NULL, 0);
+  PERF_INMODULE_BEGIN ("ScriptExec");
 
   if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
     //
     // X64 S3 Resume
     //
-- 
2.14.3.windows.1



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [patch V2 0/9] Add new Perf macros
  2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
                   ` (8 preceding siblings ...)
  2018-06-22  8:56 ` [patch V2 9/9] UefiCpuPkg: " Dandan Bi
@ 2018-06-25  8:02 ` Gao, Liming
  9 siblings, 0 replies; 12+ messages in thread
From: Gao, Liming @ 2018-06-25  8:02 UTC (permalink / raw)
  To: Bi, Dandan, edk2-devel@lists.01.org; +Cc: Zeng, Star, Kinney, Michael D

Reviewed-by: Liming Gao <liming.gao@intel.com>

>-----Original Message-----
>From: Bi, Dandan
>Sent: Friday, June 22, 2018 4:56 PM
>To: edk2-devel@lists.01.org
>Cc: Gao, Liming <liming.gao@intel.com>; Zeng, Star <star.zeng@intel.com>;
>Kinney, Michael D <michael.d.kinney@intel.com>
>Subject: [patch V2 0/9] Add new Perf macros
>
>Add a group of new Perf macros in performance library for performance
>logging. Which will simplify the usage model of performance measurement.
>And also introduce new control functionality to disable different
>perf types.
>
>Patch 1-2:
>Add a new internal protocol PERFORMANCE_MEASUREMENT_PROTOCOL,
>which can be used to log performance info.
>
>Patch 3-5:
>Add new Perf macros and update library instances in MdeModulePkg
>to for the implementation of new perf macros.
>
>Patch 6:
>Enhance the logic in DP tool since some new record and control
>functionality are introduced by new Perf macros.
>
>Patch 7-9:
>update the consumer codes in core to use the new Perf macros.
>
>Unit test:
>1.DP tool can dump the performance data saved in the ACPI FPDT
>  when set PcdEdkiiFpdtStringRecordEnableOnly to TRUE/FALSE.
>2.Can disable specific knids of Perf entry through
>  setting PcdPerformanceLibraryPropertyMask.
>
>V2:
>Patch 5: Share the common logics of creating FPDT record for
>new added Perf macros and existing Perf macros.
>
>Cc: Liming Gao <liming.gao@intel.com>
>Cc: Star Zeng <star.zeng@intel.com>
>Cc: Michael Kinney <michael.d.kinney@intel.com>
>
>Dandan Bi (9):
>  MdeModulePkg: Add PERFORMANCE_MEASUREMENT_PROTOCOL
>  MdeModulePkg: Update Performance instances to use new protocol
>  MdePkg/PerformanceLib.h: Add new Perf macros
>  MdeModulePkg/ExtendedFirmwarePerf: Remove PerfId definitions
>  MdeModulePkg: Update performance library instances
>  ShellPkg/dp: Update dp tool to parse new Perf record
>  MdeModulePkg: Use new added Perf macros
>  SecurityPkg: Use new added Perf macros
>  UefiCpuPkg: Use new added Perf macros
>
> MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c      |    7 +
> MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c            |    8 +-
> MdeModulePkg/Core/Dxe/Hand/DriverSupport.c         |    8 +-
> MdeModulePkg/Core/Dxe/Image/Image.c                |   30 +-
> MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c      |    8 +-
> MdeModulePkg/Core/Pei/PeiMain/PeiMain.c            |   17 +-
> MdeModulePkg/Core/PiSmmCore/Dispatcher.c           |   15 +-
> MdeModulePkg/Core/PiSmmCore/PiSmmCore.c            |    4 +-
> .../Include/Guid/ExtendedFirmwarePerformance.h     |   31 -
> MdeModulePkg/Include/Guid/PerformanceMeasurement.h |   91 ++
> .../DxeCorePerformanceLib/DxeCorePerformanceLib.c  | 1183
>+++++++++++---------
> .../DxeCorePerformanceLib.inf                      |    7 +-
> .../DxeCorePerformanceLibInternal.h                |  217 +---
> .../Library/DxePerformanceLib/DxePerformanceLib.c  |  193 ++--
> .../DxePerformanceLib/DxePerformanceLib.inf        |    5 +-
> .../Library/PeiPerformanceLib/PeiPerformanceLib.c  |  632 +++++++----
> .../SmmCorePerformanceLib/SmmCorePerformanceLib.c  |  960 ++++++++---
>-----
> .../SmmCorePerformanceLib.inf                      |    7 +-
> .../SmmCorePerformanceLibInternal.h                |  215 +---
> .../Library/SmmPerformanceLib/SmmPerformanceLib.c  |  198 ++--
> .../SmmPerformanceLib/SmmPerformanceLib.inf        |    5 +-
> MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c   |    2 +-
> .../Library/UefiBootManagerLib/BmConsole.c         |    9 +-
> MdeModulePkg/MdeModulePkg.dec                      |    3 +
> MdeModulePkg/Universal/BdsDxe/BdsEntry.c           |   21 +-
> MdePkg/Include/Library/PerformanceLib.h            |  408 ++++++-
> .../BasePerformanceLibNull/PerformanceLib.c        |   57 +-
> MdePkg/MdePkg.dec                                  |    9 +-
> MdePkg/MdePkg.uni                                  |    6 +
> .../DxeRsa2048Sha256GuidedSectionExtractLib.c      |   16 +-
> .../PeiRsa2048Sha256GuidedSectionExtractLib.c      |   16 +-
> ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c      |   75 +-
> ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h      |    1 +
> .../DynamicCommand/DpDynamicCommand/DpInternal.h   |   14 +
> ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c |    4 +-
> .../DynamicCommand/DpDynamicCommand/DpUtilities.c  |   31 +
> UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c  |   16 +-
> 37 files changed, 2600 insertions(+), 1929 deletions(-)
> create mode 100644
>MdeModulePkg/Include/Guid/PerformanceMeasurement.h
>
>--
>2.14.3.windows.1



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch V2 8/9] SecurityPkg: Use new added Perf macros
  2018-06-22  8:56 ` [patch V2 8/9] SecurityPkg: " Dandan Bi
@ 2018-07-03 23:29   ` Zhang, Chao B
  0 siblings, 0 replies; 12+ messages in thread
From: Zhang, Chao B @ 2018-07-03 23:29 UTC (permalink / raw)
  To: Bi, Dandan, edk2-devel@lists.01.org; +Cc: Gao, Liming

HI  Dandan :
   That patch is good to me. Reviewed-by: Chao Zhang <chao.b.zhang@intel.com>
-----Original Message-----
From: Bi, Dandan 
Sent: Friday, June 22, 2018 4:56 PM
To: edk2-devel@lists.01.org
Cc: Gao, Liming <liming.gao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: [patch V2 8/9] SecurityPkg: Use new added Perf macros

Replace old Perf macros with the new added ones.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 .../DxeRsa2048Sha256GuidedSectionExtractLib.c            | 16 ++++++++--------
 .../PeiRsa2048Sha256GuidedSectionExtractLib.c            | 16 ++++++++--------
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c b/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c
index 39768fbac22..d6f4207a506 100644
--- a/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c
+++ b/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa
+++ 2048Sha256GuidedSectionExtractLib.c
@@ -161,13 +161,13 @@ Rsa2048Sha256GuidedSectionHandler (
     // Get the RSA 2048 SHA 256 information.
     //
     CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION2_HEADER *) InputSection)->CertBlockRsa2048Sha256;
     OutputBufferSize       = SECTION2_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
     if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
-      PERF_START (NULL, "RsaCopy", "DXE", 0);
+      PERF_INMODULE_BEGIN ("DxeRsaCopy");
       CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER), OutputBufferSize);
-      PERF_END (NULL, "RsaCopy", "DXE", 0);
+      PERF_INMODULE_END ("DxeRsaCopy");
     } else {
       *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
     }
 
     //
@@ -189,13 +189,13 @@ Rsa2048Sha256GuidedSectionHandler (
     // Get the RSA 2048 SHA 256 information.
     //
     CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION_HEADER *)InputSection)->CertBlockRsa2048Sha256;
     OutputBufferSize       = SECTION_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION_HEADER);
     if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
-      PERF_START (NULL, "RsaCopy", "DXE", 0);
+      PERF_INMODULE_BEGIN ("DxeRsaCopy");
       CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER), OutputBufferSize);
-      PERF_END (NULL, "RsaCopy", "DXE", 0);
+      PERF_INMODULE_END ("DxeRsaCopy");
     } else {
       *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER);
     }
 
     //
@@ -325,13 +325,13 @@ Rsa2048Sha256GuidedSectionHandler (
   if (!CryptoStatus) {
     DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Init() failed\n"));
     *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
     goto Done;
   }
-  PERF_START (NULL, "RsaShaData", "DXE", 0);
+  PERF_INMODULE_BEGIN ("DxeRsaShaData");
   CryptoStatus = Sha256Update (HashContext, *OutputBuffer, OutputBufferSize);
-  PERF_END (NULL, "RsaShaData", "DXE", 0);
+  PERF_INMODULE_END ("DxeRsaShaData");
   if (!CryptoStatus) {
     DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Update() failed\n"));
     *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
     goto Done;
   }
@@ -343,19 +343,19 @@ Rsa2048Sha256GuidedSectionHandler (
   }
 
   //
   // Verify the RSA 2048 SHA 256 signature.
   //
-  PERF_START (NULL, "RsaVerify", "DXE", 0);
+  PERF_INMODULE_BEGIN ("DxeRsaVerify");
   CryptoStatus = RsaPkcs1Verify (
                    Rsa, 
                    Digest, 
                    SHA256_DIGEST_SIZE, 
                    CertBlockRsa2048Sha256->Signature, 
                    sizeof (CertBlockRsa2048Sha256->Signature)
                    );
-  PERF_END (NULL, "RsaVerify", "DXE", 0);
+  PERF_INMODULE_END ("DxeRsaVerify");
   if (!CryptoStatus) {
     //
     // If RSA 2048 SHA 256 signature verification fails, AUTH tested failed bit is set.
     //
     DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaPkcs1Verify() failed\n")); diff --git a/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c b/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c
index ba1c700ad03..2272308ddca 100644
--- a/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c
+++ b/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa
+++ 2048Sha256GuidedSectionExtractLib.c
@@ -158,13 +158,13 @@ Rsa2048Sha256GuidedSectionHandler (
     // Get the RSA 2048 SHA 256 information.
     //
     CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION2_HEADER *) InputSection)->CertBlockRsa2048Sha256;
     OutputBufferSize       = SECTION2_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
     if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
-      PERF_START (NULL, "RsaCopy", "PEI", 0);
+      PERF_INMODULE_BEGIN ("PeiRsaCopy");
       CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER), OutputBufferSize);
-      PERF_END (NULL, "RsaCopy", "PEI", 0);
+      PERF_INMODULE_END ("PeiRsaCopy");
     } else {
       *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
     }
 
     //
@@ -186,13 +186,13 @@ Rsa2048Sha256GuidedSectionHandler (
     // Get the RSA 2048 SHA 256 information.
     //
     CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION_HEADER *)InputSection)->CertBlockRsa2048Sha256;
     OutputBufferSize       = SECTION_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION_HEADER);
     if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
-      PERF_START (NULL, "RsaCopy", "PEI", 0);
+      PERF_INMODULE_BEGIN ("PeiRsaCopy");
       CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER), OutputBufferSize);
-      PERF_END (NULL, "RsaCopy", "PEI", 0);
+      PERF_INMODULE_END ("PeiRsaCopy");
     } else {
       *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER);
     }
 
     //
@@ -309,13 +309,13 @@ Rsa2048Sha256GuidedSectionHandler (
   if (!CryptoStatus) {
     DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Sha256Init() failed\n"));
     *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
     goto Done;
   }
-  PERF_START (NULL, "RsaShaData", "PEI", 0);
+  PERF_INMODULE_BEGIN ("PeiRsaShaData");
   CryptoStatus = Sha256Update (HashContext, *OutputBuffer, OutputBufferSize);
-  PERF_END (NULL, "RsaShaData", "PEI", 0);
+  PERF_INMODULE_END ("PeiRsaShaData");
   if (!CryptoStatus) {
     DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Sha256Update() failed\n"));
     *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
     goto Done;
   }
@@ -327,19 +327,19 @@ Rsa2048Sha256GuidedSectionHandler (
   }
 
   //
   // Verify the RSA 2048 SHA 256 signature.
   //
-  PERF_START (NULL, "RsaVerify", "PEI", 0);
+  PERF_INMODULE_BEGIN ("PeiRsaVerify");
   CryptoStatus = RsaPkcs1Verify (
                    Rsa, 
                    Digest, 
                    SHA256_DIGEST_SIZE, 
                    CertBlockRsa2048Sha256->Signature, 
                    sizeof (CertBlockRsa2048Sha256->Signature)
                    );
-  PERF_END (NULL, "RsaVerify", "PEI", 0);
+  PERF_INMODULE_END ("PeiRsaVerify");
   if (!CryptoStatus) {
     //
     // If RSA 2048 SHA 256 signature verification fails, AUTH tested failed bit is set.
     //
     DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: RsaPkcs1Verify() failed\n"));
--
2.14.3.windows.1



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2018-07-03 23:29 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-06-22  8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
2018-06-22  8:56 ` [patch V2 1/9] MdeModulePkg: Add PERFORMANCE_MEASUREMENT_PROTOCOL Dandan Bi
2018-06-22  8:56 ` [patch V2 2/9] MdeModulePkg: Update Performance instances to use new protocol Dandan Bi
2018-06-22  8:56 ` [patch V2 3/9] MdePkg/PerformanceLib.h: Add new Perf macros Dandan Bi
2018-06-22  8:56 ` [patch V2 4/9] MdeModulePkg/ExtendedFirmwarePerf: Remove PerfId definitions Dandan Bi
2018-06-22  8:56 ` [patch V2 5/9] MdeModulePkg: Update performance library instances Dandan Bi
2018-06-22  8:56 ` [patch V2 6/9] ShellPkg/dp: Update dp tool to parse new Perf record Dandan Bi
2018-06-22  8:56 ` [patch V2 7/9] MdeModulePkg: Use new added Perf macros Dandan Bi
2018-06-22  8:56 ` [patch V2 8/9] SecurityPkg: " Dandan Bi
2018-07-03 23:29   ` Zhang, Chao B
2018-06-22  8:56 ` [patch V2 9/9] UefiCpuPkg: " Dandan Bi
2018-06-25  8:02 ` [patch V2 0/9] Add new " Gao, Liming

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox