From c06ad33ed2fbbacdba42baf07f5d3fd41b36781d Mon Sep 17 00:00:00 2001 From: darylm503 Date: Fri, 23 Apr 2010 17:00:32 +0000 Subject: [PATCH 1/1] Libraries and utilities for instrumenting regions of code and measuring their performance. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10417 6f19259b-4bc3-4df7-8a09-765794883524 --- PerformancePkg/Dp_App/Dp.c | 339 +++++++++ PerformancePkg/Dp_App/Dp.h | 94 +++ PerformancePkg/Dp_App/Dp.inf | 66 ++ PerformancePkg/Dp_App/DpInternal.h | 289 ++++++++ PerformancePkg/Dp_App/DpProfile.c | 92 +++ PerformancePkg/Dp_App/DpStrings.uni | Bin 0 -> 29964 bytes PerformancePkg/Dp_App/DpTrace.c | 681 ++++++++++++++++++ PerformancePkg/Dp_App/DpUtilities.c | 317 ++++++++ PerformancePkg/Dp_App/Literals.c | 46 ++ PerformancePkg/Dp_App/Literals.h | 49 ++ PerformancePkg/Include/Ich/GenericIch.h | 54 ++ PerformancePkg/Include/PerformanceTokens.h | 28 + .../Library/TscTimerLib/TscTimerLib.c | 243 +++++++ .../Library/TscTimerLib/TscTimerLib.inf | 52 ++ PerformancePkg/PerformancePkg.dec | 34 + PerformancePkg/PerformancePkg.dsc | 68 ++ 16 files changed, 2452 insertions(+) create mode 100644 PerformancePkg/Dp_App/Dp.c create mode 100644 PerformancePkg/Dp_App/Dp.h create mode 100644 PerformancePkg/Dp_App/Dp.inf create mode 100644 PerformancePkg/Dp_App/DpInternal.h create mode 100644 PerformancePkg/Dp_App/DpProfile.c create mode 100644 PerformancePkg/Dp_App/DpStrings.uni create mode 100644 PerformancePkg/Dp_App/DpTrace.c create mode 100644 PerformancePkg/Dp_App/DpUtilities.c create mode 100644 PerformancePkg/Dp_App/Literals.c create mode 100644 PerformancePkg/Dp_App/Literals.h create mode 100644 PerformancePkg/Include/Ich/GenericIch.h create mode 100644 PerformancePkg/Include/PerformanceTokens.h create mode 100644 PerformancePkg/Library/TscTimerLib/TscTimerLib.c create mode 100644 PerformancePkg/Library/TscTimerLib/TscTimerLib.inf create mode 100644 PerformancePkg/PerformancePkg.dec create mode 100644 PerformancePkg/PerformancePkg.dsc diff --git a/PerformancePkg/Dp_App/Dp.c b/PerformancePkg/Dp_App/Dp.c new file mode 100644 index 0000000000..f5d0bda9f8 --- /dev/null +++ b/PerformancePkg/Dp_App/Dp.c @@ -0,0 +1,339 @@ +/** @file + * Shell application for Displaying Performance Metrics. + * + * The Dp application reads performance data and presents it in several + * different formats depending upon the needs of the user. Both + * Trace and Measured Profiling information is processed and presented. + * + * Dp uses the "PerformanceLib" to read the measurement records. + * The "TimerLib" provides information about the timer, such as frequency, + * beginning, and ending counter values. + * Measurement records contain identifying information (Handle, Token, Module) + * and start and end time values. + * Dp uses this information to group records in different ways. It also uses + * timer information to calculate elapsed time for each measurement. + * + * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +// +/// Module-Global Variables +/// @{ +EFI_HII_HANDLE gHiiHandle; +CHAR16 *mPrintTokenBuffer = NULL; +CHAR16 mGaugeString[DXE_PERFORMANCE_STRING_SIZE]; +CHAR16 mUnicodeToken[PERF_TOKEN_LENGTH + 1]; +UINT64 mInterestThreshold; + +PERF_SUMMARY_DATA SummaryData = { 0 }; ///< Create the SummaryData structure and init. to ZERO. + +/// Timer Specific Information. +TIMER_INFO TimerInfo; + +/// Items for which to gather cumulative statistics. +PERF_CUM_DATA CumData[] = { + PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK), + PERF_INIT_CUM_DATA (START_IMAGE_TOK), + PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK), + PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK) +}; + +/// Number of items for which we are gathering cumulative statistics. +UINT32 const NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA); + +SHELL_PARAM_ITEM DpParamList[] = { + {STR_DP_OPTION_QH, TypeFlag}, // -? Help + {STR_DP_OPTION_LH, TypeFlag}, // -h Help + {STR_DP_OPTION_UH, TypeFlag}, // -H Help + {STR_DP_OPTION_LV, TypeFlag}, // -v Verbose Mode + {STR_DP_OPTION_UA, TypeFlag}, // -A All, Cooked + {STR_DP_OPTION_UR, TypeFlag}, // -R RAW All + {STR_DP_OPTION_LS, TypeFlag}, // -s Summary +#if PROFILING_IMPLEMENTED + {STR_DP_OPTION_UP, TypeFlag}, // -P Dump Profile Data + {STR_DP_OPTION_UT, TypeFlag}, // -T Dump Trace Data +#endif + {STR_DP_OPTION_LX, TypeFlag}, // -x eXclude Cumulative Items + {STR_DP_OPTION_LN, TypeValue}, // -n # Number of records to display for A and R + {STR_DP_OPTION_LT, TypeValue}, // -t # Threshold of interest + {NULL, TypeMax} + }; + +/// @} + +/// Display Usage and Help information. +VOID +ShowHelp( void ) +{ + PrintToken (STRING_TOKEN (STR_DP_HELP_HEAD)); +#if PROFILING_IMPLEMENTED + PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS)); +#else + PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS_2)); +#endif // PROFILING_IMPLEMENTED + PrintToken (STRING_TOKEN (STR_DP_HELP_PAGINATE)); + PrintToken (STRING_TOKEN (STR_DP_HELP_VERBOSE)); + PrintToken (STRING_TOKEN (STR_DP_HELP_EXCLUDE)); + PrintToken (STRING_TOKEN (STR_DP_HELP_STAT)); + PrintToken (STRING_TOKEN (STR_DP_HELP_ALL)); + PrintToken (STRING_TOKEN (STR_DP_HELP_RAW)); +#if PROFILING_IMPLEMENTED + PrintToken (STRING_TOKEN (STR_DP_HELP_TRACE)); + PrintToken (STRING_TOKEN (STR_DP_HELP_PROFILE)); +#endif // PROFILING_IMPLEMENTED + PrintToken (STRING_TOKEN (STR_DP_HELP_THRESHOLD)); + PrintToken (STRING_TOKEN (STR_DP_HELP_COUNT)); + PrintToken (STRING_TOKEN (STR_DP_HELP_HELP)); + Print(L"\n"); +} + +/// Display the trailing Verbose information. +VOID +DumpStatistics( void ) +{ + EFI_STRING StringPtr; + + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr); + + PrintToken( STRING_TOKEN (STR_DP_STATS_NUMTRACE), SummaryData.NumTrace); + PrintToken( STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), SummaryData.NumIncomplete); + PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPHASES), SummaryData.NumSummary); + PrintToken( STRING_TOKEN (STR_DP_STATS_NUMHANDLES), SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles); + PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPEIMS), SummaryData.NumPEIMs); + PrintToken( STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), SummaryData.NumGlobal); +#if PROFILING_IMPLEMENTED + PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPROFILE), SummaryData.NumProfile); +#endif // PROFILING_IMPLEMENTED +} + +/** Dump performance data. + * + * @param[in] ImageHandle The image handle. + * @param[in] SystemTable The system table. + * + * @retval EFI_SUCCESS Command completed successfully. + * @retval EFI_INVALID_PARAMETER Command usage error. + * @retval value Unknown error. + * +**/ +EFI_STATUS +EFIAPI +InitializeDp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINT64 Freq; + UINT64 Ticker; + + LIST_ENTRY *ParamPackage; + CONST CHAR16 *CmdLineArg; + EFI_STRING StringPtr; + UINTN Number2Display; + + EFI_STATUS Status; + BOOLEAN SummaryMode = FALSE; + BOOLEAN VerboseMode = FALSE; + BOOLEAN AllMode = FALSE; + BOOLEAN RawMode = FALSE; + BOOLEAN TraceMode = FALSE; + BOOLEAN ProfileMode = FALSE; + BOOLEAN ExcludeMode = FALSE; + + + // Get DP's entry time as soon as possible. + // This is used as the Shell-Phase end time. + // + Ticker = GetPerformanceCounter (); + + // Register our string package with HII and return the handle to it. + // + gHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, DPStrings, NULL); + ASSERT (gHiiHandle != NULL); + +/**************************************************************************** +**** Process Command Line arguments **** +****************************************************************************/ + Status = ShellCommandLineParse (DpParamList, &ParamPackage, NULL, TRUE); + + if (EFI_ERROR(Status)) { + PrintToken (STRING_TOKEN (STR_DP_INVALID_ARG)); + ShowHelp(); + } + else { + if (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_QH) || + ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LH) || + ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UH)) + { + ShowHelp(); + } + else { + // Boolean Options + VerboseMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LV)); + SummaryMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_US) || + ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LS)); + AllMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UA)); + RawMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UR)); +#if PROFILING_IMPLEMENTED + TraceMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UT)); + ProfileMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UP)); +#endif // PROFILING_IMPLEMENTED + ExcludeMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LX)); + + // Options with Values + CmdLineArg = ( ShellCommandLineGetValue (ParamPackage, STR_DP_OPTION_LN)); + if (CmdLineArg == NULL) { + Number2Display = DEFAULT_DISPLAYCOUNT; + } + else { + Number2Display = StrDecimalToUintn(CmdLineArg); + if (Number2Display == 0) { + Number2Display = MAXIMUM_DISPLAYCOUNT; + } + } + CmdLineArg = (ShellCommandLineGetValue (ParamPackage, STR_DP_OPTION_LT)); + if (CmdLineArg == NULL) { + mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us + } + else { + mInterestThreshold = StrDecimalToUint64(CmdLineArg); + } + // Handle Flag combinations and default behaviors + // If both TraceMode and ProfileMode are FALSE, set them both to TRUE + if ((! TraceMode) && (! ProfileMode)) { + TraceMode = TRUE; +#if PROFILING_IMPLEMENTED + ProfileMode = TRUE; +#endif // PROFILING_IMPLEMENTED + } + +/**************************************************************************** +**** Timer specific processing **** +****************************************************************************/ + // Get the Performance counter characteristics: + // Freq = Frequency in Hz + // StartCount = Value loaded into the counter when it starts counting + // EndCount = Value counter counts to before it needs to be reset + // + Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount); + + // Convert the Frequency from Hz to KHz + TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000); + + // Determine in which direction the performance counter counts. + TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount); + +/**************************************************************************** +**** Print heading **** +****************************************************************************/ + // print DP's build version + PrintToken (STRING_TOKEN (STR_DP_BUILD_REVISION), DP_MAJOR_VERSION, DP_MINOR_VERSION); + + // print performance timer characteristics + PrintToken (STRING_TOKEN (STR_DP_KHZ), TimerInfo.Frequency); // Print Timer frequency in KHz + + if ((VerboseMode) && + (! RawMode) + ) { + StringPtr = HiiGetString (gHiiHandle, + TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN), + NULL); + ASSERT (StringPtr != NULL); + PrintToken (STRING_TOKEN (STR_DP_TIMER_PROPERTIES), // Print Timer count range and direction + StringPtr, + TimerInfo.StartCount, + TimerInfo.EndCount + ); + PrintToken (STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mInterestThreshold); + } + +/* ************************************************************************** +**** Print Sections based on command line options +**** +**** Option modes have the following priority: +**** v Verbose -- Valid in combination with any other options +**** t Threshold -- Modifies All, Raw, and Cooked output +**** Default is 0 for All and Raw mode +**** Default is DEFAULT_THRESHOLD for "Cooked" mode +**** n Number2Display Used by All and Raw mode. Otherwise ignored. +**** A All -- R and S options are ignored +**** R Raw -- S option is ignored +**** s Summary -- Modifies "Cooked" output only +**** Cooked (Default) +**** +**** The All, Raw, and Cooked modes are modified by the Trace and Profile +**** options. +**** !T && !P := (0) Default, Both are displayed +**** T && !P := (1) Only Trace records are displayed +**** !T && P := (2) Only Profile records are displayed +**** T && P := (3) Same as Default, both are displayed +****************************************************************************/ + GatherStatistics(); + if (AllMode) { + if (TraceMode) { + DumpAllTrace( Number2Display, ExcludeMode); + } + if (ProfileMode) { + DumpAllProfile( Number2Display, ExcludeMode); + } + } + else if (RawMode) { + if (TraceMode) { + DumpRawTrace( Number2Display, ExcludeMode); + } + if (ProfileMode) { + DumpRawProfile( Number2Display, ExcludeMode); + } + } + else { + //------------- Begin Cooked Mode Processing + if (TraceMode) { + ProcessPhases ( Ticker ); + if ( ! SummaryMode) { + Status = ProcessHandles ( ExcludeMode); + if ( ! EFI_ERROR( Status)) { + ProcessPeims ( ); + ProcessGlobal ( ); + ProcessCumulative (); + } + } + } + if (ProfileMode) { + DumpAllProfile( Number2Display, ExcludeMode); + } + } //------------- End of Cooked Mode Processing + if ( VerboseMode || SummaryMode) { + DumpStatistics(); + } + } + } + (void) FreePool (mPrintTokenBuffer); + HiiRemovePackages (gHiiHandle); + return Status; +} diff --git a/PerformancePkg/Dp_App/Dp.h b/PerformancePkg/Dp_App/Dp.h new file mode 100644 index 0000000000..eb0537345b --- /dev/null +++ b/PerformancePkg/Dp_App/Dp.h @@ -0,0 +1,94 @@ +/** @file + * Common declarations for the Dp Performance Reporting Utility. + * + * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _EFI_APP_DP_H_ +#define _EFI_APP_DP_H_ + +#define DP_MAJOR_VERSION 2 +#define DP_MINOR_VERSION 3 + +/** + * The value assigned to DP_DEBUG controls which debug output + * is generated. Set it to ZERO to disable. +**/ +#define DP_DEBUG 0 + +/** + * Set to 1 once Profiling has been implemented in order to enable + * profiling related options and report output. +**/ +#define PROFILING_IMPLEMENTED 0 + +#define DEFAULT_THRESHOLD 1000 ///< One millisecond. +#define DEFAULT_DISPLAYCOUNT 50 +#define MAXIMUM_DISPLAYCOUNT 999999 ///< Arbitrary maximum reasonable number. + +#define PERF_MAXDUR 0xFFFFFFFFFFFFFFFFULL + +/// Determine whether 0 <= C < L. If L == 0, return true regardless of C. +#define WITHIN_LIMIT( C, L) ( ((L) == 0) || ((C) < (L)) ) + +/// Structure for storing Timer specific information. +typedef struct { + UINT64 StartCount; ///< Value timer is initialized with. + UINT64 EndCount; ///< Value timer has just before it wraps. + UINT32 Frequency; ///< Timer count frequency in KHz. + BOOLEAN CountUp; ///< TRUE if the counter counts up. +} TIMER_INFO; + +/** Initialize one PERF_CUM_DATA structure instance for token t. + * + * This parameterized macro takes a single argument, t, which is expected + * to resolve to a pointer to an ASCII string literal. This parameter may + * take any one of the following forms: + * - PERF_INIT_CUM_DATA("Token") A string literal + * - PERF_INIT_CUM_DATA(pointer) A pointer -- CHAR8 *pointer; + * - PERF_INIT_CUM_DATA(array) Address of an array -- CHAR8 array[N]; +**/ +#define PERF_INIT_CUM_DATA(t) { 0ULL, PERF_MAXDUR, 0ULL, (t), 0U } + +typedef struct { + UINT64 Duration; ///< Cumulative duration for this item. + UINT64 MinDur; ///< Smallest duration encountered. + UINT64 MaxDur; ///< Largest duration encountered. + CHAR8 *Name; ///< ASCII name of this item. + UINT32 Count; ///< Total number of measurements accumulated. +} PERF_CUM_DATA; + +typedef struct { + UINT32 NumTrace; ///< Number of recorded TRACE performance measurements. + UINT32 NumProfile; ///< Number of recorded PROFILE performance measurements. + UINT32 NumIncomplete; ///< Number of measurements with no END value. + UINT32 NumSummary; ///< Number of summary section measurements. + UINT32 NumHandles; ///< Number of measurements with handles. + UINT32 NumPEIMs; ///< Number of measurements of PEIMs. + UINT32 NumGlobal; ///< Number of measurements with END value and NULL handle. +} PERF_SUMMARY_DATA; + +typedef struct { + VOID *Handle; + CHAR8 *Token; ///< Measured token string name. + CHAR8 *Module; ///< Module string name. + UINT64 StartTimeStamp; ///< Start time point. + UINT64 EndTimeStamp; ///< End time point. +} MEASUREMENT_RECORD; + +typedef struct { + CHAR8 *Name; ///< Measured token string name. + UINT64 CumulativeTime; ///< Accumulated Elapsed Time. + UINT64 MinTime; ///< Minimum Elapsed Time. + UINT64 MaxTime; ///< Maximum Elapsed Time. + UINT32 Count; ///< Number of measurements accumulated. +} PROFILE_RECORD; + +#endif // _EFI_APP_DP_H_ diff --git a/PerformancePkg/Dp_App/Dp.inf b/PerformancePkg/Dp_App/Dp.inf new file mode 100644 index 0000000000..6849ab9569 --- /dev/null +++ b/PerformancePkg/Dp_App/Dp.inf @@ -0,0 +1,66 @@ +#/** @file +# Display Performance Application, Module information file. +# +# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = DP + FILE_GUID = 7d5ff0e3-2fb7-4e19-8419-44266cb60000 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeDp + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DpStrings.uni + Dp.c + Literals.c + DpUtilities.c + DpTrace.c + DpProfile.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + PerformancePkg/PerformancePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + ShellLib + BaseMemoryLib + BaseLib + MemoryAllocationLib + DebugLib + UefiBootServicesTableLib + TimerLib + PeCoffGetEntryPointLib + PerformanceLib + PrintLib + UefiLib + HiiLib + PcdLib + +[Guids] + +[Protocols] + gEfiLoadedImageProtocolGuid # ALWAYS_CONSUMED + gEfiDriverBindingProtocolGuid # ALWAYS_CONSUMED + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize diff --git a/PerformancePkg/Dp_App/DpInternal.h b/PerformancePkg/Dp_App/DpInternal.h new file mode 100644 index 0000000000..9335580093 --- /dev/null +++ b/PerformancePkg/Dp_App/DpInternal.h @@ -0,0 +1,289 @@ +/** @file + * Declarations of objects defined internally to the Dp Application. + * + * Declarations of data and functions which are private to the Dp application. + * This file should never be referenced by anything other than components of the + * Dp application. In addition to global data, function declarations for + * DpUtilities.c, DpTrace.c, and DpProfile.c are included here. + * + * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +// +/// Module-Global Variables +/// @{ +extern EFI_HII_HANDLE gHiiHandle; +extern CHAR16 *mPrintTokenBuffer; +extern CHAR16 mGaugeString[DXE_PERFORMANCE_STRING_SIZE]; +extern CHAR16 mUnicodeToken[PERF_TOKEN_LENGTH + 1]; +extern UINT64 mInterestThreshold; + +extern PERF_SUMMARY_DATA SummaryData;; ///< Create the SummaryData structure and init. to ZERO. + +/// Timer Specific Information. +extern TIMER_INFO TimerInfo; + +/// Items for which to gather cumulative statistics. +extern PERF_CUM_DATA CumData[]; + +/// Number of items for which we are gathering cumulative statistics. +extern UINT32 const NumCum; + +/// @} + +/** Calculate an event's duration in timer ticks. + * + * Given the count direction and the event's start and end timer values, + * calculate the duration of the event in timer ticks. + * + * @pre The global TimerInfo structure must have already been initialized + * before this function is called. + * + * @param[in,out] Measurement Pointer to a structure containing data for the current measurement. + * + * @return The 64-bit duration of the event. +**/ +UINT64 +GetDuration ( + IN OUT MEASUREMENT_RECORD *Measurement +); + +/** Determine whether the Measurement record is for an EFI Phase. + * + * The Token and Module members of the measurement record are checked. + * Module must be empty and Token must be one of SEC, PEI, DXE, or BDS. + * + * @param[in] Measurement A pointer to the Measurement record to test. + * + * @retval TRUE The measurement record is for an EFI Phase. + * @retval FALSE The measurement record is NOT for an EFI Phase. +**/ +BOOLEAN +IsPhase( + IN MEASUREMENT_RECORD *Measurement +); + +/** Get the file name portion of the Pdb File Name. + * + * The portion of the Pdb File Name between the last backslash and + * either a following period or the end of the string is converted + * to Unicode and copied into UnicodeBuffer. The name is truncated, + * if necessary, to ensure that UnicodeBuffer is not overrun. + * + * @param[in] PdbFileName Pdb file name. + * @param[out] UnicodeBuffer The resultant Unicode File Name. + * +**/ +VOID +GetShortPdbFileName ( + IN CHAR8 *PdbFileName, + OUT CHAR16 *UnicodeBuffer +); + +/** Get a human readable name for an image handle. + * + * @param[in] Handle + * + * @post The resulting Unicode name string is stored in the + * mGaugeString global array. + * +**/ +VOID +GetNameFromHandle ( + IN EFI_HANDLE Handle +); + +/** Calculate the Duration in microseconds. + * + * Duration is multiplied by 1000, instead of Frequency being divided by 1000 + * in order to maintain precision. Since Duration is + * a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow. + * + * @param[in] Duration The event duration in timer ticks. + * + * @return A 64-bit value which is the Elapsed time in microseconds. +**/ +UINT64 +DurationInMicroSeconds ( + IN UINT64 Duration +); + +/** Formatted Print using a Hii Token to reference the localized format string. + * + * @param[in] Token A HII token associated with a localized Unicode string. + * + * @return The number of characters converted by UnicodeVSPrint(). + * +**/ +UINTN +PrintToken ( + IN UINT16 Token, + ... +); + +/** Get index of Measurement Record's match in the CumData array. + * + * @param[in] Measurement A pointer to a Measurement Record to match against the CumData array. + * + * @retval <0 Token is not in the CumData array. + * @retval >=0 Return value is the index into CumData where Token is found. +**/ +INTN +GetCumulativeItem( + IN MEASUREMENT_RECORD *Measurement +); + +/** Collect verbose statistics about the logged performance measurements. + * + * General Summary information for all Trace measurements is gathered and + * stored within the SummaryData structure. This information is both + * used internally by subsequent reporting functions, and displayed + * at the end of verbose reports. + * + * @pre The SummaryData and CumData structures must be initialized + * prior to calling this function. + * + * @post The SummaryData and CumData structures contain statistics for the + * current performance logs. +**/ +VOID +GatherStatistics( + VOID +); + +/** Gather and print ALL Trace Records. + * + * Displays all "interesting" Trace measurements in order. + * The number of records displayed is controlled by: + * - records with a duration less than mInterestThreshold microseconds are not displayed. + * - No more than Limit records are displayed. A Limit of zero will not limit the output. + * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + * displayed. + * + * @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + * The mGaugeString and mUnicodeToken global arrays are used for temporary string storage. + * They must not be in use by a calling function. + * + * @param[in] Limit The number of records to print. Zero is ALL. + * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + * +**/ +VOID +DumpAllTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag +); + +/** Gather and print Raw Trace Records. + * + * All Trace measurements with a duration greater than or equal to + * mInterestThreshold are printed without interpretation. + * + * The number of records displayed is controlled by: + * - records with a duration less than mInterestThreshold microseconds are not displayed. + * - No more than Limit records are displayed. A Limit of zero will not limit the output. + * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + * displayed. + * + * @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + * + * @param[in] Limit The number of records to print. Zero is ALL. + * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + * +**/ +VOID +DumpRawTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag +); + +/** Gather and print Major Phase metrics. + * + * @param[in] Ticker The timer value for the END of Shell phase + * +**/ +VOID +ProcessPhases( + IN UINT64 Ticker +); + + +/** Gather and print Handle data. + * + * @param[in] ExcludeFlag TRUE if the -x command line flag given. Elides accumulated trace records. + * + * @return Status from a call to gBS->LocateHandle(). +**/ +EFI_STATUS +ProcessHandles( + IN BOOLEAN ExcludeFlag +); + + +/** Gather and print PEIM data. + * + * Only prints complete PEIM records + * +**/ +VOID +ProcessPeims( + VOID +); + +/** Gather and print global data. + * + * Strips out incomplete or "Execution Phase" records + * Only prints records where Handle is NULL + * Increment TIndex for every record, even skipped ones, so that we have an + * indication of every measurement record taken. + * + * +**/ +VOID +ProcessGlobal( + VOID +); + +/** Gather and print cumulative data. + * + * Traverse the measurement records and: + * for each record with a Token listed in the CumData array, + * Update the instance count and the total, minimum, and maximum durations. + * Finally, print the gathered cumulative statistics. + * +**/ +VOID +ProcessCumulative( + VOID +); + +/** Gather and print ALL Profile Records. + * + * @param[in] Limit The number of records to print. Zero is ALL. + * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display + * +**/ +VOID +DumpAllProfile( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag +); + +/** Gather and print Raw Profile Records. + * + * @param[in] Limit The number of records to print. + * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display + * +**/ +VOID +DumpRawProfile( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag +); diff --git a/PerformancePkg/Dp_App/DpProfile.c b/PerformancePkg/Dp_App/DpProfile.c new file mode 100644 index 0000000000..880e057e7c --- /dev/null +++ b/PerformancePkg/Dp_App/DpProfile.c @@ -0,0 +1,92 @@ +/** @file + * Measured Profiling reporting for the Dp utility. + * + * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +/** Gather and print ALL Profiling Records. + * + * Displays all "interesting" Profile measurements in order. + * The number of records displayed is controlled by: + * - records with a duration less than mInterestThreshold microseconds are not displayed. + * - No more than Limit records are displayed. A Limit of zero will not limit the output. + * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + * displayed. + * + * @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + * The mGaugeString and mUnicodeToken global arrays are used for temporary string storage. + * They must not be in use by a calling function. + * + * @param[in] Limit The number of records to print. Zero is ALL. + * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + * +**/ +VOID +DumpAllProfile( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ) +{ + EFI_STRING StringPtr; + + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PROFILE), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr); + return; +} + +/** Gather and print Raw Profile Records. + * + * All Profile measurements with a duration greater than or equal to + * mInterestThreshold are printed without interpretation. + * + * The number of records displayed is controlled by: + * - records with a duration less than mInterestThreshold microseconds are not displayed. + * - No more than Limit records are displayed. A Limit of zero will not limit the output. + * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + * displayed. + * + * @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + * + * @param[in] Limit The number of records to print. Zero is ALL. + * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + * +**/ +VOID +DumpRawProfile( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ) +{ + EFI_STRING StringPtr; + + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWPROFILE), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr); + return; +} diff --git a/PerformancePkg/Dp_App/DpStrings.uni b/PerformancePkg/Dp_App/DpStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..ba0b614d66ca98343548ebf4f245e5589f5d2312 GIT binary patch literal 29964 zcmd^|`)=IE6~_5@fxg4SfnYcFHAU0bXc{Pz91D@`tuA)jBv{Cj?5NenUCEAJ^nHuG zMBDE-N3%l?htzN-g>;IAc6lA1`ObCD9FG3`pL@lfaZ&MfLYSA=#?-QIq2s(Yu!TYc~8%0Cug6dT2#N)&C0iUVCWQoB>N_sX?>r2QSW zy{F$ZU9s=>cSY$*ail9b_g?oM>-v$7Kn>41(AJ?^^F61Psk{47=XSMq>?opL-#&Nm zoj>8Nwhz?8PVqwDJoSyEg0=%C_N*gEwQmK=p!Z;g3w=5%UY73rqS!2!wZB%OCD8hV z!(vz8P*?5kfvBNH&@jAs)~WXC^$XEi=EtZ2SLlDKGsYXJey6Kqs;bBsn(uYhi}U+W z&M|vOYt=J%)ynt!3z&qh zt>SU9BD%(spr^%``d%#7wZAGKcaFjjK@l~}-8&BQSH?#-s z9OIc=x|VBrs$KO+*Yfng==Up~fpTpX`06^{vGMM z6CsaOARkY})gx^^tlcrvS#W(V>P*Vewo|o@P8=kzUvymMTBP@^vCVROBd2>W)gEnn z89vpMUpnatTDR#W+GKf8RE_iutO5Fq=GA+;p?hi9 zHq%=CtoX>a&E7{sjie1e?g4%HR&*>oDqg!D zV-LoC zH`}5&|I*(bJ=bq-%+7Ajw#Kt9Y(AdtP(9tB9Yr6|Ahh{xb`;-Zt$(g#0gvXs&2uJ& zN6gJ(B4QlA{Y+kIFCwk+xkR@wa8 zk+k^GSuxIFm5GtD?fqKhD(y#+Z9Wy%Wg8u6#;a6&RPIME51tA44MlEGWu2QiFe>@< zW`F4W@ixf=#t-GlA4@xu_dG6n%esfLHm~YCB}uVGy^dbw@`9*!NxpJhamCf};+^9K zqeh}UtR?zg*AGTu@Pac$gT%hZAtIL@X$Vrd@8THRz`y#~li0u{(Z;(xht?QNG5)*T ztB3Ub92ye2GC@p*b!^vxlw`-g(IWxx>M{U_ZJa>V-=vw0i;tzb?+3wC>q%@eo10l+l@J}Wwf^F zvO8_)cEQ%{RP0~2|t5Tp-!QwT7%s7x^Umc_x`B##(XcZVJOxOhgWuh==^tiIBD|`$=^Fk+`ty_(2Ze z=eNsoc$;Q*KbPujleMk(HQ1^Gzo+Wp8bH?p!WxUx<5^D>+=C&A#%#;o0qWU|HJ#T-smlUGrW} zzkQp1^}YK1i~7&p7Mi!2g+WgLnKv2kCul@7m*+W?LMHZE!$k$k0y6C~V>6aE1DS(V z3Ypk<67Au~80(hXKa+>Exe3OqSZcX25RT&Z_ zB=?DV*QMx+btjLmi}1>`a-QlGU9se*=pr9DJhWn}+OZ-}zNDzwsuFB&nHl9Kz0bi4 z`T0zrZ=7_Y>)*M3j`>fYGS-d0cKjGqe5F5&FD9DPx7lGYTk&rWe%r$D@A^AYZiZ<4 zr6O47cF@)DC3AgZw=C`b*W6 zHj7}fx2y-hwGtJn991bItJNjGDR-Y2;skU6PjhwbbA2lEJ z!{{YH4#idnIM#XUBSW=Fy(jJXj~(KV9OCPa7u1yXEs~?T32`rXLVorZhYYUxaO7Z6lwWtfnyc97O*gv1c zB&uNM_QT~8z4@`!8?$7W(VF1XC-U{wLazv+=1&d};#iaTj;aaM5nn6Z*I2s?b?vsF z3UTJLh%%AjXWHA;pH+a@G0ee^D2Iw%YQ^6OHJev?=CJb>$Yd(Yp9OidyNZ$adX13+ zoTk0EL0K57~ z-&H%~xwN4E_-qKY_MHv+>H5~rH}9{hhqjqvi+4Gm$|>h)Pxro=55s@q*DNE0mF1m) zk=|Zo z<-N`uq1kUv`Re=7&WC{iL~+!z@Y_;U*364sK2%$kQYj-;eC zwq937c{}E46IIu1iruaXbMmQF9+Pb>f12#vuyDUh>f5o8eekj*epMqYM)FvX_>+>F z*vFJd=)_bnT%M$ymG5h`o=aIfX62cTiDrWsw=dU_3drSP#+(rL`#9eVT|^WzbN)@_aFw^lx8zm&_V!g|s`DU$;?&j?H}1MM;}9!Kw0|x_W=qJi z*2AghzG7s$$P6=zY5nr_<;V=ydC$qqHyW+{MzZsr`+Xq#7W8K4@AS(!hRCf?uRkB1 z?Rds^i_tzA`;^TB(;Pf~8~u$IVhY+Z@K;aN>vD~Rm!bGK2ZNw(;cnA8vKp41dglD9 zy~h)-innOV-u@v|&M289^~%t2A6}2S529E9Sy5!bdN8rJ`SVxvn?fdzg+3Hy@@2-} zbZgQWLpFs>?C(v#N70zka$66IPhD-ZwT4x)SlITx1QUHd&}UE9s((v$^*!mzlTT*y zpOWu>;`xcYZtXnZc8YpCw|G8_?pIv$cd)7z8Fb=3A~=7Xx;0jNvZH(UIa!E3evXb9U%Zv{TnfL;oZCuD;aHsi@@Fo4yiaMcJ`4?q`Q)J~CeM+F1zD6& zT&CHN`a#Aby8DW)^Y{AX=5_RWx(YRmVszK#PN!|H0y6oQ8Q_g8TfsD}O!~0bG2?aj zs4I_nV}ZB0ZS76+C*|lXhex5t$gfmOoI!01xld{(hz$B&XQ(@kU2zPvzE$lvZ!;f` ztY6}*0m$`JPa9Txq$->06RTJl8ou+=-WB)q>`EQ^Zn%S{t&c^84lAN!$86Og&V{!` zuq$STyv+M6hr)-e?n_s`_#9E4Cul@BzIcp%n|-fZR<|Z;%DQ4!&Zg9Hn-4R_Um>&9 z>@|lXx1QJY(A^d9_BDa#!`t5XvGsrOgS_QP)Pg^pDsCB`>~^F0B8}#6V@@im1#`GdO+wnB~ z!rS2+($cn1j+`WRB6mhaXZFwj>XoQY|ba-U~Fxm zE6lP{W6+nEXrg2uOqyeuE|^rkY2Ub{sA5Tzb8Z(XPyY=*t+(RESRXD;`;`ZVlz z1LAoyesMLR`JWsa_kPEG%cqJdzdrXfscr9zs7^Ppw9{)Y^(v{)!=4rASWW19<3;|< zPslb^qY2)}A-~OhtNlN-c+Sq^K5|vf=i@eQzbT4LUmYJU$E`u8ox7s`BY8uFs)rUaaCum@ZhE%^JcR4{1vN2U7yyzyJUM literal 0 HcmV?d00001 diff --git a/PerformancePkg/Dp_App/DpTrace.c b/PerformancePkg/Dp_App/DpTrace.c new file mode 100644 index 0000000000..fdbd860d43 --- /dev/null +++ b/PerformancePkg/Dp_App/DpTrace.c @@ -0,0 +1,681 @@ +/** @file + * Trace reporting for the Dp utility. + * + * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +/** Collect verbose statistics about the logged performance measurements. + * + * General Summary information for all Trace measurements is gathered and + * stored within the SummaryData structure. This information is both + * used internally by subsequent reporting functions, and displayed + * at the end of verbose reports. + * + * @pre The SummaryData and CumData structures must be initialized + * prior to calling this function. + * + * @post The SummaryData and CumData structures contain statistics for the + * current performance logs. +**/ +VOID +GatherStatistics( + VOID +) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINTN LogEntryKey; + UINTN TIndex; + + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp)) != 0) + { + ++SummaryData.NumTrace; // Count the number of TRACE Measurement records + if (Measurement.EndTimeStamp == 0) { + ++SummaryData.NumIncomplete; // Count the incomplete records + continue; + } + + if (Measurement.Handle != NULL) { + ++SummaryData.NumHandles; // Count the number of measurements with non-NULL handles + } + + if (IsPhase( &Measurement)) { + ++SummaryData.NumSummary; // Count the number of major phases + } + else { // !IsPhase(... + if(Measurement.Handle == NULL) { + ++SummaryData.NumGlobal; + } + } + + if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) { + ++SummaryData.NumPEIMs; // Count PEIM measurements + } + + Duration = GetDuration (&Measurement); + TIndex = GetCumulativeItem (&Measurement); + if (TIndex >= 0) { + CumData[TIndex].Duration += Duration; + CumData[TIndex].Count++; + if ( Duration < CumData[TIndex].MinDur ) { + CumData[TIndex].MinDur = Duration; + } + if ( Duration > CumData[TIndex].MaxDur ) { + CumData[TIndex].MaxDur = Duration; + } + } + } +} + +/** Gather and print ALL Trace Records. + * + * Displays all "interesting" Trace measurements in order.
+ * The number of records displayed is controlled by: + * - records with a duration less than mInterestThreshold microseconds are not displayed. + * - No more than Limit records are displayed. A Limit of zero will not limit the output. + * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + * displayed. + * + * @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + * The mGaugeString and mUnicodeToken global arrays are used for temporary string storage. + * They must not be in use by a calling function. + * + * @param[in] Limit The number of records to print. Zero is ALL. + * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + * +**/ +VOID +DumpAllTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 ElapsedTime; + UINT64 Duration; + const CHAR16 *IncFlag; + UINTN LogEntryKey; + UINTN Count; + UINTN Index; + UINTN TIndex; + + EFI_HANDLE *HandleBuffer; + UINTN Size; + EFI_HANDLE TempHandle; + EFI_STATUS Status; + + IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (IncFlag == NULL) ? ALit_UNKNOWN: IncFlag); + + // Get Handle information + // + Size = 0; + HandleBuffer = NULL; + Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocatePool (Size); + ASSERT (HandleBuffer != NULL); + Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer); + } + if (EFI_ERROR (Status)) { + PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status); + } + else { + // We have successfully populated the HandleBuffer + // Display ALL Measurement Records + // Up to Limit lines displayed + // Display only records with Elapsed times >= mInterestThreshold + // Display driver names in Module field for records with Handles. + // + PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR) ); + PrintToken (STRING_TOKEN (STR_DP_DASHES) ); + + LogEntryKey = 0; + Count = 0; + Index = 0; + while ( WITHIN_LIMIT(Count, Limit) && + ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp)) != 0) + ) + { + ++Index; // Count every record. First record is 1. + ElapsedTime = 0; + if (Measurement.EndTimeStamp != 0) { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + IncFlag = STR_DP_COMPLETE; + } + else { + IncFlag = STR_DP_INCOMPLETE; // Mark incomplete records + } + if ((ElapsedTime < mInterestThreshold) || + ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) + ) { // Ignore "uninteresting" or excluded records + continue; + } + if (Measurement.EndTimeStamp == 0) { + ElapsedTime = Measurement.StartTimeStamp; + } + ++Count; // Count the number of records printed + + // If Handle is non-zero, see if we can determine a name for the driver + AsciiStrToUnicodeStr (Measurement.Module, mGaugeString); // Use Module by default + AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken); + if (Measurement.Handle != NULL) { + // See if the Handle is in the HandleBuffer + for (TIndex = 0; TIndex < (Size / sizeof(HandleBuffer[0])); TIndex++) { + if (Measurement.Handle == HandleBuffer[TIndex]) { + GetNameFromHandle (HandleBuffer[TIndex]); + break; + } + } + } + // Ensure that the argument strings are not too long. + mGaugeString[31] = 0; + mUnicodeToken[18] = 0; + + PrintToken( STRING_TOKEN (STR_DP_ALL_STATS), + Index, // 1 based, Which measurement record is being printed + IncFlag, + Measurement.Handle, + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + } + FreePool (HandleBuffer); +} + +/** Gather and print Raw Trace Records. + * + * All Trace measurements with a duration greater than or equal to + * mInterestThreshold are printed without interpretation. + * + * The number of records displayed is controlled by: + * - records with a duration less than mInterestThreshold microseconds are not displayed. + * - No more than Limit records are displayed. A Limit of zero will not limit the output. + * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + * displayed. + * + * @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + * + * @param[in] Limit The number of records to print. Zero is ALL. + * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + * +**/ +VOID +DumpRawTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 ElapsedTime; + UINT64 Duration; + UINTN LogEntryKey; + UINTN Count; + UINTN Index; + + EFI_STRING StringPtr; + + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr); + + PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR) ); + PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES) ); + + LogEntryKey = 0; + Count = 0; + Index = 0; + while ( WITHIN_LIMIT(Count, Limit) && + ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp)) != 0) + ) + { + ++Index; // Count every record. First record is 1. + ElapsedTime = 0; + if (Measurement.EndTimeStamp != 0) { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + } + if ((ElapsedTime < mInterestThreshold) || + ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) + ) { // Ignore "uninteresting" or Excluded records + continue; + } + ++Count; // Count the number of records printed + PrintToken (STRING_TOKEN (STR_DP_RAW_VARS), + Index, // 1 based, Which measurement record is being printed + Measurement.Handle, + Measurement.StartTimeStamp, + Measurement.EndTimeStamp, + Measurement.Token, + Measurement.Module + ); + } +} + +/** Gather and print Major Phase metrics. + * + * @param[in] Ticker The timer value for the END of Shell phase + * +**/ +VOID +ProcessPhases( + UINT64 Ticker + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 BdsTimeoutValue = 0; + UINT64 SecTime = 0; + UINT64 PeiTime = 0; + UINT64 DxeTime = 0; + UINT64 BdsTime = 0; + UINT64 ShellTime = 0; + UINT64 ElapsedTime; + UINT64 Duration; + UINT64 Total; + EFI_STRING StringPtr; + UINTN LogEntryKey; + + // + // Get Execution Phase Statistics + // + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr); + + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp)) != 0) + { + if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) { + Measurement.EndTimeStamp = Ticker; + } + if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records + continue; + } + Duration = GetDuration (&Measurement); + if ( Measurement.Handle != NULL + && (AsciiStrnCmp (Measurement.Token, ALit_BdsTO, PERF_TOKEN_LENGTH) == 0) + ) + { + BdsTimeoutValue = Duration; + } else if (AsciiStrnCmp (Measurement.Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) { + SecTime = Duration; + } else if (AsciiStrnCmp (Measurement.Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) { + PeiTime = Duration; + } else if (AsciiStrnCmp (Measurement.Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) { + DxeTime = Duration; + } else if (AsciiStrnCmp (Measurement.Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0) { + BdsTime = Duration; + } else if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) { + ShellTime = Duration; + } + } + + Total = 0; + + // print SEC phase duration time + // + if (SecTime > 0) { + ElapsedTime = DurationInMicroSeconds ( SecTime ); // Calculate elapsed time in microseconds + Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds + PrintToken (STRING_TOKEN (STR_DP_SEC_PHASE), ElapsedTime); + } + + // print PEI phase duration time + // + if (PeiTime > 0) { + ElapsedTime = DivU64x32 ( + PeiTime, + (UINT32)TimerInfo.Frequency + ); + Total += ElapsedTime; + PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_PEI, ElapsedTime); + } + + // print DXE phase duration time + // + if (DxeTime > 0) { + ElapsedTime = DivU64x32 ( + DxeTime, + (UINT32)TimerInfo.Frequency + ); + Total += ElapsedTime; + PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_DXE, ElapsedTime); + } + + // print BDS phase duration time + // + if (BdsTime > 0) { + ElapsedTime = DivU64x32 ( + BdsTime, + (UINT32)TimerInfo.Frequency + ); + Total += ElapsedTime; + PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_BDS, ElapsedTime); + } + + if (BdsTimeoutValue > 0) { + ElapsedTime = DivU64x32 ( + BdsTimeoutValue, + (UINT32)TimerInfo.Frequency + ); + PrintToken (STRING_TOKEN (STR_DP_PHASE_BDSTO), ALit_BdsTO, ElapsedTime); + } + + // print SHELL phase duration time + // + if (ShellTime > 0) { + ElapsedTime = DivU64x32 ( + ShellTime, + (UINT32)TimerInfo.Frequency + ); + Total += ElapsedTime; + PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_SHELL, ElapsedTime); + } + + PrintToken (STRING_TOKEN (STR_DP_TOTAL_DURATION), Total); +} + +/** Gather and print Handle data. + * + * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + * + * @return Status from a call to gBS->LocateHandle(). +**/ +EFI_STATUS +ProcessHandles( + IN BOOLEAN ExcludeFlag + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 ElapsedTime; + UINT64 Duration; + EFI_HANDLE *HandleBuffer; + EFI_STRING StringPtr; + UINTN Index; + UINTN LogEntryKey; + UINTN Count; + UINTN Size; + EFI_HANDLE TempHandle; + EFI_STATUS Status; + + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr); + + Size = 0; + HandleBuffer = NULL; + Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocatePool (Size); + ASSERT (HandleBuffer != NULL); + Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer); + } + if (EFI_ERROR (Status)) { + PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status); + } + else { +#if DP_DEBUG == 2 + Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0]))); +#endif + + PrintToken (STRING_TOKEN (STR_DP_HANDLE_GUID) ); + PrintToken (STRING_TOKEN (STR_DP_DASHES) ); + + LogEntryKey = 0; + Count = 0; + while ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp)) != 0) + { + Count++; + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + if ((ElapsedTime < mInterestThreshold) || + (Measurement.EndTimeStamp == 0) || + (Measurement.Handle == NULL) || + ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) + ) { // Ignore "uninteresting" or excluded records + continue; + } + mGaugeString[0] = 0; // Empty driver name by default + AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken); + // See if the Handle is in the HandleBuffer + for (Index = 0; Index < (Size / sizeof(HandleBuffer[0])); Index++) { + if (Measurement.Handle == HandleBuffer[Index]) { + GetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString + break; + } + } + // Ensure that the argument strings are not too long. + mGaugeString[31] = 0; + mUnicodeToken[18] = 0; + if (mGaugeString[0] != 0) { + // Display the record if it has a valid handle. + PrintToken ( + STRING_TOKEN (STR_DP_HANDLE_VARS), + Count, // 1 based, Which measurement record is being printed + Index + 1, // 1 based, Which handle is being printed + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + } + } + FreePool (HandleBuffer); + return Status; +} + +/** Gather and print PEIM data. + * + * Only prints complete PEIM records + * +**/ +VOID +ProcessPeims( + VOID +) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINT64 ElapsedTime; + EFI_STRING StringPtr; + UINTN LogEntryKey; + UINTN TIndex; + + + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr); + + PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION)); + PrintToken (STRING_TOKEN (STR_DP_DASHES)); + TIndex = 0; + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp)) != 0) + { + TIndex++; + if ((Measurement.EndTimeStamp == 0) || + (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) != 0) + ) { + continue; + } + + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); // Calculate elapsed time in microseconds + if (ElapsedTime >= mInterestThreshold) { + GetNameFromHandle (Measurement.Handle); // Name placed in mGaugeString + PrintToken (STRING_TOKEN (STR_DP_PEIM_STAT2), + TIndex, // 1 based, Which measurement record is being printed + Measurement.Handle, + mGaugeString, + ElapsedTime + ); + } + } +} + +/** Gather and print global data. + * + * Strips out incomplete or "Execution Phase" records + * Only prints records where Handle is NULL + * Increment TIndex for every record, even skipped ones, so that we have an + * indication of every measurement record taken. + * + * +**/ +VOID +ProcessGlobal( + VOID +) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINT64 ElapsedTime; + EFI_STRING StringPtr; + UINTN LogEntryKey; + UINTN Index; // Index, or number, of the measurement record being processed + + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr); + + PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION)); + PrintToken (STRING_TOKEN (STR_DP_DASHES)); + + Index = 1; + LogEntryKey = 0; + + while ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp)) != 0) + { + AsciiStrToUnicodeStr (Measurement.Module, mGaugeString); + AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken); + if ( ! ( IsPhase( &Measurement) || + (Measurement.Handle != NULL) || + (Measurement.EndTimeStamp == 0) + )) + { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + if (ElapsedTime >= mInterestThreshold) { + PrintToken ( + STRING_TOKEN (STR_DP_FOUR_VARS_2), + Index, + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + } + Index++; + } +} + +/** Gather and print cumulative data. + * + * Traverse the measurement records and:
+ * For each record with a Token listed in the CumData array:
+ * - Update the instance count and the total, minimum, and maximum durations. + * Finally, print the gathered cumulative statistics. + * +**/ +VOID +ProcessCumulative( + VOID +) +{ + UINT64 avgval; // the computed average duration + EFI_STRING StringPtr; + UINTN TIndex; + + + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr); + + PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1)); + PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2)); + PrintToken (STRING_TOKEN (STR_DP_DASHES)); + + for ( TIndex = 0; TIndex < NumCum; ++TIndex) { + avgval = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count); + PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS), + CumData[TIndex].Name, + CumData[TIndex].Count, + DurationInMicroSeconds(CumData[TIndex].Duration), + DurationInMicroSeconds(avgval), + DurationInMicroSeconds(CumData[TIndex].MinDur), + DurationInMicroSeconds(CumData[TIndex].MaxDur) + ); + } +} diff --git a/PerformancePkg/Dp_App/DpUtilities.c b/PerformancePkg/Dp_App/DpUtilities.c new file mode 100644 index 0000000000..7f88a40208 --- /dev/null +++ b/PerformancePkg/Dp_App/DpUtilities.c @@ -0,0 +1,317 @@ +/** @file + * Utility functions used by the Dp application. + * + * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +/** Calculate an event's duration in timer ticks. + * + * Given the count direction and the event's start and end timer values, + * calculate the duration of the event in timer ticks. Information for + * the current measurement is pointed to by the parameter. + * + * If the measurement's start time is 1, it indicates that the developer + * is indicating that the measurement began at the release of reset. + * The start time is adjusted to the timer's starting count before performing + * the elapsed time calculation. + * + * The calculated duration, in ticks, is the absolute difference between + * the measurement's ending and starting counts. + * + * @pre The global TimerInfo structure must have already been initialized + * before this function is called. + * + * @param[in,out] Measurement Pointer to a MEASUREMENT_RECORD structure containing + * data for the current measurement. + * + * @return The 64-bit duration of the event. +**/ +UINT64 +GetDuration ( + IN OUT MEASUREMENT_RECORD *Measurement + ) +{ + UINT64 Duration; + BOOLEAN Error; + + // PERF_START macros are called with a value of 1 to indicate + // the beginning of time. So, adjust the start ticker value + // to the real beginning of time. + // Assumes no wraparound. Even then, there is a very low probability + // of having a valid StartTicker value of 1. + if (Measurement->StartTimeStamp == 1) { + Measurement->StartTimeStamp = TimerInfo.StartCount; + } + if (TimerInfo.CountUp) { + Duration = Measurement->EndTimeStamp - Measurement->StartTimeStamp; + Error = (BOOLEAN)(Duration > Measurement->EndTimeStamp); + } + else { + Duration = Measurement->StartTimeStamp - Measurement->EndTimeStamp; + Error = (BOOLEAN)(Duration > Measurement->StartTimeStamp); + } + + if (Error) { + DEBUG ((EFI_D_ERROR, ALit_TimerLibError)); + Duration = 0; + } + return Duration; +} + +/** Determine whether the Measurement record is for an EFI Phase. + * + * The Token and Module members of the measurement record are checked. + * Module must be empty and Token must be one of SEC, PEI, DXE, BDS, or SHELL. + * + * @param[in] Measurement A pointer to the Measurement record to test. + * + * @retval TRUE The measurement record is for an EFI Phase. + * @retval FALSE The measurement record is NOT for an EFI Phase. +**/ +BOOLEAN +IsPhase( + IN MEASUREMENT_RECORD *Measurement + ) +{ + BOOLEAN RetVal; + + RetVal = (BOOLEAN)( ( *Measurement->Module == '\0') && + ((AsciiStrnCmp (Measurement->Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) || + (AsciiStrnCmp (Measurement->Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) || + (AsciiStrnCmp (Measurement->Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) || + (AsciiStrnCmp (Measurement->Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0)) + ); + return RetVal; +} + +/** Get the file name portion of the Pdb File Name. + * + * The portion of the Pdb File Name between the last backslash and + * either a following period or the end of the string is converted + * to Unicode and copied into UnicodeBuffer. The name is truncated, + * if necessary, to ensure that UnicodeBuffer is not overrun. + * + * @param[in] PdbFileName Pdb file name. + * @param[out] UnicodeBuffer The resultant Unicode File Name. + * +**/ +VOID +GetShortPdbFileName ( + IN CHAR8 *PdbFileName, + OUT CHAR16 *UnicodeBuffer + ) +{ + UINTN IndexA; // Current work location within an ASCII string. + UINTN IndexU; // Current work location within a Unicode string. + UINTN StartIndex; + UINTN EndIndex; + + ZeroMem (UnicodeBuffer, DXE_PERFORMANCE_STRING_LENGTH * sizeof (CHAR16)); + + if (PdbFileName == NULL) { + StrCpy (UnicodeBuffer, L" "); + } else { + StartIndex = 0; + for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++) + ; + for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) { + if (PdbFileName[IndexA] == '\\') { + StartIndex = IndexA + 1; + } + + if (PdbFileName[IndexA] == '.') { + EndIndex = IndexA; + } + } + + IndexU = 0; + for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) { + UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA]; + IndexU++; + if (IndexU >= DXE_PERFORMANCE_STRING_LENGTH) { + UnicodeBuffer[DXE_PERFORMANCE_STRING_LENGTH] = 0; + break; + } + } + } +} + +/** Get a human readable name for an image handle. + * + * @param[in] Handle + * + * @post The resulting Unicode name string is stored in the + * mGaugeString global array. + * +**/ +VOID +GetNameFromHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *Image; + CHAR8 *PdbFileName; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + EFI_STRING StringPtr; + + // Proactively get the error message so it will be ready if needed + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_ERROR_NAME), NULL); + ASSERT (StringPtr != NULL); + + // Get handle name from image protocol + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiLoadedImageProtocolGuid, + &Image + ); + + if (EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + StrCpy (mGaugeString, StringPtr); + return ; + } + + // Get handle name from image protocol + // + Status = gBS->HandleProtocol ( + DriverBinding->ImageHandle, + &gEfiLoadedImageProtocolGuid, + &Image + ); + } + + PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase); + + if (PdbFileName != NULL) { + GetShortPdbFileName (PdbFileName, mGaugeString); + } else { + StrCpy (mGaugeString, StringPtr); + } + return ; +} + +/** Calculate the Duration in microseconds. + * + * Duration is multiplied by 1000, instead of Frequency being divided by 1000 or + * multiplying the result by 1000, in order to maintain precision. Since Duration is + * a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow. + * + * The time is calculated as (Duration * 1000) / Timer_Frequency. + * + * @param[in] Duration The event duration in timer ticks. + * + * @return A 64-bit value which is the Elapsed time in microseconds. +**/ +UINT64 +DurationInMicroSeconds ( + IN UINT64 Duration + ) +{ + UINT64 Temp; + + Temp = MultU64x32 (Duration, 1000); + return DivU64x32 (Temp, TimerInfo.Frequency); +} + +/** Formatted Print using a Hii Token to reference the localized format string. + * + * @param[in] Token A HII token associated with a localized Unicode string. + * + * @return The number of characters converted by UnicodeVSPrint(). + * +**/ +UINTN +PrintToken ( + IN UINT16 Token, + ... + ) +{ + VA_LIST Marker; + EFI_STRING StringPtr; + UINTN Return; + UINTN BufferSize; + + StringPtr = HiiGetString (gHiiHandle, Token, NULL); + ASSERT (StringPtr != NULL); + + VA_START (Marker, Token); + + BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16); + + if (mPrintTokenBuffer == NULL) { + mPrintTokenBuffer = AllocatePool (BufferSize); + ASSERT (mPrintTokenBuffer != NULL); + } + SetMem( mPrintTokenBuffer, BufferSize, 0); + + Return = UnicodeVSPrint (mPrintTokenBuffer, BufferSize, StringPtr, Marker); + if (Return > 0 && gST->ConOut != NULL) { + gST->ConOut->OutputString (gST->ConOut, mPrintTokenBuffer); + } + return Return; +} + +/** Get index of Measurement Record's match in the CumData array. + * + * If the Measurement's Token value matches a Token in one of the CumData + * records, the index of the matching record is returned. The returned + * index is a signed value so that negative values can indicate that + * the Measurement didn't match any entry in the CumData array. + * + * @param[in] Measurement A pointer to a Measurement Record to match against the CumData array. + * + * @retval <0 Token is not in the CumData array. + * @retval >=0 Return value is the index into CumData where Token is found. +**/ +INTN +GetCumulativeItem( + IN MEASUREMENT_RECORD *Measurement + ) +{ + INTN Index; + + for( Index = 0; Index < (INTN)NumCum; ++Index) { + if (AsciiStrnCmp (Measurement->Token, CumData[Index].Name, PERF_TOKEN_LENGTH) == 0) { + return Index; // Exit, we found a match + } + } + // If the for loop exits, Token was not found. + return -1; // Indicate failure +} diff --git a/PerformancePkg/Dp_App/Literals.c b/PerformancePkg/Dp_App/Literals.c new file mode 100644 index 0000000000..efc7d1f355 --- /dev/null +++ b/PerformancePkg/Dp_App/Literals.c @@ -0,0 +1,46 @@ +/** @file + * Definitions of ASCII string literals used by DP. + * + * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ +#include + +// ASCII String literals which probably don't need translation +CHAR8 const ALit_TimerLibError[] = "Timer library instance error!\n"; +CHAR8 const ALit_SEC[] = SEC_TOK; +CHAR8 const ALit_DXE[] = DXE_TOK; +CHAR8 const ALit_SHELL[] = SHELL_TOK; +CHAR8 const ALit_PEI[] = PEI_TOK; +CHAR8 const ALit_BDS[] = BDS_TOK; +CHAR8 const ALit_BdsTO[] = "BdsTimeOut"; +CHAR8 const ALit_PEIM[] = "PEIM"; + +/// UNICODE String literals which should probably be translated +CHAR16 STR_DP_OPTION_UA[] = L"-A"; +CHAR16 STR_DP_OPTION_LA[] = L"-a"; +CHAR16 STR_DP_OPTION_LN[] = L"-n"; +CHAR16 STR_DP_OPTION_LT[] = L"-t"; +CHAR16 STR_DP_OPTION_UP[] = L"-P"; +CHAR16 STR_DP_OPTION_UR[] = L"-R"; +CHAR16 STR_DP_OPTION_LS[] = L"-s"; +CHAR16 STR_DP_OPTION_US[] = L"-S"; +CHAR16 STR_DP_OPTION_UT[] = L"-T"; +CHAR16 STR_DP_OPTION_LV[] = L"-v"; +CHAR16 STR_DP_OPTION_QH[] = L"-?"; +CHAR16 STR_DP_OPTION_LH[] = L"-h"; +CHAR16 STR_DP_OPTION_UH[] = L"-H"; +CHAR16 STR_DP_OPTION_LX[] = L"-x"; + +CHAR16 const ALit_UNKNOWN[] = L"Unknown"; +CHAR16 const STR_DP_INCOMPLETE[] = L" I "; +CHAR16 const STR_DP_COMPLETE[] = L" "; + +CHAR8 const ALit_TRUE[] = "TRUE"; +CHAR8 const ALit_FALSE[] = "FALSE"; diff --git a/PerformancePkg/Dp_App/Literals.h b/PerformancePkg/Dp_App/Literals.h new file mode 100644 index 0000000000..d50dd7074f --- /dev/null +++ b/PerformancePkg/Dp_App/Literals.h @@ -0,0 +1,49 @@ +/** @file + * Declarations of ASCII string literals used by DP. + * + * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ +#ifndef _LITERALS_H_ +#define _LITERALS_H_ + +// ASCII String literals which probably don't need translation +extern CHAR8 const ALit_TimerLibError[]; +extern CHAR8 const ALit_SEC[]; +extern CHAR8 const ALit_DXE[]; +extern CHAR8 const ALit_SHELL[]; +extern CHAR8 const ALit_PEI[]; +extern CHAR8 const ALit_BDS[]; +extern CHAR8 const ALit_BdsTO[]; +extern CHAR8 const ALit_PEIM[]; + +/// UNICODE String literals which should probably be translated +extern CHAR16 STR_DP_OPTION_UA[]; +extern CHAR16 STR_DP_OPTION_LA[]; +extern CHAR16 STR_DP_OPTION_LN[]; +extern CHAR16 STR_DP_OPTION_LT[]; +extern CHAR16 STR_DP_OPTION_UP[]; +extern CHAR16 STR_DP_OPTION_UR[]; +extern CHAR16 STR_DP_OPTION_LS[]; +extern CHAR16 STR_DP_OPTION_US[]; +extern CHAR16 STR_DP_OPTION_UT[]; +extern CHAR16 STR_DP_OPTION_LV[]; +extern CHAR16 STR_DP_OPTION_QH[]; +extern CHAR16 STR_DP_OPTION_LH[]; +extern CHAR16 STR_DP_OPTION_UH[]; +extern CHAR16 STR_DP_OPTION_LX[]; + +extern CHAR16 const ALit_UNKNOWN[]; +extern CHAR16 const STR_DP_INCOMPLETE[]; +extern CHAR16 const STR_DP_COMPLETE[]; + +extern CHAR8 const ALit_TRUE[]; +extern CHAR8 const ALit_FALSE[]; + +#endif // _LITERALS_H_ diff --git a/PerformancePkg/Include/Ich/GenericIch.h b/PerformancePkg/Include/Ich/GenericIch.h new file mode 100644 index 0000000000..67af774f40 --- /dev/null +++ b/PerformancePkg/Include/Ich/GenericIch.h @@ -0,0 +1,54 @@ +/** @file + Generic definitions for registers in the Intel Ich devices. + + These definitions should work for any version of Ich. + + Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _GENERIC_ICH_H_ +#define _GENERIC_ICH_H_ + +/** @defgroup GenericIchDefs Generic ICH Definitions. + +Definitions beginning with "R_" are registers. +Definitions beginning with "B_" are bits within registers. +Definitions beginning with "V_" are meaningful values of bits within the registers. +**/ +///@{ + +/// @defgroup IchPciAddressing PCI Bus Address for ICH. +///@{ +#define PCI_BUS_NUMBER_ICH 0x00 ///< ICH is on PCI Bus 0. +#define PCI_DEVICE_NUMBER_ICH_LPC 31 ///< ICH is Device 31. +#define PCI_FUNCTION_NUMBER_ICH_LPC 0 ///< ICH is Function 0. +///@} + +/// @defgroup IchAcpiCntr Control for the ICH's ACPI Counter. +///@{ +#define R_ICH_LPC_ACPI_BASE 0x40 +#define R_ICH_LPC_ACPI_CNT 0x44 +#define B_ICH_LPC_ACPI_CNT_ACPI_EN 0x80 +///@} + +/// @defgroup IchAcpiTimer The ICH's ACPI Timer. +///@{ +#define R_ACPI_PM1_TMR 0x08 +#define V_ACPI_TMR_FREQUENCY 3579545 +#define V_ACPI_PM1_TMR_MAX_VAL 0x1000000 ///< The timer is 24 bit overflow. +///@} + +/// Macro to generate the PCI address of any given ICH Register. +#define PCI_ICH_LPC_ADDRESS(Register) \ + ((UINTN)(PCI_LIB_ADDRESS (PCI_BUS_NUMBER_ICH, PCI_DEVICE_NUMBER_ICH_LPC, PCI_FUNCTION_NUMBER_ICH_LPC, Register))) + +///@} +#endif // _GENERIC_ICH_H_ diff --git a/PerformancePkg/Include/PerformanceTokens.h b/PerformancePkg/Include/PerformanceTokens.h new file mode 100644 index 0000000000..8a69415a30 --- /dev/null +++ b/PerformancePkg/Include/PerformanceTokens.h @@ -0,0 +1,28 @@ +/** @file + ASCII String Literals with special meaning to Performance measurement and the Dp utility. + +Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PERFORMANCE_TOKENS_H__ +#define __PERFORMANCE_TOKENS_H__ + +#define SEC_TOK "SEC" ///< SEC Phase +#define DXE_TOK "DXE" ///< DEC Phase +#define SHELL_TOK "SHELL" ///< Shell Phase +#define PEI_TOK "PEI" ///< PEI Phase +#define BDS_TOK "BDS" ///< BDS Phase +#define DRIVERBINDING_START_TOK "DB:Start:" ///< Driver Binding Start() function call +#define DRIVERBINDING_SUPPORT_TOK "DB:Support:" ///< Driver Binding Support() function call +#define LOAD_IMAGE_TOK "LoadImage:" ///< Load a dispatched module +#define START_IMAGE_TOK "StartImage:" ///< Dispatched Modules Entry Point execution + +#endif // __PERFORMANCE_TOKENS_H__ diff --git a/PerformancePkg/Library/TscTimerLib/TscTimerLib.c b/PerformancePkg/Library/TscTimerLib/TscTimerLib.c new file mode 100644 index 0000000000..19151a4e9b --- /dev/null +++ b/PerformancePkg/Library/TscTimerLib/TscTimerLib.c @@ -0,0 +1,243 @@ +/** @file + A Timer Library implementation which uses the Time Stamp Counter in the processor. + + For Pentium 4 processors, Intel Xeon processors (family [0FH], models [03H and higher]); + for Intel Core Solo and Intel Core Duo processors (family [06H], model [0EH]); + for the Intel Xeon processor 5100 series and Intel Core 2 Duo processors (family [06H], model [0FH]); + for Intel Core 2 and Intel Xeon processors (family [06H], display_model [17H]); + for Intel Atom processors (family [06H], display_model [1CH]): + the time-stamp counter increments at a constant rate. + That rate may be set by the maximum core-clock to bus-clock ratio of the processor or may be set by + the maximum resolved frequency at which the processor is booted. The maximum resolved frequency may + differ from the maximum qualified frequency of the processor. + + The specific processor configuration determines the behavior. Constant TSC behavior ensures that the + duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if + the processor core changes frequency. This is the architectural behavior moving forward. + + A Processor’s support for invariant TSC is indicated by CPUID.0x80000007.EDX[8]. + + Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +#include +#include +#include +#include +#include + +STATIC UINT64 mTscFrequency; + +#ifndef R_ICH_ACPI_PM1_TMR +#define R_ICH_ACPI_PM1_TMR R_ACPI_PM1_TMR +#endif + +/** The constructor function determines the actual TSC frequency. + + The TSC counting frequency is determined by comparing how far it counts + during a 1ms period as determined by the ACPI timer. The ACPI timer is + used because it counts at a known frequency. + If ACPI I/O space not enabled, this function will enable it. Then the + TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms. + The TSC is then sampled again. The difference multiplied by 1000 is the TSC + frequency. There will be a small error because of the overhead of reading + the ACPI timer. An attempt is made to determine and compensate for this error. + This function will always return RETURN_SUCCESS. + + @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +TscTimerLibConstructor ( + VOID + ) +{ + UINT64 StartTSC; + UINT64 EndTSC; + UINT32 TimerAddr; + UINT32 Ticks; + + // + // If ACPI I/O space is not enabled yet, program ACPI I/O base address and enable it. + // + if ((PciRead8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT)) & B_ICH_LPC_ACPI_CNT_ACPI_EN) == 0) { + PciWrite16 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_BASE), PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress)); + PciOr8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT), B_ICH_LPC_ACPI_CNT_ACPI_EN); + } + + TimerAddr = PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress) + R_ACPI_PM1_TMR; // Locate the ACPI Timer + Ticks = IoRead32( TimerAddr) + (3579); // Set Ticks to 1ms in the future + StartTSC = AsmReadTsc(); // Get base value for the TSC + // + // Wait until the ACPI timer has counted 1ms. + // Timer wrap-arounds are handled correctly by this function. + // When the current ACPI timer value is greater than 'Ticks', the while loop will exit. + // + while (((Ticks - IoRead32( TimerAddr)) & BIT23) == 0) { + CpuPause(); + } + EndTSC = AsmReadTsc(); // TSC value 1ms later + + mTscFrequency = MultU64x32 ( + (EndTSC - StartTSC), // Number of TSC counts in 1ms + 1000 // Number of ms in a second + ); + // + // mTscFrequency is now equal to the number of TSC counts per second + // + return RETURN_SUCCESS; +} + +/** Stalls the CPU for at least the given number of ticks. + + Stalls the CPU for at least the given number of ticks. It's invoked by + MicroSecondDelay() and NanoSecondDelay(). + + @param[in] Delay A period of time to delay in ticks. + +**/ +STATIC +VOID +InternalX86Delay ( + IN UINT64 Delay + ) +{ + UINT64 Ticks; + + // + // The target timer count is calculated here + // + Ticks = AsmReadTsc() + Delay; + + // + // Wait until time out + // Timer wrap-arounds are NOT handled correctly by this function. + // Thus, this function must be called within 10 years of reset since + // Intel guarantees a minimum of 10 years before the TSC wraps. + // + while (AsmReadTsc() <= Ticks) CpuPause(); +} + +/** Stalls the CPU for at least the specified number of MicroSeconds. + + @param[in] MicroSeconds The minimum number of microseconds to delay. + + @return The value of MicroSeconds input. + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + InternalX86Delay ( + DivU64x32 ( + MultU64x64 ( + mTscFrequency, + MicroSeconds + ), + 1000000u + ) + ); + return MicroSeconds; +} + +/** Stalls the CPU for at least the specified number of NanoSeconds. + + @param[in] NanoSeconds The minimum number of nanoseconds to delay. + + @return The value of NanoSeconds input. + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + InternalX86Delay ( + DivU64x32 ( + MultU64x32 ( + mTscFrequency, + (UINT32)NanoSeconds + ), + 1000000000u + ) + ); + return NanoSeconds; +} + +/** Retrieves the current value of the 64-bit free running Time-Stamp counter. + + The time-stamp counter (as implemented in the P6 family, Pentium, Pentium M, + Pentium 4, Intel Xeon, Intel Core Solo and Intel Core Duo processors and + later processors) is a 64-bit counter that is set to 0 following a RESET of + the processor. Following a RESET, the counter increments even when the + processor is halted by the HLT instruction or the external STPCLK# pin. Note + that the assertion of the external DPSLP# pin may cause the time-stamp + counter to stop. + + The properties of the counter can be retrieved by the + GetPerformanceCounterProperties() function. + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return AsmReadTsc(); +} + +/** Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with, 0x0, is returned in StartValue. If EndValue is not NULL, then the value + that the performance counter end with, 0xFFFFFFFFFFFFFFFF, is returned in + EndValue. + + The 64-bit frequency of the performance counter, in Hz, is always returned. + To determine average processor clock frequency, Intel recommends the use of + EMON logic to count processor core clocks over the period of time for which + the average is required. + + + @param[out] StartValue Pointer to where the performance counter's starting value is saved, or NULL. + @param[out] EndValue Pointer to where the performance counter's ending value is saved, or NULL. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + if (StartValue != NULL) { + *StartValue = 0; + } + if (EndValue != NULL) { + *EndValue = 0xFFFFFFFFFFFFFFFFull; + } + + return mTscFrequency; +} diff --git a/PerformancePkg/Library/TscTimerLib/TscTimerLib.inf b/PerformancePkg/Library/TscTimerLib/TscTimerLib.inf new file mode 100644 index 0000000000..3f9aebfdcb --- /dev/null +++ b/PerformancePkg/Library/TscTimerLib/TscTimerLib.inf @@ -0,0 +1,52 @@ +#/** @file +# Timer Library which uses the Time Stamp Counter in the processor. +# +# A version of the Timer Library using the processor's TSC. +# The time stamp counter in newer processors may support an enhancement, referred to as invariant TSC. +# The invariant TSC runs at a constant rate in all ACPI P-, C-. and T-states. +# This is the architectural behavior moving forward. +# TSC reads are much more efficient and do not incur the overhead associated with a ring transition or +# access to a platform resource. +# +# Copyright (c) 2009-2010, Intel Corporation. All rights reserved. +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TscTimerLib + FILE_GUID = 95ab030f-b4fd-4ee4-92a5-9e04e87634d9 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + + CONSTRUCTOR = TscTimerLibConstructor + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + TscTimerLib.c + + +[Packages] + MdePkg/MdePkg.dec + PerformancePkg/PerformancePkg.dec + + +[LibraryClasses] + PcdLib + PciLib + IoLib + BaseLib + +[Pcd.common] + gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress diff --git a/PerformancePkg/PerformancePkg.dec b/PerformancePkg/PerformancePkg.dec new file mode 100644 index 0000000000..b2bb19f752 --- /dev/null +++ b/PerformancePkg/PerformancePkg.dec @@ -0,0 +1,34 @@ +#/** @file +# Build description file to generate Shell DP application and +# Performance Libraries. +# +# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# **/ + +[Defines] + PACKAGE_NAME = PerformancePkg + PACKAGE_GUID = ce898697-b945-46e2-a26e-5752af565185 + PACKAGE_VERSION = 0.1 + DEC_SPECIFICATION = 0x00010005 + +[Includes.common] + Include + +[Guids.common] + ## Performance Package token space guid + # Include/Guid/PerformancePkgTokenSpace.h + # 669346ef-fdad-4aeb-a608-7def3f2d4621 + gPerformancePkgTokenSpaceGuid = { 0x669346ef, 0xFDad, 0x4aeb, { 0x08, 0xa6, 0x21, 0x46, 0x2d, 0x3f, 0xef, 0x7d }} + +[PcdsFixedAtBuild.common] + ## The base address of the ACPI registers within the ICH PCI space. + # This space must be 128-byte aligned. + gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress|0x400|UINT16|1 diff --git a/PerformancePkg/PerformancePkg.dsc b/PerformancePkg/PerformancePkg.dsc new file mode 100644 index 0000000000..026803ab14 --- /dev/null +++ b/PerformancePkg/PerformancePkg.dsc @@ -0,0 +1,68 @@ +#/** @file +# Build description file to generate Shell DP application. +# +# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# **/ + +[Defines] + DSC_SPECIFICATION = 0x00010005 + PLATFORM_NAME = PerformancePkg + PLATFORM_GUID = 9ffd7bf2-231e-4525-9a42-480545dafd17 + PLATFORM_VERSION = 0.1 + OUTPUT_DIRECTORY = Build/PerformancePkg + SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + +[LibraryClasses] + # + # Entry Point Libraries + # + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + # + # Common Libraries + # + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + FileHandleLib|ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf + + # This library instance mapping needs adjusting based on platform. + # The TimerLib instance must match the TimerLib the platform was built with. + # If the platform was built with more than one TimerLib type, then this utility + # will produce invalid results for any measurements done with a TimerLib instance + # that is different than the one below. + # + # TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf + TimerLib|PerformancePkg/Library/TscTimerLib/TscTimerLib.inf + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + +[LibraryClasses.IPF] + PalLib|MdePkg/Library/UefiPalLib/UefiPalLib.inf + +[Components] + PerformancePkg/Library/TscTimerLib/TscTimerLib.inf + PerformancePkg/Dp_App/Dp.inf -- 2.39.2