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
This commit is contained in:
darylm503 2010-04-23 17:00:32 +00:00
parent c3f13d41ab
commit c06ad33ed2
16 changed files with 2452 additions and 0 deletions

339
PerformancePkg/Dp_App/Dp.c Normal file
View File

@ -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.<BR>
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* 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 <Library/UefiApplicationEntryPoint.h>
#include <Library/ShellLib.h>
#include <Library/BaseLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/TimerLib.h>
#include <Library/UefiLib.h>
#include <Library/HiiLib.h>
#include <Library/PcdLib.h>
#include <Guid/Performance.h>
#include <PerformanceTokens.h>
#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;
}

View File

@ -0,0 +1,94 @@
/** @file
* Common declarations for the Dp Performance Reporting Utility.
*
* Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* 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_

View File

@ -0,0 +1,66 @@
#/** @file
# Display Performance Application, Module information file.
#
# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# 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

View File

@ -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.<BR>
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* 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
);

View File

@ -0,0 +1,92 @@
/** @file
* Measured Profiling reporting for the Dp utility.
*
* Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* 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 <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/TimerLib.h>
#include <Library/PeCoffGetEntryPointLib.h>
#include <Library/PerformanceLib.h>
#include <Library/PrintLib.h>
#include <Library/HiiLib.h>
#include <Library/PcdLib.h>
#include <Guid/Performance.h>
#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;
}

Binary file not shown.

View File

@ -0,0 +1,681 @@
/** @file
* Trace reporting for the Dp utility.
*
* Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* 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 <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/TimerLib.h>
#include <Library/PeCoffGetEntryPointLib.h>
#include <Library/PerformanceLib.h>
#include <Library/PrintLib.h>
#include <Library/HiiLib.h>
#include <Library/PcdLib.h>
#include <Guid/Performance.h>
#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.<BR>
* 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:<BR>
* For each record with a Token listed in the CumData array:<BR>
* - 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)
);
}
}

View File

@ -0,0 +1,317 @@
/** @file
* Utility functions used by the Dp application.
*
* Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* 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 <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/TimerLib.h>
#include <Library/PeCoffGetEntryPointLib.h>
#include <Library/PrintLib.h>
#include <Library/HiiLib.h>
#include <Library/PcdLib.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/Driverbinding.h>
#include <Guid/Performance.h>
#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
}

View File

@ -0,0 +1,46 @@
/** @file
* Definitions of ASCII string literals used by DP.
*
* Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* 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 <PerformanceTokens.h>
// 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";

View File

@ -0,0 +1,49 @@
/** @file
* Declarations of ASCII string literals used by DP.
*
* Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* 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_

View File

@ -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.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
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_

View File

@ -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.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
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__

View File

@ -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 Processors support for invariant TSC is indicated by CPUID.0x80000007.EDX[8].
Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
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 <Base.h>
#include <Ich/GenericIch.h>
#include <Library/TimerLib.h>
#include <Library/BaseLib.h>
#include <Library/IoLib.h>
#include <Library/PciLib.h>
#include <Library/PcdLib.h>
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;
}

View File

@ -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

View File

@ -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.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# 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

View File

@ -0,0 +1,68 @@
#/** @file
# Build description file to generate Shell DP application.
#
# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# 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