Libraries and utilities for instrumenting regions of code and measuring their perform...
authordarylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 23 Apr 2010 17:00:32 +0000 (17:00 +0000)
committerdarylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 23 Apr 2010 17:00:32 +0000 (17:00 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10417 6f19259b-4bc3-4df7-8a09-765794883524

16 files changed:
PerformancePkg/Dp_App/Dp.c [new file with mode: 0644]
PerformancePkg/Dp_App/Dp.h [new file with mode: 0644]
PerformancePkg/Dp_App/Dp.inf [new file with mode: 0644]
PerformancePkg/Dp_App/DpInternal.h [new file with mode: 0644]
PerformancePkg/Dp_App/DpProfile.c [new file with mode: 0644]
PerformancePkg/Dp_App/DpStrings.uni [new file with mode: 0644]
PerformancePkg/Dp_App/DpTrace.c [new file with mode: 0644]
PerformancePkg/Dp_App/DpUtilities.c [new file with mode: 0644]
PerformancePkg/Dp_App/Literals.c [new file with mode: 0644]
PerformancePkg/Dp_App/Literals.h [new file with mode: 0644]
PerformancePkg/Include/Ich/GenericIch.h [new file with mode: 0644]
PerformancePkg/Include/PerformanceTokens.h [new file with mode: 0644]
PerformancePkg/Library/TscTimerLib/TscTimerLib.c [new file with mode: 0644]
PerformancePkg/Library/TscTimerLib/TscTimerLib.inf [new file with mode: 0644]
PerformancePkg/PerformancePkg.dec [new file with mode: 0644]
PerformancePkg/PerformancePkg.dsc [new file with mode: 0644]

diff --git a/PerformancePkg/Dp_App/Dp.c b/PerformancePkg/Dp_App/Dp.c
new file mode 100644 (file)
index 0000000..f5d0bda
--- /dev/null
@@ -0,0 +1,339 @@
+/** @file\r
+  * Shell application for Displaying Performance Metrics.\r
+  *\r
+  * The Dp application reads performance data and presents it in several\r
+  * different formats depending upon the needs of the user.  Both\r
+  * Trace and Measured Profiling information is processed and presented.\r
+  *\r
+  * Dp uses the "PerformanceLib" to read the measurement records.\r
+  * The "TimerLib" provides information about the timer, such as frequency,\r
+  * beginning, and ending counter values.\r
+  * Measurement records contain identifying information (Handle, Token, Module)\r
+  * and start and end time values.\r
+  * Dp uses this information to group records in different ways.  It also uses\r
+  * timer information to calculate elapsed time for each measurement.\r
+  *\r
+  * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+  * This program and the accompanying materials\r
+  * are licensed and made available under the terms and conditions of the BSD License\r
+  * which accompanies this distribution.  The full text of the license may be found at\r
+  * http://opensource.org/licenses/bsd-license.php\r
+  *\r
+  * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include <Library/UefiApplicationEntryPoint.h>\r
+#include <Library/ShellLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Guid/Performance.h>\r
+\r
+#include <PerformanceTokens.h>\r
+#include "Dp.h"\r
+#include "Literals.h"\r
+#include "DpInternal.h"\r
+\r
+//\r
+/// Module-Global Variables\r
+/// @{\r
+EFI_HII_HANDLE   gHiiHandle;\r
+CHAR16           *mPrintTokenBuffer = NULL;\r
+CHAR16           mGaugeString[DXE_PERFORMANCE_STRING_SIZE];\r
+CHAR16           mUnicodeToken[PERF_TOKEN_LENGTH + 1];\r
+UINT64           mInterestThreshold;\r
+\r
+PERF_SUMMARY_DATA SummaryData = { 0 };    ///< Create the SummaryData structure and init. to ZERO.\r
+\r
+/// Timer Specific Information.\r
+TIMER_INFO TimerInfo;\r
+\r
+/// Items for which to gather cumulative statistics.\r
+PERF_CUM_DATA CumData[] = {\r
+  PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK),\r
+  PERF_INIT_CUM_DATA (START_IMAGE_TOK),\r
+  PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK),\r
+  PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK)\r
+};\r
+\r
+/// Number of items for which we are gathering cumulative statistics.\r
+UINT32 const      NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA);\r
+\r
+SHELL_PARAM_ITEM  DpParamList[] = {\r
+  {STR_DP_OPTION_QH, TypeFlag},   // -?   Help\r
+  {STR_DP_OPTION_LH, TypeFlag},   // -h   Help\r
+  {STR_DP_OPTION_UH, TypeFlag},   // -H   Help\r
+  {STR_DP_OPTION_LV, TypeFlag},   // -v   Verbose Mode\r
+  {STR_DP_OPTION_UA, TypeFlag},   // -A   All, Cooked\r
+  {STR_DP_OPTION_UR, TypeFlag},   // -R   RAW All\r
+  {STR_DP_OPTION_LS, TypeFlag},   // -s   Summary\r
+#if PROFILING_IMPLEMENTED\r
+  {STR_DP_OPTION_UP, TypeFlag},   // -P   Dump Profile Data\r
+  {STR_DP_OPTION_UT, TypeFlag},   // -T   Dump Trace Data\r
+#endif\r
+  {STR_DP_OPTION_LX, TypeFlag},   // -x   eXclude Cumulative Items\r
+  {STR_DP_OPTION_LN, TypeValue},  // -n # Number of records to display for A and R\r
+  {STR_DP_OPTION_LT, TypeValue},  // -t # Threshold of interest\r
+  {NULL, TypeMax}\r
+  };\r
+\r
+/// @}\r
+\r
+/// Display Usage and Help information.\r
+VOID\r
+ShowHelp( void )\r
+{\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_HEAD));\r
+#if PROFILING_IMPLEMENTED\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS));\r
+#else\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS_2));\r
+#endif // PROFILING_IMPLEMENTED\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_PAGINATE));\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_VERBOSE));\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_EXCLUDE));\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_STAT));\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_ALL));\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_RAW));\r
+#if PROFILING_IMPLEMENTED\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_TRACE));\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_PROFILE));\r
+#endif // PROFILING_IMPLEMENTED\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_THRESHOLD));\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_COUNT));\r
+  PrintToken (STRING_TOKEN (STR_DP_HELP_HELP));\r
+  Print(L"\n");\r
+}\r
+\r
+/// Display the trailing Verbose information.\r
+VOID\r
+DumpStatistics( void )\r
+{\r
+  EFI_STRING                StringPtr;\r
+\r
+  StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);\r
+  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+              (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMTRACE),       SummaryData.NumTrace);\r
+  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE),  SummaryData.NumIncomplete);\r
+  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPHASES),      SummaryData.NumSummary);\r
+  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMHANDLES),     SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);\r
+  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPEIMS),       SummaryData.NumPEIMs);\r
+  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMGLOBALS),     SummaryData.NumGlobal);\r
+#if PROFILING_IMPLEMENTED\r
+  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPROFILE),     SummaryData.NumProfile);\r
+#endif // PROFILING_IMPLEMENTED\r
+}\r
+\r
+/** Dump performance data.\r
+  *\r
+  * @param[in]  ImageHandle     The image handle.\r
+  * @param[in]  SystemTable     The system table.\r
+  *\r
+  * @retval EFI_SUCCESS            Command completed successfully.\r
+  * @retval EFI_INVALID_PARAMETER  Command usage error.\r
+  * @retval value                  Unknown error.\r
+  *\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeDp (\r
+  IN EFI_HANDLE               ImageHandle,\r
+  IN EFI_SYSTEM_TABLE         *SystemTable\r
+  )\r
+{\r
+  UINT64                    Freq;\r
+  UINT64                    Ticker;\r
+\r
+  LIST_ENTRY                *ParamPackage;\r
+  CONST CHAR16              *CmdLineArg;\r
+  EFI_STRING                StringPtr;\r
+  UINTN                     Number2Display;\r
+\r
+  EFI_STATUS                Status;\r
+  BOOLEAN                   SummaryMode     = FALSE;\r
+  BOOLEAN                   VerboseMode     = FALSE;\r
+  BOOLEAN                   AllMode         = FALSE;\r
+  BOOLEAN                   RawMode         = FALSE;\r
+  BOOLEAN                   TraceMode       = FALSE;\r
+  BOOLEAN                   ProfileMode     = FALSE;\r
+  BOOLEAN                   ExcludeMode     = FALSE;\r
+\r
+\r
+  // Get DP's entry time as soon as possible.\r
+  // This is used as the Shell-Phase end time.\r
+  //\r
+  Ticker  = GetPerformanceCounter ();\r
+\r
+  // Register our string package with HII and return the handle to it.\r
+  //\r
+  gHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, DPStrings, NULL);\r
+  ASSERT (gHiiHandle != NULL);\r
+\r
+/****************************************************************************\r
+****            Process Command Line arguments                           ****\r
+****************************************************************************/\r
+  Status = ShellCommandLineParse (DpParamList, &ParamPackage, NULL, TRUE);\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    PrintToken (STRING_TOKEN (STR_DP_INVALID_ARG));\r
+    ShowHelp();\r
+  }\r
+  else {\r
+    if (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_QH)  ||\r
+        ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LH)  ||\r
+        ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UH))\r
+    {\r
+      ShowHelp();\r
+    }\r
+    else {\r
+      // Boolean Options\r
+      VerboseMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LV));\r
+      SummaryMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_US) ||\r
+                     ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LS));\r
+      AllMode     = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UA));\r
+      RawMode     = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UR));\r
+#if PROFILING_IMPLEMENTED\r
+      TraceMode   = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UT));\r
+      ProfileMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UP));\r
+#endif  // PROFILING_IMPLEMENTED\r
+      ExcludeMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LX));\r
+\r
+      // Options with Values\r
+      CmdLineArg  = ( ShellCommandLineGetValue (ParamPackage, STR_DP_OPTION_LN));\r
+      if (CmdLineArg == NULL) {\r
+        Number2Display = DEFAULT_DISPLAYCOUNT;\r
+      }\r
+      else {\r
+        Number2Display = StrDecimalToUintn(CmdLineArg);\r
+        if (Number2Display == 0) {\r
+          Number2Display = MAXIMUM_DISPLAYCOUNT;\r
+        }\r
+      }\r
+      CmdLineArg  = (ShellCommandLineGetValue (ParamPackage, STR_DP_OPTION_LT));\r
+      if (CmdLineArg == NULL) {\r
+        mInterestThreshold = DEFAULT_THRESHOLD;  // 1ms := 1,000 us\r
+      }\r
+      else {\r
+        mInterestThreshold = StrDecimalToUint64(CmdLineArg);\r
+      }\r
+      // Handle Flag combinations and default behaviors\r
+      // If both TraceMode and ProfileMode are FALSE, set them both to TRUE\r
+      if ((! TraceMode) && (! ProfileMode)) {\r
+        TraceMode   = TRUE;\r
+#if PROFILING_IMPLEMENTED\r
+        ProfileMode = TRUE;\r
+#endif  // PROFILING_IMPLEMENTED\r
+      }\r
+\r
+/****************************************************************************\r
+****            Timer specific processing                                ****\r
+****************************************************************************/\r
+      // Get the Performance counter characteristics:\r
+      //          Freq = Frequency in Hz\r
+      //    StartCount = Value loaded into the counter when it starts counting\r
+      //      EndCount = Value counter counts to before it needs to be reset\r
+      //\r
+      Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);\r
+\r
+      // Convert the Frequency from Hz to KHz\r
+      TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);\r
+\r
+      // Determine in which direction the performance counter counts.\r
+      TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);\r
+\r
+/****************************************************************************\r
+****            Print heading                                            ****\r
+****************************************************************************/\r
+      // print DP's build version\r
+      PrintToken (STRING_TOKEN (STR_DP_BUILD_REVISION), DP_MAJOR_VERSION, DP_MINOR_VERSION);\r
+\r
+      // print performance timer characteristics\r
+      PrintToken (STRING_TOKEN (STR_DP_KHZ), TimerInfo.Frequency);         // Print Timer frequency in KHz\r
+\r
+      if ((VerboseMode)   &&\r
+          (! RawMode)\r
+         ) {\r
+        StringPtr = HiiGetString (gHiiHandle,\r
+                      TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN),\r
+                      NULL);\r
+        ASSERT (StringPtr != NULL);\r
+        PrintToken (STRING_TOKEN (STR_DP_TIMER_PROPERTIES),   // Print Timer count range and direction\r
+                    StringPtr,\r
+                    TimerInfo.StartCount,\r
+                    TimerInfo.EndCount\r
+                    );\r
+        PrintToken (STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mInterestThreshold);\r
+      }\r
+\r
+/* **************************************************************************\r
+****            Print Sections based on command line options\r
+****\r
+****  Option modes have the following priority:\r
+****    v Verbose     --  Valid in combination with any other options\r
+****    t Threshold   --  Modifies All, Raw, and Cooked output\r
+****                      Default is 0 for All and Raw mode\r
+****                      Default is DEFAULT_THRESHOLD for "Cooked" mode\r
+****    n Number2Display  Used by All and Raw mode.  Otherwise ignored.\r
+****    A All         --  R and S options are ignored\r
+****    R Raw         --  S option is ignored\r
+****    s Summary     --  Modifies "Cooked" output only\r
+****    Cooked (Default)\r
+****\r
+****  The All, Raw, and Cooked modes are modified by the Trace and Profile\r
+****  options.\r
+****    !T && !P  := (0) Default, Both are displayed\r
+****     T && !P  := (1) Only Trace records are displayed\r
+****    !T &&  P  := (2) Only Profile records are displayed\r
+****     T &&  P  := (3) Same as Default, both are displayed\r
+****************************************************************************/\r
+      GatherStatistics();\r
+      if (AllMode) {\r
+        if (TraceMode) {\r
+          DumpAllTrace( Number2Display, ExcludeMode);\r
+        }\r
+        if (ProfileMode) {\r
+          DumpAllProfile( Number2Display, ExcludeMode);\r
+        }\r
+      }\r
+      else if (RawMode) {\r
+        if (TraceMode) {\r
+          DumpRawTrace( Number2Display, ExcludeMode);\r
+        }\r
+        if (ProfileMode) {\r
+          DumpRawProfile( Number2Display, ExcludeMode);\r
+        }\r
+      }\r
+      else {\r
+        //------------- Begin Cooked Mode Processing\r
+        if (TraceMode) {\r
+          ProcessPhases ( Ticker );\r
+          if ( ! SummaryMode) {\r
+            Status = ProcessHandles ( ExcludeMode);\r
+            if ( ! EFI_ERROR( Status)) {\r
+              ProcessPeims (     );\r
+              ProcessGlobal (    );\r
+              ProcessCumulative ();\r
+            }\r
+          }\r
+        }\r
+        if (ProfileMode) {\r
+          DumpAllProfile( Number2Display, ExcludeMode);\r
+        }\r
+      } //------------- End of Cooked Mode Processing\r
+      if ( VerboseMode || SummaryMode) {\r
+        DumpStatistics();\r
+      }\r
+    }\r
+  }\r
+  (void) FreePool (mPrintTokenBuffer);\r
+  HiiRemovePackages (gHiiHandle);\r
+  return Status;\r
+}\r
diff --git a/PerformancePkg/Dp_App/Dp.h b/PerformancePkg/Dp_App/Dp.h
new file mode 100644 (file)
index 0000000..eb05373
--- /dev/null
@@ -0,0 +1,94 @@
+/** @file\r
+  * Common declarations for the Dp Performance Reporting Utility.\r
+  *\r
+  * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+  * This program and the accompanying materials\r
+  * are licensed and made available under the terms and conditions of the BSD License\r
+  * which accompanies this distribution.  The full text of the license may be found at\r
+  * http://opensource.org/licenses/bsd-license.php\r
+  *\r
+  * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef _EFI_APP_DP_H_\r
+#define _EFI_APP_DP_H_\r
+\r
+#define DP_MAJOR_VERSION        2\r
+#define DP_MINOR_VERSION        3\r
+\r
+/**\r
+  * The value assigned to DP_DEBUG controls which debug output\r
+  * is generated.  Set it to ZERO to disable.\r
+**/\r
+#define DP_DEBUG                0\r
+\r
+/**\r
+  * Set to 1 once Profiling has been implemented in order to enable\r
+  * profiling related options and report output.\r
+**/\r
+#define PROFILING_IMPLEMENTED   0\r
+\r
+#define DEFAULT_THRESHOLD       1000    ///< One millisecond.\r
+#define DEFAULT_DISPLAYCOUNT    50\r
+#define MAXIMUM_DISPLAYCOUNT    999999  ///< Arbitrary maximum reasonable number.\r
+\r
+#define PERF_MAXDUR             0xFFFFFFFFFFFFFFFFULL\r
+\r
+/// Determine whether  0 <= C < L.  If L == 0, return true regardless of C.\r
+#define WITHIN_LIMIT( C, L)   ( ((L) == 0) || ((C) < (L)) )\r
+\r
+/// Structure for storing Timer specific information.\r
+typedef struct {\r
+  UINT64    StartCount;   ///< Value timer is initialized with.\r
+  UINT64    EndCount;     ///< Value timer has just before it wraps.\r
+  UINT32    Frequency;    ///< Timer count frequency in KHz.\r
+  BOOLEAN   CountUp;      ///< TRUE if the counter counts up.\r
+} TIMER_INFO;\r
+\r
+/** Initialize one PERF_CUM_DATA structure instance for token t.\r
+  *\r
+  * This parameterized macro takes a single argument, t, which is expected\r
+  * to resolve to a pointer to an ASCII string literal.  This parameter may\r
+  * take any one of the following forms:\r
+  *   - PERF_INIT_CUM_DATA("Token")         A string literal\r
+  *   - PERF_INIT_CUM_DATA(pointer)         A pointer -- CHAR8 *pointer;\r
+  *   - PERF_INIT_CUM_DATA(array)           Address of an array -- CHAR8 array[N];\r
+**/\r
+#define PERF_INIT_CUM_DATA(t)   { 0ULL, PERF_MAXDUR, 0ULL, (t), 0U }\r
+\r
+typedef struct {\r
+  UINT64  Duration;     ///< Cumulative duration for this item.\r
+  UINT64  MinDur;       ///< Smallest duration encountered.\r
+  UINT64  MaxDur;       ///< Largest duration encountered.\r
+  CHAR8   *Name;        ///< ASCII name of this item.\r
+  UINT32  Count;        ///< Total number of measurements accumulated.\r
+} PERF_CUM_DATA;\r
+\r
+typedef struct {\r
+  UINT32                NumTrace;         ///< Number of recorded TRACE performance measurements.\r
+  UINT32                NumProfile;       ///< Number of recorded PROFILE performance measurements.\r
+  UINT32                NumIncomplete;    ///< Number of measurements with no END value.\r
+  UINT32                NumSummary;       ///< Number of summary section measurements.\r
+  UINT32                NumHandles;       ///< Number of measurements with handles.\r
+  UINT32                NumPEIMs;         ///< Number of measurements of PEIMs.\r
+  UINT32                NumGlobal;        ///< Number of measurements with END value and NULL handle.\r
+} PERF_SUMMARY_DATA;\r
+\r
+typedef struct {\r
+  VOID                  *Handle;\r
+  CHAR8                 *Token;           ///< Measured token string name.\r
+  CHAR8                 *Module;          ///< Module string name.\r
+  UINT64                StartTimeStamp;   ///< Start time point.\r
+  UINT64                EndTimeStamp;     ///< End time point.\r
+} MEASUREMENT_RECORD;\r
+\r
+typedef struct {\r
+  CHAR8                 *Name;            ///< Measured token string name.\r
+  UINT64                CumulativeTime;   ///< Accumulated Elapsed Time.\r
+  UINT64                MinTime;          ///< Minimum Elapsed Time.\r
+  UINT64                MaxTime;          ///< Maximum Elapsed Time.\r
+  UINT32                Count;            ///< Number of measurements accumulated.\r
+} PROFILE_RECORD;\r
+\r
+#endif  // _EFI_APP_DP_H_\r
diff --git a/PerformancePkg/Dp_App/Dp.inf b/PerformancePkg/Dp_App/Dp.inf
new file mode 100644 (file)
index 0000000..6849ab9
--- /dev/null
@@ -0,0 +1,66 @@
+#/** @file\r
+#  Display Performance Application, Module information file.\r
+#\r
+# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010006\r
+  BASE_NAME                      = DP\r
+  FILE_GUID                      = 7d5ff0e3-2fb7-4e19-8419-44266cb60000\r
+  MODULE_TYPE                    = UEFI_APPLICATION\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = InitializeDp\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  DpStrings.uni\r
+  Dp.c\r
+  Literals.c\r
+  DpUtilities.c\r
+  DpTrace.c\r
+  DpProfile.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  ShellPkg/ShellPkg.dec\r
+  PerformancePkg/PerformancePkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiApplicationEntryPoint\r
+  ShellLib\r
+  BaseMemoryLib\r
+  BaseLib\r
+  MemoryAllocationLib\r
+  DebugLib\r
+  UefiBootServicesTableLib\r
+  TimerLib\r
+  PeCoffGetEntryPointLib\r
+  PerformanceLib\r
+  PrintLib\r
+  UefiLib\r
+  HiiLib\r
+  PcdLib\r
+\r
+[Guids]\r
+\r
+[Protocols]\r
+  gEfiLoadedImageProtocolGuid                             # ALWAYS_CONSUMED\r
+  gEfiDriverBindingProtocolGuid                           # ALWAYS_CONSUMED\r
+\r
+[Pcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize\r
diff --git a/PerformancePkg/Dp_App/DpInternal.h b/PerformancePkg/Dp_App/DpInternal.h
new file mode 100644 (file)
index 0000000..9335580
--- /dev/null
@@ -0,0 +1,289 @@
+/** @file\r
+  * Declarations of objects defined internally to the Dp Application.\r
+  *\r
+  * Declarations of data and functions which are private to the Dp application.\r
+  * This file should never be referenced by anything other than components of the\r
+  * Dp application.  In addition to global data, function declarations for\r
+  * DpUtilities.c, DpTrace.c, and DpProfile.c are included here.\r
+  *\r
+  * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+  * This program and the accompanying materials\r
+  * are licensed and made available under the terms and conditions of the BSD License\r
+  * which accompanies this distribution.  The full text of the license may be found at\r
+  * http://opensource.org/licenses/bsd-license.php\r
+  *\r
+  * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+//\r
+/// Module-Global Variables\r
+/// @{\r
+extern EFI_HII_HANDLE     gHiiHandle;\r
+extern CHAR16             *mPrintTokenBuffer;\r
+extern CHAR16             mGaugeString[DXE_PERFORMANCE_STRING_SIZE];\r
+extern CHAR16             mUnicodeToken[PERF_TOKEN_LENGTH + 1];\r
+extern UINT64             mInterestThreshold;\r
+\r
+extern PERF_SUMMARY_DATA  SummaryData;;    ///< Create the SummaryData structure and init. to ZERO.\r
+\r
+/// Timer Specific Information.\r
+extern TIMER_INFO         TimerInfo;\r
+\r
+/// Items for which to gather cumulative statistics.\r
+extern PERF_CUM_DATA      CumData[];\r
+\r
+/// Number of items for which we are gathering cumulative statistics.\r
+extern UINT32 const       NumCum;\r
+\r
+/// @}\r
+\r
+/** Calculate an event's duration in timer ticks.\r
+  *\r
+  * Given the count direction and the event's start and end timer values,\r
+  * calculate the duration of the event in timer ticks.\r
+  *\r
+  * @pre  The global TimerInfo structure must have already been initialized\r
+  *       before this function is called.\r
+  *\r
+  * @param[in,out]    Measurement   Pointer to a structure containing data for the current measurement.\r
+  *\r
+  * @return       The 64-bit duration of the event.\r
+**/\r
+UINT64\r
+GetDuration (\r
+  IN OUT MEASUREMENT_RECORD *Measurement\r
+);\r
+\r
+/** Determine whether the Measurement record is for an EFI Phase.\r
+  *\r
+  * The Token and Module members of the measurement record are checked.\r
+  * Module must be empty and Token must be one of SEC, PEI, DXE, or BDS.\r
+  *\r
+  * @param[in]  Measurement A pointer to the Measurement record to test.\r
+  *\r
+  * @retval     TRUE        The measurement record is for an EFI Phase.\r
+  * @retval     FALSE       The measurement record is NOT for an EFI Phase.\r
+**/\r
+BOOLEAN\r
+IsPhase(\r
+  IN MEASUREMENT_RECORD *Measurement\r
+);\r
+\r
+/** Get the file name portion of the Pdb File Name.\r
+  *\r
+  * The portion of the Pdb File Name between the last backslash and\r
+  * either a following period or the end of the string is converted\r
+  * to Unicode and copied into UnicodeBuffer.  The name is truncated,\r
+  * if necessary, to ensure that UnicodeBuffer is not overrun.\r
+  *\r
+  * @param[in]  PdbFileName     Pdb file name.\r
+  * @param[out] UnicodeBuffer   The resultant Unicode File Name.\r
+  *\r
+**/\r
+VOID\r
+GetShortPdbFileName (\r
+  IN  CHAR8     *PdbFileName,\r
+  OUT CHAR16    *UnicodeBuffer\r
+);\r
+\r
+/** Get a human readable name for an image handle.\r
+  *\r
+  * @param[in]    Handle\r
+  *\r
+  * @post   The resulting Unicode name string is stored in the\r
+  *         mGaugeString global array.\r
+  *\r
+**/\r
+VOID\r
+GetNameFromHandle (\r
+  IN EFI_HANDLE Handle\r
+);\r
+\r
+/** Calculate the Duration in microseconds.\r
+  *\r
+  * Duration is multiplied by 1000, instead of Frequency being divided by 1000\r
+  * in order to maintain precision.  Since Duration is\r
+  * a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow.\r
+  *\r
+  * @param[in] Duration   The event duration in timer ticks.\r
+  *\r
+  * @return   A 64-bit value which is the Elapsed time in microseconds.\r
+**/\r
+UINT64\r
+DurationInMicroSeconds (\r
+  IN UINT64 Duration\r
+);\r
+\r
+/** Formatted Print using a Hii Token to reference the localized format string.\r
+  *\r
+  * @param[in]  Token   A HII token associated with a localized Unicode string.\r
+  *\r
+  * @return             The number of characters converted by UnicodeVSPrint().\r
+  *\r
+**/\r
+UINTN\r
+PrintToken (\r
+  IN UINT16 Token,\r
+  ...\r
+);\r
+\r
+/** Get index of Measurement Record's match in the CumData array.\r
+  *\r
+  * @param[in]  Measurement A pointer to a Measurement Record to match against the CumData array.\r
+  *\r
+  * @retval     <0    Token is not in the CumData array.\r
+  * @retval     >=0   Return value is the index into CumData where Token is found.\r
+**/\r
+INTN\r
+GetCumulativeItem(\r
+  IN MEASUREMENT_RECORD *Measurement\r
+);\r
+\r
+/** Collect verbose statistics about the logged performance measurements.\r
+  *\r
+  * General Summary information for all Trace measurements is gathered and\r
+  * stored within the SummaryData structure.  This information is both\r
+  * used internally by subsequent reporting functions, and displayed\r
+  * at the end of verbose reports.\r
+  *\r
+  * @pre  The SummaryData and CumData structures must be initialized\r
+  *       prior to calling this function.\r
+  *\r
+  * @post The SummaryData and CumData structures contain statistics for the\r
+  *       current performance logs.\r
+**/\r
+VOID\r
+GatherStatistics(\r
+  VOID\r
+);\r
+\r
+/** Gather and print ALL Trace Records.\r
+  *\r
+  * Displays all "interesting" Trace measurements in order.\r
+  * The number of records displayed is controlled by:\r
+  *   - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+  *   - No more than Limit records are displayed.  A Limit of zero will not limit the output.\r
+  *   - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+  *     displayed.\r
+  *\r
+  * @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+  *         The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.\r
+  *         They must not be in use by a calling function.\r
+  *\r
+  * @param[in]    Limit       The number of records to print.  Zero is ALL.\r
+  * @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+  *\r
+**/\r
+VOID\r
+DumpAllTrace(\r
+  IN UINTN             Limit,\r
+  IN BOOLEAN           ExcludeFlag\r
+);\r
+\r
+/** Gather and print Raw Trace Records.\r
+  *\r
+  * All Trace measurements with a duration greater than or equal to\r
+  * mInterestThreshold are printed without interpretation.\r
+  *\r
+  * The number of records displayed is controlled by:\r
+  *   - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+  *   - No more than Limit records are displayed.  A Limit of zero will not limit the output.\r
+  *   - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+  *     displayed.\r
+  *\r
+  * @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+  *\r
+  * @param[in]    Limit       The number of records to print.  Zero is ALL.\r
+  * @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+  *\r
+**/\r
+VOID\r
+DumpRawTrace(\r
+  IN UINTN          Limit,\r
+  IN BOOLEAN        ExcludeFlag\r
+);\r
+\r
+/** Gather and print Major Phase metrics.\r
+  *\r
+  * @param[in]    Ticker      The timer value for the END of Shell phase\r
+  *\r
+**/\r
+VOID\r
+ProcessPhases(\r
+  IN UINT64 Ticker\r
+);\r
+\r
+\r
+/** Gather and print Handle data.\r
+  *\r
+  * @param[in]    ExcludeFlag   TRUE if the -x command line flag given.  Elides accumulated trace records.\r
+  *\r
+  * @return       Status from a call to gBS->LocateHandle().\r
+**/\r
+EFI_STATUS\r
+ProcessHandles(\r
+  IN BOOLEAN ExcludeFlag\r
+);\r
+\r
+\r
+/** Gather and print PEIM data.\r
+  *\r
+  * Only prints complete PEIM records\r
+  *\r
+**/\r
+VOID\r
+ProcessPeims(\r
+  VOID\r
+);\r
+\r
+/** Gather and print global data.\r
+  *\r
+  * Strips out incomplete or "Execution Phase" records\r
+  * Only prints records where Handle is NULL\r
+  * Increment TIndex for every record, even skipped ones, so that we have an\r
+  * indication of every measurement record taken.\r
+  *\r
+  *\r
+**/\r
+VOID\r
+ProcessGlobal(\r
+  VOID\r
+);\r
+\r
+/** Gather and print cumulative data.\r
+  *\r
+  * Traverse the measurement records and:\r
+  * for each record with a Token listed in the CumData array,\r
+  *   Update the instance count and the total, minimum, and maximum durations.\r
+  * Finally, print the gathered cumulative statistics.\r
+  *\r
+**/\r
+VOID\r
+ProcessCumulative(\r
+  VOID\r
+);\r
+\r
+/** Gather and print ALL Profile Records.\r
+  *\r
+  * @param[in]    Limit       The number of records to print.  Zero is ALL.\r
+  * @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display\r
+  *\r
+**/\r
+VOID\r
+DumpAllProfile(\r
+  IN UINTN          Limit,\r
+  IN BOOLEAN        ExcludeFlag\r
+);\r
+\r
+/** Gather and print Raw Profile Records.\r
+  *\r
+  * @param[in]    Limit       The number of records to print.\r
+  * @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display\r
+  *\r
+**/\r
+VOID\r
+DumpRawProfile(\r
+  IN UINTN          Limit,\r
+  IN BOOLEAN        ExcludeFlag\r
+);\r
diff --git a/PerformancePkg/Dp_App/DpProfile.c b/PerformancePkg/Dp_App/DpProfile.c
new file mode 100644 (file)
index 0000000..880e057
--- /dev/null
@@ -0,0 +1,92 @@
+/** @file\r
+  * Measured Profiling reporting for the Dp utility.\r
+  *\r
+  * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+  * This program and the accompanying materials\r
+  * are licensed and made available under the terms and conditions of the BSD License\r
+  * which accompanies this distribution.  The full text of the license may be found at\r
+  * http://opensource.org/licenses/bsd-license.php\r
+  *\r
+  * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Guid/Performance.h>\r
+\r
+#include "Dp.h"\r
+#include "Literals.h"\r
+#include "DpInternal.h"\r
+\r
+/** Gather and print ALL Profiling Records.\r
+  *\r
+  * Displays all "interesting" Profile measurements in order.\r
+  * The number of records displayed is controlled by:\r
+  *   - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+  *   - No more than Limit records are displayed.  A Limit of zero will not limit the output.\r
+  *   - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+  *     displayed.\r
+  *\r
+  * @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+  *         The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.\r
+  *         They must not be in use by a calling function.\r
+  *\r
+  * @param[in]    Limit         The number of records to print.  Zero is ALL.\r
+  * @param[in]    ExcludeFlag   TRUE to exclude individual Cumulative items from display.\r
+  *\r
+**/\r
+VOID\r
+DumpAllProfile(\r
+  IN UINTN      Limit,\r
+  IN BOOLEAN    ExcludeFlag\r
+  )\r
+{\r
+  EFI_STRING    StringPtr;\r
+\r
+  StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PROFILE), NULL);\r
+  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+              (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+  return;\r
+}\r
+\r
+/** Gather and print Raw Profile Records.\r
+  *\r
+  * All Profile measurements with a duration greater than or equal to\r
+  * mInterestThreshold are printed without interpretation.\r
+  *\r
+  * The number of records displayed is controlled by:\r
+  *   - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+  *   - No more than Limit records are displayed.  A Limit of zero will not limit the output.\r
+  *   - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+  *     displayed.\r
+  *\r
+  * @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+  *\r
+  * @param[in]    Limit         The number of records to print.  Zero is ALL.\r
+  * @param[in]    ExcludeFlag   TRUE to exclude individual Cumulative items from display.\r
+  *\r
+**/\r
+VOID\r
+DumpRawProfile(\r
+  IN UINTN      Limit,\r
+  IN BOOLEAN    ExcludeFlag\r
+  )\r
+{\r
+  EFI_STRING    StringPtr;\r
+\r
+  StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWPROFILE), NULL);\r
+  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+              (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+  return;\r
+}\r
diff --git a/PerformancePkg/Dp_App/DpStrings.uni b/PerformancePkg/Dp_App/DpStrings.uni
new file mode 100644 (file)
index 0000000..ba0b614
Binary files /dev/null and b/PerformancePkg/Dp_App/DpStrings.uni differ
diff --git a/PerformancePkg/Dp_App/DpTrace.c b/PerformancePkg/Dp_App/DpTrace.c
new file mode 100644 (file)
index 0000000..fdbd860
--- /dev/null
@@ -0,0 +1,681 @@
+/** @file\r
+  * Trace reporting for the Dp utility.\r
+  *\r
+  * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+  * This program and the accompanying materials\r
+  * are licensed and made available under the terms and conditions of the BSD License\r
+  * which accompanies this distribution.  The full text of the license may be found at\r
+  * http://opensource.org/licenses/bsd-license.php\r
+  *\r
+  * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Guid/Performance.h>\r
+\r
+#include "Dp.h"\r
+#include "Literals.h"\r
+#include "DpInternal.h"\r
+\r
+/** Collect verbose statistics about the logged performance measurements.\r
+  *\r
+  * General Summary information for all Trace measurements is gathered and\r
+  * stored within the SummaryData structure.  This information is both\r
+  * used internally by subsequent reporting functions, and displayed\r
+  * at the end of verbose reports.\r
+  *\r
+  * @pre  The SummaryData and CumData structures must be initialized\r
+  *       prior to calling this function.\r
+  *\r
+  * @post The SummaryData and CumData structures contain statistics for the\r
+  *       current performance logs.\r
+**/\r
+VOID\r
+GatherStatistics(\r
+  VOID\r
+)\r
+{\r
+  MEASUREMENT_RECORD        Measurement;\r
+  UINT64                    Duration;\r
+  UINTN                     LogEntryKey;\r
+  UINTN                     TIndex;\r
+\r
+  LogEntryKey = 0;\r
+  while ((LogEntryKey = GetPerformanceMeasurement (\r
+                        LogEntryKey,\r
+                        &Measurement.Handle,\r
+                        &Measurement.Token,\r
+                        &Measurement.Module,\r
+                        &Measurement.StartTimeStamp,\r
+                        &Measurement.EndTimeStamp)) != 0)\r
+  {\r
+    ++SummaryData.NumTrace;           // Count the number of TRACE Measurement records\r
+    if (Measurement.EndTimeStamp == 0) {\r
+      ++SummaryData.NumIncomplete;    // Count the incomplete records\r
+      continue;\r
+    }\r
+\r
+    if (Measurement.Handle != NULL) {\r
+      ++SummaryData.NumHandles;       // Count the number of measurements with non-NULL handles\r
+    }\r
+\r
+    if (IsPhase( &Measurement)) {\r
+      ++SummaryData.NumSummary;       // Count the number of major phases\r
+    }\r
+    else {  // !IsPhase(...\r
+      if(Measurement.Handle == NULL) {\r
+        ++SummaryData.NumGlobal;\r
+      }\r
+    }\r
+\r
+    if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) {\r
+      ++SummaryData.NumPEIMs;         // Count PEIM measurements\r
+    }\r
+\r
+    Duration = GetDuration (&Measurement);\r
+    TIndex = GetCumulativeItem (&Measurement);\r
+    if (TIndex >= 0) {\r
+      CumData[TIndex].Duration += Duration;\r
+      CumData[TIndex].Count++;\r
+      if ( Duration < CumData[TIndex].MinDur ) {\r
+        CumData[TIndex].MinDur = Duration;\r
+      }\r
+      if ( Duration > CumData[TIndex].MaxDur ) {\r
+        CumData[TIndex].MaxDur = Duration;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/** Gather and print ALL Trace Records.\r
+  *\r
+  * Displays all "interesting" Trace measurements in order.<BR>\r
+  * The number of records displayed is controlled by:\r
+  *   - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+  *   - No more than Limit records are displayed.  A Limit of zero will not limit the output.\r
+  *   - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+  *     displayed.\r
+  *\r
+  * @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+  *         The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.\r
+  *         They must not be in use by a calling function.\r
+  *\r
+  * @param[in]    Limit       The number of records to print.  Zero is ALL.\r
+  * @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+  *\r
+**/\r
+VOID\r
+DumpAllTrace(\r
+  IN UINTN             Limit,\r
+  IN BOOLEAN           ExcludeFlag\r
+  )\r
+{\r
+  MEASUREMENT_RECORD        Measurement;\r
+  UINT64                    ElapsedTime;\r
+  UINT64                    Duration;\r
+  const CHAR16              *IncFlag;\r
+  UINTN                     LogEntryKey;\r
+  UINTN                     Count;\r
+  UINTN                     Index;\r
+  UINTN                     TIndex;\r
+\r
+  EFI_HANDLE                *HandleBuffer;\r
+  UINTN                     Size;\r
+  EFI_HANDLE                TempHandle;\r
+  EFI_STATUS                Status;\r
+\r
+  IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);\r
+  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+              (IncFlag == NULL) ? ALit_UNKNOWN: IncFlag);\r
+\r
+  // Get Handle information\r
+  //\r
+  Size = 0;\r
+  HandleBuffer = NULL;\r
+  Status  = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HandleBuffer = AllocatePool (Size);\r
+    ASSERT (HandleBuffer != NULL);\r
+    Status  = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);\r
+  }\r
+  else {\r
+    // We have successfully populated the HandleBuffer\r
+    // Display ALL Measurement Records\r
+    //    Up to Limit lines displayed\r
+    //    Display only records with Elapsed times >= mInterestThreshold\r
+    //    Display driver names in Module field for records with Handles.\r
+    //\r
+    PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR) );\r
+    PrintToken (STRING_TOKEN (STR_DP_DASHES) );\r
+\r
+    LogEntryKey = 0;\r
+    Count = 0;\r
+    Index = 0;\r
+    while ( WITHIN_LIMIT(Count, Limit) &&\r
+            ((LogEntryKey = GetPerformanceMeasurement (\r
+                            LogEntryKey,\r
+                            &Measurement.Handle,\r
+                            &Measurement.Token,\r
+                            &Measurement.Module,\r
+                            &Measurement.StartTimeStamp,\r
+                            &Measurement.EndTimeStamp)) != 0)\r
+          )\r
+    {\r
+      ++Index;    // Count every record.  First record is 1.\r
+      ElapsedTime = 0;\r
+      if (Measurement.EndTimeStamp != 0) {\r
+        Duration = GetDuration (&Measurement);\r
+        ElapsedTime = DurationInMicroSeconds ( Duration );\r
+        IncFlag = STR_DP_COMPLETE;\r
+      }\r
+      else {\r
+        IncFlag = STR_DP_INCOMPLETE;  // Mark incomplete records\r
+      }\r
+      if ((ElapsedTime < mInterestThreshold)                 ||\r
+          ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
+         ) {      // Ignore "uninteresting" or excluded records\r
+        continue;\r
+      }\r
+      if (Measurement.EndTimeStamp == 0) {\r
+        ElapsedTime = Measurement.StartTimeStamp;\r
+      }\r
+      ++Count;    // Count the number of records printed\r
+\r
+      // If Handle is non-zero, see if we can determine a name for the driver\r
+      AsciiStrToUnicodeStr (Measurement.Module, mGaugeString); // Use Module by default\r
+      AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);\r
+      if (Measurement.Handle != NULL) {\r
+        // See if the Handle is in the HandleBuffer\r
+        for (TIndex = 0; TIndex < (Size / sizeof(HandleBuffer[0])); TIndex++) {\r
+          if (Measurement.Handle == HandleBuffer[TIndex]) {\r
+            GetNameFromHandle (HandleBuffer[TIndex]);\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      // Ensure that the argument strings are not too long.\r
+      mGaugeString[31] = 0;\r
+      mUnicodeToken[18] = 0;\r
+\r
+      PrintToken( STRING_TOKEN (STR_DP_ALL_STATS),\r
+        Index,      // 1 based, Which measurement record is being printed\r
+        IncFlag,\r
+        Measurement.Handle,\r
+        mGaugeString,\r
+        mUnicodeToken,\r
+        ElapsedTime\r
+      );\r
+    }\r
+  }\r
+  FreePool (HandleBuffer);\r
+}\r
+\r
+/** Gather and print Raw Trace Records.\r
+  *\r
+  * All Trace measurements with a duration greater than or equal to\r
+  * mInterestThreshold are printed without interpretation.\r
+  *\r
+  * The number of records displayed is controlled by:\r
+  *   - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+  *   - No more than Limit records are displayed.  A Limit of zero will not limit the output.\r
+  *   - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+  *     displayed.\r
+  *\r
+  * @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+  *\r
+  * @param[in]    Limit       The number of records to print.  Zero is ALL.\r
+  * @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+  *\r
+**/\r
+VOID\r
+DumpRawTrace(\r
+  IN UINTN          Limit,\r
+  IN BOOLEAN        ExcludeFlag\r
+  )\r
+{\r
+  MEASUREMENT_RECORD        Measurement;\r
+  UINT64                    ElapsedTime;\r
+  UINT64                    Duration;\r
+  UINTN                     LogEntryKey;\r
+  UINTN                     Count;\r
+  UINTN                     Index;\r
+\r
+  EFI_STRING    StringPtr;\r
+\r
+  StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);\r
+  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+              (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+  PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR) );\r
+  PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES) );\r
+\r
+  LogEntryKey = 0;\r
+  Count = 0;\r
+  Index = 0;\r
+  while ( WITHIN_LIMIT(Count, Limit) &&\r
+          ((LogEntryKey = GetPerformanceMeasurement (\r
+                          LogEntryKey,\r
+                          &Measurement.Handle,\r
+                          &Measurement.Token,\r
+                          &Measurement.Module,\r
+                          &Measurement.StartTimeStamp,\r
+                          &Measurement.EndTimeStamp)) != 0)\r
+        )\r
+  {\r
+    ++Index;    // Count every record.  First record is 1.\r
+    ElapsedTime = 0;\r
+    if (Measurement.EndTimeStamp != 0) {\r
+      Duration = GetDuration (&Measurement);\r
+      ElapsedTime = DurationInMicroSeconds ( Duration );\r
+    }\r
+    if ((ElapsedTime < mInterestThreshold)                 ||\r
+        ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
+        ) { // Ignore "uninteresting" or Excluded records\r
+      continue;\r
+    }\r
+    ++Count;    // Count the number of records printed\r
+    PrintToken (STRING_TOKEN (STR_DP_RAW_VARS),\r
+      Index,      // 1 based, Which measurement record is being printed\r
+      Measurement.Handle,\r
+      Measurement.StartTimeStamp,\r
+      Measurement.EndTimeStamp,\r
+      Measurement.Token,\r
+      Measurement.Module\r
+    );\r
+  }\r
+}\r
+\r
+/** Gather and print Major Phase metrics.\r
+  *\r
+  * @param[in]    Ticker      The timer value for the END of Shell phase\r
+  *\r
+**/\r
+VOID\r
+ProcessPhases(\r
+  UINT64            Ticker\r
+  )\r
+{\r
+  MEASUREMENT_RECORD        Measurement;\r
+  UINT64                    BdsTimeoutValue = 0;\r
+  UINT64                    SecTime         = 0;\r
+  UINT64                    PeiTime         = 0;\r
+  UINT64                    DxeTime         = 0;\r
+  UINT64                    BdsTime         = 0;\r
+  UINT64                    ShellTime       = 0;\r
+  UINT64                    ElapsedTime;\r
+  UINT64                    Duration;\r
+  UINT64                    Total;\r
+  EFI_STRING                StringPtr;\r
+  UINTN                     LogEntryKey;\r
+\r
+  //\r
+  // Get Execution Phase Statistics\r
+  //\r
+  StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);\r
+  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+              (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+  LogEntryKey = 0;\r
+  while ((LogEntryKey = GetPerformanceMeasurement (\r
+                          LogEntryKey,\r
+                          &Measurement.Handle,\r
+                          &Measurement.Token,\r
+                          &Measurement.Module,\r
+                          &Measurement.StartTimeStamp,\r
+                          &Measurement.EndTimeStamp)) != 0)\r
+  {\r
+    if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {\r
+      Measurement.EndTimeStamp = Ticker;\r
+    }\r
+    if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records\r
+      continue;\r
+    }\r
+    Duration = GetDuration (&Measurement);\r
+    if (   Measurement.Handle != NULL\r
+        && (AsciiStrnCmp (Measurement.Token, ALit_BdsTO, PERF_TOKEN_LENGTH) == 0)\r
+       )\r
+    {\r
+      BdsTimeoutValue = Duration;\r
+    } else if (AsciiStrnCmp (Measurement.Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) {\r
+      SecTime     = Duration;\r
+    } else if (AsciiStrnCmp (Measurement.Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) {\r
+      PeiTime     = Duration;\r
+    } else if (AsciiStrnCmp (Measurement.Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) {\r
+      DxeTime      = Duration;\r
+    } else if (AsciiStrnCmp (Measurement.Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0) {\r
+      BdsTime      = Duration;\r
+    } else if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {\r
+      ShellTime    = Duration;\r
+    }\r
+  }\r
+\r
+  Total = 0;\r
+\r
+  // print SEC phase duration time\r
+  //\r
+  if (SecTime > 0) {\r
+    ElapsedTime = DurationInMicroSeconds ( SecTime );     // Calculate elapsed time in microseconds\r
+    Total += DivU64x32 (ElapsedTime, 1000);   // Accumulate time in milliseconds\r
+    PrintToken (STRING_TOKEN (STR_DP_SEC_PHASE), ElapsedTime);\r
+  }\r
+\r
+  // print PEI phase duration time\r
+  //\r
+  if (PeiTime > 0) {\r
+    ElapsedTime = DivU64x32 (\r
+                    PeiTime,\r
+                    (UINT32)TimerInfo.Frequency\r
+                    );\r
+    Total += ElapsedTime;\r
+    PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_PEI, ElapsedTime);\r
+  }\r
+\r
+  // print DXE phase duration time\r
+  //\r
+  if (DxeTime > 0) {\r
+    ElapsedTime = DivU64x32 (\r
+                    DxeTime,\r
+                    (UINT32)TimerInfo.Frequency\r
+                    );\r
+    Total += ElapsedTime;\r
+    PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_DXE, ElapsedTime);\r
+  }\r
+\r
+  // print BDS phase duration time\r
+  //\r
+  if (BdsTime > 0) {\r
+    ElapsedTime = DivU64x32 (\r
+                    BdsTime,\r
+                    (UINT32)TimerInfo.Frequency\r
+                    );\r
+    Total += ElapsedTime;\r
+    PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_BDS, ElapsedTime);\r
+  }\r
+\r
+  if (BdsTimeoutValue > 0) {\r
+    ElapsedTime = DivU64x32 (\r
+                    BdsTimeoutValue,\r
+                    (UINT32)TimerInfo.Frequency\r
+                    );\r
+    PrintToken (STRING_TOKEN (STR_DP_PHASE_BDSTO), ALit_BdsTO, ElapsedTime);\r
+  }\r
+\r
+  // print SHELL phase duration time\r
+  //\r
+  if (ShellTime > 0) {\r
+    ElapsedTime = DivU64x32 (\r
+                    ShellTime,\r
+                    (UINT32)TimerInfo.Frequency\r
+                    );\r
+    Total += ElapsedTime;\r
+    PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_SHELL, ElapsedTime);\r
+  }\r
+\r
+  PrintToken (STRING_TOKEN (STR_DP_TOTAL_DURATION), Total);\r
+}\r
+\r
+/** Gather and print Handle data.\r
+  *\r
+  * @param[in]    ExcludeFlag   TRUE to exclude individual Cumulative items from display.\r
+  *\r
+  * @return       Status from a call to gBS->LocateHandle().\r
+**/\r
+EFI_STATUS\r
+ProcessHandles(\r
+  IN BOOLEAN      ExcludeFlag\r
+  )\r
+{\r
+  MEASUREMENT_RECORD        Measurement;\r
+  UINT64                    ElapsedTime;\r
+  UINT64                    Duration;\r
+  EFI_HANDLE                *HandleBuffer;\r
+  EFI_STRING                StringPtr;\r
+  UINTN                     Index;\r
+  UINTN                     LogEntryKey;\r
+  UINTN                     Count;\r
+  UINTN                     Size;\r
+  EFI_HANDLE                TempHandle;\r
+  EFI_STATUS                Status;\r
+\r
+  StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);\r
+  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+              (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+  Size = 0;\r
+  HandleBuffer = NULL;\r
+  Status  = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HandleBuffer = AllocatePool (Size);\r
+    ASSERT (HandleBuffer != NULL);\r
+    Status  = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);\r
+  }\r
+  else {\r
+#if DP_DEBUG == 2\r
+    Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0])));\r
+#endif\r
+\r
+    PrintToken (STRING_TOKEN (STR_DP_HANDLE_GUID) );\r
+    PrintToken (STRING_TOKEN (STR_DP_DASHES) );\r
+\r
+    LogEntryKey = 0;\r
+    Count   = 0;\r
+    while ((LogEntryKey = GetPerformanceMeasurement (\r
+                            LogEntryKey,\r
+                            &Measurement.Handle,\r
+                            &Measurement.Token,\r
+                            &Measurement.Module,\r
+                            &Measurement.StartTimeStamp,\r
+                            &Measurement.EndTimeStamp)) != 0)\r
+    {\r
+      Count++;\r
+      Duration = GetDuration (&Measurement);\r
+      ElapsedTime = DurationInMicroSeconds ( Duration );\r
+      if ((ElapsedTime < mInterestThreshold)                 ||\r
+          (Measurement.EndTimeStamp == 0)                    ||\r
+          (Measurement.Handle == NULL)                       ||\r
+          ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
+         ) { // Ignore "uninteresting" or excluded records\r
+        continue;\r
+      }\r
+      mGaugeString[0] = 0;    // Empty driver name by default\r
+      AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);\r
+      // See if the Handle is in the HandleBuffer\r
+      for (Index = 0; Index < (Size / sizeof(HandleBuffer[0])); Index++) {\r
+        if (Measurement.Handle == HandleBuffer[Index]) {\r
+          GetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString\r
+          break;\r
+        }\r
+      }\r
+      // Ensure that the argument strings are not too long.\r
+      mGaugeString[31] = 0;\r
+      mUnicodeToken[18] = 0;\r
+      if (mGaugeString[0] != 0) {\r
+        // Display the record if it has a valid handle.\r
+        PrintToken (\r
+          STRING_TOKEN (STR_DP_HANDLE_VARS),\r
+          Count,      // 1 based, Which measurement record is being printed\r
+          Index + 1,  // 1 based, Which handle is being printed\r
+          mGaugeString,\r
+          mUnicodeToken,\r
+          ElapsedTime\r
+        );\r
+      }\r
+    }\r
+  }\r
+  FreePool (HandleBuffer);\r
+  return Status;\r
+}\r
+\r
+/** Gather and print PEIM data.\r
+  *\r
+  * Only prints complete PEIM records\r
+  *\r
+**/\r
+VOID\r
+ProcessPeims(\r
+  VOID\r
+)\r
+{\r
+  MEASUREMENT_RECORD        Measurement;\r
+  UINT64                    Duration;\r
+  UINT64                    ElapsedTime;\r
+  EFI_STRING                StringPtr;\r
+  UINTN                     LogEntryKey;\r
+  UINTN                     TIndex;\r
+\r
+\r
+  StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);\r
+  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+              (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+  PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION));\r
+  PrintToken (STRING_TOKEN (STR_DP_DASHES));\r
+  TIndex  = 0;\r
+  LogEntryKey = 0;\r
+  while ((LogEntryKey = GetPerformanceMeasurement (\r
+                          LogEntryKey,\r
+                          &Measurement.Handle,\r
+                          &Measurement.Token,\r
+                          &Measurement.Module,\r
+                          &Measurement.StartTimeStamp,\r
+                          &Measurement.EndTimeStamp)) != 0)\r
+  {\r
+    TIndex++;\r
+    if ((Measurement.EndTimeStamp == 0) ||\r
+        (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) != 0)\r
+       ) {\r
+      continue;\r
+    }\r
+\r
+    Duration = GetDuration (&Measurement);\r
+    ElapsedTime = DurationInMicroSeconds ( Duration );  // Calculate elapsed time in microseconds\r
+    if (ElapsedTime >= mInterestThreshold) {\r
+      GetNameFromHandle (Measurement.Handle);           // Name placed in mGaugeString\r
+      PrintToken (STRING_TOKEN (STR_DP_PEIM_STAT2),\r
+            TIndex,   // 1 based, Which measurement record is being printed\r
+            Measurement.Handle,\r
+            mGaugeString,\r
+            ElapsedTime\r
+      );\r
+    }\r
+  }\r
+}\r
+\r
+/** Gather and print global data.\r
+  *\r
+  * Strips out incomplete or "Execution Phase" records\r
+  * Only prints records where Handle is NULL\r
+  * Increment TIndex for every record, even skipped ones, so that we have an\r
+  * indication of every measurement record taken.\r
+  *\r
+  *\r
+**/\r
+VOID\r
+ProcessGlobal(\r
+  VOID\r
+)\r
+{\r
+  MEASUREMENT_RECORD        Measurement;\r
+  UINT64                    Duration;\r
+  UINT64                    ElapsedTime;\r
+  EFI_STRING                StringPtr;\r
+  UINTN                     LogEntryKey;\r
+  UINTN                     Index;        // Index, or number, of the measurement record being processed\r
+\r
+  StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);\r
+  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+              (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+  PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION));\r
+  PrintToken (STRING_TOKEN (STR_DP_DASHES));\r
+\r
+  Index = 1;\r
+  LogEntryKey = 0;\r
+\r
+  while ((LogEntryKey = GetPerformanceMeasurement (\r
+                          LogEntryKey,\r
+                          &Measurement.Handle,\r
+                          &Measurement.Token,\r
+                          &Measurement.Module,\r
+                          &Measurement.StartTimeStamp,\r
+                          &Measurement.EndTimeStamp)) != 0)\r
+  {\r
+    AsciiStrToUnicodeStr (Measurement.Module, mGaugeString);\r
+    AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);\r
+    if ( ! ( IsPhase( &Measurement)  ||\r
+        (Measurement.Handle != NULL)      ||\r
+        (Measurement.EndTimeStamp == 0)\r
+        ))\r
+    {\r
+      Duration = GetDuration (&Measurement);\r
+      ElapsedTime = DurationInMicroSeconds ( Duration );\r
+      if (ElapsedTime >= mInterestThreshold) {\r
+        PrintToken (\r
+          STRING_TOKEN (STR_DP_FOUR_VARS_2),\r
+          Index,\r
+          mGaugeString,\r
+          mUnicodeToken,\r
+          ElapsedTime\r
+          );\r
+      }\r
+    }\r
+    Index++;\r
+  }\r
+}\r
+\r
+/** Gather and print cumulative data.\r
+  *\r
+  * Traverse the measurement records and:<BR>\r
+  * For each record with a Token listed in the CumData array:<BR>\r
+  *   - Update the instance count and the total, minimum, and maximum durations.\r
+  * Finally, print the gathered cumulative statistics.\r
+  *\r
+**/\r
+VOID\r
+ProcessCumulative(\r
+  VOID\r
+)\r
+{\r
+  UINT64                    avgval;         // the computed average duration\r
+  EFI_STRING                StringPtr;\r
+  UINTN                     TIndex;\r
+\r
+\r
+  StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);\r
+  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+              (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+  PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1));\r
+  PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2));\r
+  PrintToken (STRING_TOKEN (STR_DP_DASHES));\r
+\r
+  for ( TIndex = 0; TIndex < NumCum; ++TIndex) {\r
+    avgval = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);\r
+    PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS),\r
+                CumData[TIndex].Name,\r
+                CumData[TIndex].Count,\r
+                DurationInMicroSeconds(CumData[TIndex].Duration),\r
+                DurationInMicroSeconds(avgval),\r
+                DurationInMicroSeconds(CumData[TIndex].MinDur),\r
+                DurationInMicroSeconds(CumData[TIndex].MaxDur)\r
+               );\r
+  }\r
+}\r
diff --git a/PerformancePkg/Dp_App/DpUtilities.c b/PerformancePkg/Dp_App/DpUtilities.c
new file mode 100644 (file)
index 0000000..7f88a40
--- /dev/null
@@ -0,0 +1,317 @@
+/** @file\r
+  * Utility functions used by the Dp application.\r
+  *\r
+  * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+  * This program and the accompanying materials\r
+  * are licensed and made available under the terms and conditions of the BSD License\r
+  * which accompanies this distribution.  The full text of the license may be found at\r
+  * http://opensource.org/licenses/bsd-license.php\r
+  *\r
+  * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/Driverbinding.h>\r
+\r
+#include <Guid/Performance.h>\r
+\r
+#include "Dp.h"\r
+#include "Literals.h"\r
+#include "DpInternal.h"\r
+\r
+/** Calculate an event's duration in timer ticks.\r
+  *\r
+  * Given the count direction and the event's start and end timer values,\r
+  * calculate the duration of the event in timer ticks.  Information for\r
+  * the current measurement is pointed to by the parameter.\r
+  *\r
+  * If the measurement's start time is 1, it indicates that the developer\r
+  * is indicating that the measurement began at the release of reset.\r
+  * The start time is adjusted to the timer's starting count before performing\r
+  * the elapsed time calculation.\r
+  *\r
+  * The calculated duration, in ticks, is the absolute difference between\r
+  * the measurement's ending and starting counts.\r
+  *\r
+  * @pre  The global TimerInfo structure must have already been initialized\r
+  *       before this function is called.\r
+  *\r
+  * @param[in,out]    Measurement   Pointer to a MEASUREMENT_RECORD structure containing\r
+  *                   data for the current measurement.\r
+  *\r
+  * @return       The 64-bit duration of the event.\r
+**/\r
+UINT64\r
+GetDuration (\r
+  IN OUT MEASUREMENT_RECORD   *Measurement\r
+  )\r
+{\r
+  UINT64    Duration;\r
+  BOOLEAN   Error;\r
+\r
+  // PERF_START macros are called with a value of 1 to indicate\r
+  // the beginning of time.  So, adjust the start ticker value\r
+  // to the real beginning of time.\r
+  // Assumes no wraparound.  Even then, there is a very low probability\r
+  // of having a valid StartTicker value of 1.\r
+  if (Measurement->StartTimeStamp == 1) {\r
+    Measurement->StartTimeStamp = TimerInfo.StartCount;\r
+  }\r
+  if (TimerInfo.CountUp) {\r
+    Duration = Measurement->EndTimeStamp - Measurement->StartTimeStamp;\r
+    Error = (BOOLEAN)(Duration > Measurement->EndTimeStamp);\r
+  }\r
+  else {\r
+    Duration = Measurement->StartTimeStamp - Measurement->EndTimeStamp;\r
+    Error = (BOOLEAN)(Duration > Measurement->StartTimeStamp);\r
+  }\r
+\r
+  if (Error) {\r
+    DEBUG ((EFI_D_ERROR, ALit_TimerLibError));\r
+    Duration = 0;\r
+  }\r
+  return Duration;\r
+}\r
+\r
+/** Determine whether the Measurement record is for an EFI Phase.\r
+  *\r
+  * The Token and Module members of the measurement record are checked.\r
+  * Module must be empty and Token must be one of SEC, PEI, DXE, BDS, or SHELL.\r
+  *\r
+  * @param[in]  Measurement A pointer to the Measurement record to test.\r
+  *\r
+  * @retval     TRUE        The measurement record is for an EFI Phase.\r
+  * @retval     FALSE       The measurement record is NOT for an EFI Phase.\r
+**/\r
+BOOLEAN\r
+IsPhase(\r
+  IN MEASUREMENT_RECORD        *Measurement\r
+  )\r
+{\r
+  BOOLEAN   RetVal;\r
+\r
+  RetVal = (BOOLEAN)( ( *Measurement->Module == '\0')                               &&\r
+            ((AsciiStrnCmp (Measurement->Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0)    ||\r
+             (AsciiStrnCmp (Measurement->Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0)    ||\r
+             (AsciiStrnCmp (Measurement->Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0)    ||\r
+             (AsciiStrnCmp (Measurement->Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0))\r
+            );\r
+  return RetVal;\r
+}\r
+\r
+/** Get the file name portion of the Pdb File Name.\r
+  *\r
+  * The portion of the Pdb File Name between the last backslash and\r
+  * either a following period or the end of the string is converted\r
+  * to Unicode and copied into UnicodeBuffer.  The name is truncated,\r
+  * if necessary, to ensure that UnicodeBuffer is not overrun.\r
+  *\r
+  * @param[in]  PdbFileName     Pdb file name.\r
+  * @param[out] UnicodeBuffer   The resultant Unicode File Name.\r
+  *\r
+**/\r
+VOID\r
+GetShortPdbFileName (\r
+  IN  CHAR8     *PdbFileName,\r
+  OUT CHAR16    *UnicodeBuffer\r
+  )\r
+{\r
+  UINTN IndexA;     // Current work location within an ASCII string.\r
+  UINTN IndexU;     // Current work location within a Unicode string.\r
+  UINTN StartIndex;\r
+  UINTN EndIndex;\r
+\r
+  ZeroMem (UnicodeBuffer, DXE_PERFORMANCE_STRING_LENGTH * sizeof (CHAR16));\r
+\r
+  if (PdbFileName == NULL) {\r
+    StrCpy (UnicodeBuffer, L" ");\r
+  } else {\r
+    StartIndex = 0;\r
+    for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r
+      ;\r
+    for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) {\r
+      if (PdbFileName[IndexA] == '\\') {\r
+        StartIndex = IndexA + 1;\r
+      }\r
+\r
+      if (PdbFileName[IndexA] == '.') {\r
+        EndIndex = IndexA;\r
+      }\r
+    }\r
+\r
+    IndexU = 0;\r
+    for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) {\r
+      UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA];\r
+      IndexU++;\r
+      if (IndexU >= DXE_PERFORMANCE_STRING_LENGTH) {\r
+        UnicodeBuffer[DXE_PERFORMANCE_STRING_LENGTH] = 0;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/** Get a human readable name for an image handle.\r
+  *\r
+  * @param[in]    Handle\r
+  *\r
+  * @post   The resulting Unicode name string is stored in the\r
+  *         mGaugeString global array.\r
+  *\r
+**/\r
+VOID\r
+GetNameFromHandle (\r
+  IN EFI_HANDLE   Handle\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_LOADED_IMAGE_PROTOCOL   *Image;\r
+  CHAR8                       *PdbFileName;\r
+  EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
+  EFI_STRING                  StringPtr;\r
+\r
+  // Proactively get the error message so it will be ready if needed\r
+  StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_ERROR_NAME), NULL);\r
+  ASSERT (StringPtr != NULL);\r
+\r
+  // Get handle name from image protocol\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                Handle,\r
+                &gEfiLoadedImageProtocolGuid,\r
+                &Image\r
+                );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Status = gBS->OpenProtocol (\r
+                  Handle,\r
+                  &gEfiDriverBindingProtocolGuid,\r
+                  (VOID **) &DriverBinding,\r
+                  NULL,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+    if (EFI_ERROR (Status)) {\r
+      StrCpy (mGaugeString, StringPtr);\r
+      return ;\r
+    }\r
+\r
+    // Get handle name from image protocol\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                  DriverBinding->ImageHandle,\r
+                  &gEfiLoadedImageProtocolGuid,\r
+                  &Image\r
+                  );\r
+  }\r
+\r
+  PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);\r
+\r
+  if (PdbFileName != NULL) {\r
+    GetShortPdbFileName (PdbFileName, mGaugeString);\r
+  } else {\r
+    StrCpy (mGaugeString, StringPtr);\r
+  }\r
+  return ;\r
+}\r
+\r
+/** Calculate the Duration in microseconds.\r
+  *\r
+  * Duration is multiplied by 1000, instead of Frequency being divided by 1000 or\r
+  * multiplying the result by 1000, in order to maintain precision.  Since Duration is\r
+  * a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow.\r
+  *\r
+  * The time is calculated as (Duration * 1000) / Timer_Frequency.\r
+  *\r
+  * @param[in]  Duration   The event duration in timer ticks.\r
+  *\r
+  * @return     A 64-bit value which is the Elapsed time in microseconds.\r
+**/\r
+UINT64\r
+DurationInMicroSeconds (\r
+  IN UINT64 Duration\r
+  )\r
+{\r
+  UINT64 Temp;\r
+\r
+  Temp = MultU64x32 (Duration, 1000);\r
+  return DivU64x32 (Temp, TimerInfo.Frequency);\r
+}\r
+\r
+/** Formatted Print using a Hii Token to reference the localized format string.\r
+  *\r
+  * @param[in]  Token   A HII token associated with a localized Unicode string.\r
+  *\r
+  * @return             The number of characters converted by UnicodeVSPrint().\r
+  *\r
+**/\r
+UINTN\r
+PrintToken (\r
+  IN UINT16           Token,\r
+  ...\r
+  )\r
+{\r
+  VA_LIST           Marker;\r
+  EFI_STRING        StringPtr;\r
+  UINTN             Return;\r
+  UINTN             BufferSize;\r
+\r
+  StringPtr = HiiGetString (gHiiHandle, Token, NULL);\r
+  ASSERT (StringPtr != NULL);\r
+\r
+  VA_START (Marker, Token);\r
+\r
+  BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16);\r
+\r
+  if (mPrintTokenBuffer == NULL) {\r
+    mPrintTokenBuffer = AllocatePool (BufferSize);\r
+    ASSERT (mPrintTokenBuffer != NULL);\r
+  }\r
+  SetMem( mPrintTokenBuffer, BufferSize, 0);\r
+\r
+  Return = UnicodeVSPrint (mPrintTokenBuffer, BufferSize, StringPtr, Marker);\r
+  if (Return > 0 && gST->ConOut != NULL) {\r
+    gST->ConOut->OutputString (gST->ConOut, mPrintTokenBuffer);\r
+  }\r
+  return Return;\r
+}\r
+\r
+/** Get index of Measurement Record's match in the CumData array.\r
+  *\r
+  * If the Measurement's Token value matches a Token in one of the CumData\r
+  * records, the index of the matching record is returned.  The returned\r
+  * index is a signed value so that negative values can indicate that\r
+  * the Measurement didn't match any entry in the CumData array.\r
+  *\r
+  * @param[in]  Measurement A pointer to a Measurement Record to match against the CumData array.\r
+  *\r
+  * @retval     <0    Token is not in the CumData array.\r
+  * @retval     >=0   Return value is the index into CumData where Token is found.\r
+**/\r
+INTN\r
+GetCumulativeItem(\r
+  IN MEASUREMENT_RECORD   *Measurement\r
+  )\r
+{\r
+  INTN    Index;\r
+\r
+  for( Index = 0; Index < (INTN)NumCum; ++Index) {\r
+    if (AsciiStrnCmp (Measurement->Token, CumData[Index].Name, PERF_TOKEN_LENGTH) == 0) {\r
+      return Index;  // Exit, we found a match\r
+    }\r
+  }\r
+  // If the for loop exits, Token was not found.\r
+  return -1;   // Indicate failure\r
+}\r
diff --git a/PerformancePkg/Dp_App/Literals.c b/PerformancePkg/Dp_App/Literals.c
new file mode 100644 (file)
index 0000000..efc7d1f
--- /dev/null
@@ -0,0 +1,46 @@
+/** @file\r
+  * Definitions of ASCII string literals used by DP.\r
+  *\r
+  * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+  * This program and the accompanying materials\r
+  * are licensed and made available under the terms and conditions of the BSD License\r
+  * which accompanies this distribution.  The full text of the license may be found at\r
+  * http://opensource.org/licenses/bsd-license.php\r
+  *\r
+  * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+#include <PerformanceTokens.h>\r
+\r
+// ASCII String literals which probably don't need translation\r
+CHAR8 const ALit_TimerLibError[] = "Timer library instance error!\n";\r
+CHAR8 const ALit_SEC[]    = SEC_TOK;\r
+CHAR8 const ALit_DXE[]    = DXE_TOK;\r
+CHAR8 const ALit_SHELL[]  = SHELL_TOK;\r
+CHAR8 const ALit_PEI[]    = PEI_TOK;\r
+CHAR8 const ALit_BDS[]    = BDS_TOK;\r
+CHAR8 const ALit_BdsTO[]  = "BdsTimeOut";\r
+CHAR8 const ALit_PEIM[]   = "PEIM";\r
+\r
+/// UNICODE String literals which should probably be translated\r
+CHAR16  STR_DP_OPTION_UA[]   = L"-A";\r
+CHAR16  STR_DP_OPTION_LA[]   = L"-a";\r
+CHAR16  STR_DP_OPTION_LN[]   = L"-n";\r
+CHAR16  STR_DP_OPTION_LT[]   = L"-t";\r
+CHAR16  STR_DP_OPTION_UP[]   = L"-P";\r
+CHAR16  STR_DP_OPTION_UR[]   = L"-R";\r
+CHAR16  STR_DP_OPTION_LS[]   = L"-s";\r
+CHAR16  STR_DP_OPTION_US[]   = L"-S";\r
+CHAR16  STR_DP_OPTION_UT[]   = L"-T";\r
+CHAR16  STR_DP_OPTION_LV[]   = L"-v";\r
+CHAR16  STR_DP_OPTION_QH[]   = L"-?";\r
+CHAR16  STR_DP_OPTION_LH[]   = L"-h";\r
+CHAR16  STR_DP_OPTION_UH[]   = L"-H";\r
+CHAR16  STR_DP_OPTION_LX[]   = L"-x";\r
+\r
+CHAR16 const ALit_UNKNOWN[]       = L"Unknown";\r
+CHAR16 const STR_DP_INCOMPLETE[]  = L" I ";\r
+CHAR16 const STR_DP_COMPLETE[]    = L"   ";\r
+\r
+CHAR8 const ALit_TRUE[]   = "TRUE";\r
+CHAR8 const ALit_FALSE[]  = "FALSE";\r
diff --git a/PerformancePkg/Dp_App/Literals.h b/PerformancePkg/Dp_App/Literals.h
new file mode 100644 (file)
index 0000000..d50dd70
--- /dev/null
@@ -0,0 +1,49 @@
+/** @file\r
+  * Declarations of ASCII string literals used by DP.\r
+  *\r
+  * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+  * This program and the accompanying materials\r
+  * are licensed and made available under the terms and conditions of the BSD License\r
+  * which accompanies this distribution.  The full text of the license may be found at\r
+  * http://opensource.org/licenses/bsd-license.php\r
+  *\r
+  * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+#ifndef _LITERALS_H_\r
+#define _LITERALS_H_\r
+\r
+// ASCII String literals which probably don't need translation\r
+extern CHAR8 const ALit_TimerLibError[];\r
+extern CHAR8 const ALit_SEC[];\r
+extern CHAR8 const ALit_DXE[];\r
+extern CHAR8 const ALit_SHELL[];\r
+extern CHAR8 const ALit_PEI[];\r
+extern CHAR8 const ALit_BDS[];\r
+extern CHAR8 const ALit_BdsTO[];\r
+extern CHAR8 const ALit_PEIM[];\r
+\r
+/// UNICODE String literals which should probably be translated\r
+extern CHAR16  STR_DP_OPTION_UA[];\r
+extern CHAR16  STR_DP_OPTION_LA[];\r
+extern CHAR16  STR_DP_OPTION_LN[];\r
+extern CHAR16  STR_DP_OPTION_LT[];\r
+extern CHAR16  STR_DP_OPTION_UP[];\r
+extern CHAR16  STR_DP_OPTION_UR[];\r
+extern CHAR16  STR_DP_OPTION_LS[];\r
+extern CHAR16  STR_DP_OPTION_US[];\r
+extern CHAR16  STR_DP_OPTION_UT[];\r
+extern CHAR16  STR_DP_OPTION_LV[];\r
+extern CHAR16  STR_DP_OPTION_QH[];\r
+extern CHAR16  STR_DP_OPTION_LH[];\r
+extern CHAR16  STR_DP_OPTION_UH[];\r
+extern CHAR16  STR_DP_OPTION_LX[];\r
+\r
+extern CHAR16 const ALit_UNKNOWN[];\r
+extern CHAR16 const STR_DP_INCOMPLETE[];\r
+extern CHAR16 const STR_DP_COMPLETE[];\r
+\r
+extern CHAR8 const ALit_TRUE[];\r
+extern CHAR8 const ALit_FALSE[];\r
+\r
+#endif  // _LITERALS_H_\r
diff --git a/PerformancePkg/Include/Ich/GenericIch.h b/PerformancePkg/Include/Ich/GenericIch.h
new file mode 100644 (file)
index 0000000..67af774
--- /dev/null
@@ -0,0 +1,54 @@
+/** @file\r
+  Generic definitions for registers in the Intel Ich devices.\r
+\r
+  These definitions should work for any version of Ich.\r
+\r
+  Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _GENERIC_ICH_H_\r
+#define _GENERIC_ICH_H_\r
+\r
+/** @defgroup GenericIchDefs  Generic ICH Definitions.\r
+\r
+Definitions beginning with "R_" are registers.\r
+Definitions beginning with "B_" are bits within registers.\r
+Definitions beginning with "V_" are meaningful values of bits within the registers.\r
+**/\r
+///@{\r
+\r
+/// @defgroup IchPciAddressing  PCI Bus Address for ICH.\r
+///@{\r
+#define PCI_BUS_NUMBER_ICH                0x00  ///< ICH is on PCI Bus 0.\r
+#define PCI_DEVICE_NUMBER_ICH_LPC           31  ///< ICH is Device 31.\r
+#define PCI_FUNCTION_NUMBER_ICH_LPC          0  ///< ICH is Function 0.\r
+///@}\r
+\r
+/// @defgroup IchAcpiCntr   Control for the ICH's ACPI Counter.\r
+///@{\r
+#define R_ICH_LPC_ACPI_BASE                   0x40\r
+#define R_ICH_LPC_ACPI_CNT                    0x44\r
+#define   B_ICH_LPC_ACPI_CNT_ACPI_EN              0x80\r
+///@}\r
+\r
+/// @defgroup IchAcpiTimer  The ICH's ACPI Timer.\r
+///@{\r
+#define R_ACPI_PM1_TMR                        0x08\r
+#define   V_ACPI_TMR_FREQUENCY                    3579545\r
+#define   V_ACPI_PM1_TMR_MAX_VAL                  0x1000000 ///< The timer is 24 bit overflow.\r
+///@}\r
+\r
+/// Macro to generate the PCI address of any given ICH Register.\r
+#define PCI_ICH_LPC_ADDRESS(Register) \\r
+  ((UINTN)(PCI_LIB_ADDRESS (PCI_BUS_NUMBER_ICH, PCI_DEVICE_NUMBER_ICH_LPC, PCI_FUNCTION_NUMBER_ICH_LPC, Register)))\r
+\r
+///@}\r
+#endif  // _GENERIC_ICH_H_\r
diff --git a/PerformancePkg/Include/PerformanceTokens.h b/PerformancePkg/Include/PerformanceTokens.h
new file mode 100644 (file)
index 0000000..8a69415
--- /dev/null
@@ -0,0 +1,28 @@
+/** @file\r
+  ASCII String Literals with special meaning to Performance measurement and the Dp utility.\r
+\r
+Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __PERFORMANCE_TOKENS_H__\r
+#define __PERFORMANCE_TOKENS_H__\r
+\r
+#define SEC_TOK                         "SEC"             ///< SEC Phase\r
+#define DXE_TOK                         "DXE"             ///< DEC Phase\r
+#define SHELL_TOK                       "SHELL"           ///< Shell Phase\r
+#define PEI_TOK                         "PEI"             ///< PEI Phase\r
+#define BDS_TOK                         "BDS"             ///< BDS Phase\r
+#define DRIVERBINDING_START_TOK         "DB:Start:"       ///< Driver Binding Start() function call\r
+#define DRIVERBINDING_SUPPORT_TOK       "DB:Support:"     ///< Driver Binding Support() function call\r
+#define LOAD_IMAGE_TOK                  "LoadImage:"      ///< Load a dispatched module\r
+#define START_IMAGE_TOK                 "StartImage:"     ///< Dispatched Modules Entry Point execution\r
+\r
+#endif  // __PERFORMANCE_TOKENS_H__\r
diff --git a/PerformancePkg/Library/TscTimerLib/TscTimerLib.c b/PerformancePkg/Library/TscTimerLib/TscTimerLib.c
new file mode 100644 (file)
index 0000000..19151a4
--- /dev/null
@@ -0,0 +1,243 @@
+/** @file\r
+  A Timer Library implementation which uses the Time Stamp Counter in the processor.\r
+\r
+  For Pentium 4 processors, Intel Xeon processors (family [0FH], models [03H and higher]);\r
+    for Intel Core Solo and Intel Core Duo processors (family [06H], model [0EH]);\r
+    for the Intel Xeon processor 5100 series and Intel Core 2 Duo processors (family [06H], model [0FH]);\r
+    for Intel Core 2 and Intel Xeon processors (family [06H], display_model [17H]);\r
+    for Intel Atom processors (family [06H], display_model [1CH]):\r
+  the time-stamp counter increments at a constant rate.\r
+  That rate may be set by the maximum core-clock to bus-clock ratio of the processor or may be set by\r
+  the maximum resolved frequency at which the processor is booted. The maximum resolved frequency may\r
+  differ from the maximum qualified frequency of the processor.\r
+\r
+  The specific processor configuration determines the behavior. Constant TSC behavior ensures that the\r
+  duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if\r
+  the processor core changes frequency.  This is the architectural behavior moving forward.\r
+\r
+  A Processor\92s support for invariant TSC is indicated by CPUID.0x80000007.EDX[8].\r
+\r
+  Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+#include <Ich/GenericIch.h>\r
+\r
+#include <Library/TimerLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+STATIC UINT64   mTscFrequency;\r
+\r
+#ifndef R_ICH_ACPI_PM1_TMR\r
+#define R_ICH_ACPI_PM1_TMR  R_ACPI_PM1_TMR\r
+#endif\r
+\r
+/** The constructor function determines the actual TSC frequency.\r
+\r
+  The TSC counting frequency is determined by comparing how far it counts\r
+  during a 1ms period as determined by the ACPI timer.  The ACPI timer is\r
+  used because it counts at a known frequency.\r
+  If ACPI I/O space not enabled, this function will enable it.  Then the\r
+  TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms.\r
+  The TSC is then sampled again. The difference multiplied by 1000 is the TSC\r
+  frequency.  There will be a small error because of the overhead of reading\r
+  the ACPI timer.  An attempt is made to determine and compensate for this error.\r
+  This function will always return RETURN_SUCCESS.\r
+\r
+  @retval RETURN_SUCCESS   The constructor always returns RETURN_SUCCESS.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+TscTimerLibConstructor (\r
+  VOID\r
+  )\r
+{\r
+  UINT64      StartTSC;\r
+  UINT64      EndTSC;\r
+  UINT32      TimerAddr;\r
+  UINT32      Ticks;\r
+\r
+  //\r
+  // If ACPI I/O space is not enabled yet, program ACPI I/O base address and enable it.\r
+  //\r
+  if ((PciRead8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT)) & B_ICH_LPC_ACPI_CNT_ACPI_EN) == 0) {\r
+    PciWrite16 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_BASE), PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress));\r
+    PciOr8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT), B_ICH_LPC_ACPI_CNT_ACPI_EN);\r
+  }\r
+\r
+  TimerAddr = PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress) + R_ACPI_PM1_TMR;  // Locate the ACPI Timer\r
+  Ticks    = IoRead32( TimerAddr) + (3579);   // Set Ticks to 1ms in the future\r
+  StartTSC = AsmReadTsc();                    // Get base value for the TSC\r
+  //\r
+  // Wait until the ACPI timer has counted 1ms.\r
+  // Timer wrap-arounds are handled correctly by this function.\r
+  // When the current ACPI timer value is greater than 'Ticks', the while loop will exit.\r
+  //\r
+  while (((Ticks - IoRead32( TimerAddr)) & BIT23) == 0) {\r
+    CpuPause();\r
+  }\r
+  EndTSC = AsmReadTsc();    // TSC value 1ms later\r
+\r
+  mTscFrequency =   MultU64x32 (\r
+                      (EndTSC - StartTSC),    // Number of TSC counts in 1ms\r
+                      1000                    // Number of ms in a second\r
+                    );\r
+  //\r
+  // mTscFrequency is now equal to the number of TSC counts per second\r
+  //\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**  Stalls the CPU for at least the given number of ticks.\r
+\r
+  Stalls the CPU for at least the given number of ticks. It's invoked by\r
+  MicroSecondDelay() and NanoSecondDelay().\r
+\r
+  @param[in]  Delay     A period of time to delay in ticks.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+InternalX86Delay (\r
+  IN      UINT64                    Delay\r
+  )\r
+{\r
+  UINT64                             Ticks;\r
+\r
+  //\r
+  // The target timer count is calculated here\r
+  //\r
+  Ticks = AsmReadTsc() + Delay;\r
+\r
+  //\r
+  // Wait until time out\r
+  // Timer wrap-arounds are NOT handled correctly by this function.\r
+  // Thus, this function must be called within 10 years of reset since\r
+  // Intel guarantees a minimum of 10 years before the TSC wraps.\r
+  //\r
+  while (AsmReadTsc() <= Ticks) CpuPause();\r
+}\r
+\r
+/**  Stalls the CPU for at least the specified number of MicroSeconds.\r
+\r
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.\r
+\r
+  @return The value of MicroSeconds input.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+MicroSecondDelay (\r
+  IN      UINTN                     MicroSeconds\r
+  )\r
+{\r
+  InternalX86Delay (\r
+    DivU64x32 (\r
+      MultU64x64 (\r
+        mTscFrequency,\r
+        MicroSeconds\r
+      ),\r
+      1000000u\r
+    )\r
+  );\r
+  return MicroSeconds;\r
+}\r
+\r
+/**  Stalls the CPU for at least the specified number of NanoSeconds.\r
+\r
+  @param[in]  NanoSeconds The minimum number of nanoseconds to delay.\r
+\r
+  @return The value of NanoSeconds input.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+NanoSecondDelay (\r
+  IN      UINTN                     NanoSeconds\r
+  )\r
+{\r
+  InternalX86Delay (\r
+    DivU64x32 (\r
+      MultU64x32 (\r
+        mTscFrequency,\r
+        (UINT32)NanoSeconds\r
+      ),\r
+    1000000000u\r
+    )\r
+  );\r
+  return NanoSeconds;\r
+}\r
+\r
+/**  Retrieves the current value of the 64-bit free running Time-Stamp counter.\r
+\r
+  The time-stamp counter (as implemented in the P6 family, Pentium, Pentium M,\r
+  Pentium 4, Intel Xeon, Intel Core Solo and Intel Core Duo processors and\r
+  later processors) is a 64-bit counter that is set to 0 following a RESET of\r
+  the processor.  Following a RESET, the counter increments even when the\r
+  processor is halted by the HLT instruction or the external STPCLK# pin. Note\r
+  that the assertion of the external DPSLP# pin may cause the time-stamp\r
+  counter to stop.\r
+\r
+  The properties of the counter can be retrieved by the\r
+  GetPerformanceCounterProperties() function.\r
+\r
+  @return The current value of the free running performance counter.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetPerformanceCounter (\r
+  VOID\r
+  )\r
+{\r
+  return AsmReadTsc();\r
+}\r
+\r
+/**  Retrieves the 64-bit frequency in Hz and the range of performance counter\r
+  values.\r
+\r
+  If StartValue is not NULL, then the value that the performance counter starts\r
+  with, 0x0, is returned in StartValue. If EndValue is not NULL, then the value\r
+  that the performance counter end with, 0xFFFFFFFFFFFFFFFF, is returned in\r
+  EndValue.\r
+\r
+  The 64-bit frequency of the performance counter, in Hz, is always returned.\r
+  To determine average processor clock frequency, Intel recommends the use of\r
+  EMON logic to count processor core clocks over the period of time for which\r
+  the average is required.\r
+\r
+\r
+  @param[out]   StartValue  Pointer to where the performance counter's starting value is saved, or NULL.\r
+  @param[out]   EndValue    Pointer to where the performance counter's ending value is saved, or NULL.\r
+\r
+  @return The frequency in Hz.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetPerformanceCounterProperties (\r
+  OUT      UINT64                    *StartValue,  OPTIONAL\r
+  OUT      UINT64                    *EndValue     OPTIONAL\r
+  )\r
+{\r
+  if (StartValue != NULL) {\r
+    *StartValue = 0;\r
+  }\r
+  if (EndValue != NULL) {\r
+    *EndValue = 0xFFFFFFFFFFFFFFFFull;\r
+  }\r
+\r
+  return mTscFrequency;\r
+}\r
diff --git a/PerformancePkg/Library/TscTimerLib/TscTimerLib.inf b/PerformancePkg/Library/TscTimerLib/TscTimerLib.inf
new file mode 100644 (file)
index 0000000..3f9aebf
--- /dev/null
@@ -0,0 +1,52 @@
+#/** @file\r
+#  Timer Library which uses the Time Stamp Counter in the processor.\r
+#\r
+#  A version of the Timer Library using the processor's TSC.\r
+#  The time stamp counter in newer processors may support an enhancement, referred to as invariant TSC.\r
+#  The invariant TSC runs at a constant rate in all ACPI P-, C-. and T-states.\r
+#  This is the architectural behavior moving forward.\r
+#  TSC reads are much more efficient and do not incur the overhead associated with a ring transition or\r
+#  access to a platform resource.\r
+#\r
+#  Copyright (c) 2009-2010, Intel Corporation. All rights reserved.\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = TscTimerLib\r
+  FILE_GUID                      = 95ab030f-b4fd-4ee4-92a5-9e04e87634d9\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = TimerLib\r
+\r
+  CONSTRUCTOR                    = TscTimerLibConstructor\r
+\r
+\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources.common]\r
+  TscTimerLib.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  PerformancePkg/PerformancePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  PcdLib\r
+  PciLib\r
+  IoLib\r
+  BaseLib\r
+\r
+[Pcd.common]\r
+  gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress\r
diff --git a/PerformancePkg/PerformancePkg.dec b/PerformancePkg/PerformancePkg.dec
new file mode 100644 (file)
index 0000000..b2bb19f
--- /dev/null
@@ -0,0 +1,34 @@
+#/** @file\r
+# Build description file to generate Shell DP application and\r
+# Performance Libraries.\r
+#\r
+# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+# **/\r
+\r
+[Defines]\r
+  PACKAGE_NAME                   = PerformancePkg\r
+  PACKAGE_GUID                   = ce898697-b945-46e2-a26e-5752af565185\r
+  PACKAGE_VERSION                = 0.1\r
+  DEC_SPECIFICATION              = 0x00010005\r
+\r
+[Includes.common]\r
+  Include\r
+\r
+[Guids.common]\r
+  ## Performance Package token space guid\r
+  # Include/Guid/PerformancePkgTokenSpace.h\r
+  # 669346ef-fdad-4aeb-a608-7def3f2d4621\r
+  gPerformancePkgTokenSpaceGuid       = { 0x669346ef, 0xFDad, 0x4aeb, { 0x08, 0xa6, 0x21, 0x46, 0x2d, 0x3f, 0xef, 0x7d }}\r
+\r
+[PcdsFixedAtBuild.common]\r
+  ##  The base address of the ACPI registers within the ICH PCI space.\r
+  #   This space must be 128-byte aligned.\r
+  gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress|0x400|UINT16|1\r
diff --git a/PerformancePkg/PerformancePkg.dsc b/PerformancePkg/PerformancePkg.dsc
new file mode 100644 (file)
index 0000000..026803a
--- /dev/null
@@ -0,0 +1,68 @@
+#/** @file\r
+# Build description file to generate Shell DP application.\r
+#\r
+# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+# **/\r
+\r
+[Defines]\r
+  DSC_SPECIFICATION              = 0x00010005\r
+  PLATFORM_NAME                  = PerformancePkg\r
+  PLATFORM_GUID                  = 9ffd7bf2-231e-4525-9a42-480545dafd17\r
+  PLATFORM_VERSION               = 0.1\r
+  OUTPUT_DIRECTORY               = Build/PerformancePkg\r
+  SUPPORTED_ARCHITECTURES        = IA32|IPF|X64|EBC\r
+  BUILD_TARGETS                  = DEBUG|RELEASE\r
+  SKUID_IDENTIFIER               = DEFAULT\r
+\r
+[LibraryClasses]\r
+  #\r
+  # Entry Point Libraries\r
+  #\r
+  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf\r
+  #\r
+  # Common Libraries\r
+  #\r
+  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf\r
+  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf\r
+  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf\r
+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf\r
+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf\r
+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf\r
+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf\r
+  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf\r
+  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf\r
+  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf\r
+  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf\r
+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf\r
+\r
+  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf\r
+  FileHandleLib|ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf\r
+\r
+  # This library instance mapping needs adjusting based on platform.\r
+  # The TimerLib instance must match the TimerLib the platform was built with.\r
+  # If the platform was built with more than one TimerLib type, then this utility\r
+  # will produce invalid results for any measurements done with a TimerLib instance\r
+  # that is different than the one below.\r
+  #\r
+  # TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf\r
+  TimerLib|PerformancePkg/Library/TscTimerLib/TscTimerLib.inf\r
+  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf\r
+  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf\r
+\r
+[LibraryClasses.IPF]\r
+  PalLib|MdePkg/Library/UefiPalLib/UefiPalLib.inf\r
+\r
+[Components]\r
+  PerformancePkg/Library/TscTimerLib/TscTimerLib.inf\r
+  PerformancePkg/Dp_App/Dp.inf\r