From 51e4dfbde92eae40b71e23477cd54c9fe9fea9bc Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 27 Apr 2017 11:19:11 +0800 Subject: PerformancePkg: Move to new location Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- Core/PerformancePkg/Contributions.txt | 218 +++++ Core/PerformancePkg/Dp_App/Dp.c | 559 +++++++++++++ Core/PerformancePkg/Dp_App/Dp.h | 101 +++ Core/PerformancePkg/Dp_App/Dp.inf | 80 ++ Core/PerformancePkg/Dp_App/DpInternal.h | 383 +++++++++ Core/PerformancePkg/Dp_App/DpProfile.c | 102 +++ Core/PerformancePkg/Dp_App/DpStrings.uni | 281 +++++++ Core/PerformancePkg/Dp_App/DpTrace.c | 879 +++++++++++++++++++++ Core/PerformancePkg/Dp_App/DpUtilities.c | 489 ++++++++++++ Core/PerformancePkg/Dp_App/Literals.c | 22 + Core/PerformancePkg/Dp_App/Literals.h | 26 + .../Include/Guid/PerformancePkgTokenSpace.h | 25 + Core/PerformancePkg/Include/Guid/TscFrequency.h | 25 + Core/PerformancePkg/Include/Ich/GenericIch.h | 55 ++ Core/PerformancePkg/Include/PerformanceTokens.h | 28 + .../Library/TscTimerLib/BaseTscTimerLib.c | 45 ++ .../Library/TscTimerLib/BaseTscTimerLib.inf | 59 ++ .../Library/TscTimerLib/DxeTscTimerLib.c | 102 +++ .../Library/TscTimerLib/DxeTscTimerLib.inf | 64 ++ .../Library/TscTimerLib/PeiTscTimerLib.c | 76 ++ .../Library/TscTimerLib/PeiTscTimerLib.inf | 60 ++ .../Library/TscTimerLib/TscTimerLibInternal.h | 55 ++ .../Library/TscTimerLib/TscTimerLibShare.c | 275 +++++++ Core/PerformancePkg/License.txt | 25 + Core/PerformancePkg/PerformancePkg.dec | 37 + Core/PerformancePkg/PerformancePkg.dsc | 68 ++ 26 files changed, 4139 insertions(+) create mode 100644 Core/PerformancePkg/Contributions.txt create mode 100644 Core/PerformancePkg/Dp_App/Dp.c create mode 100644 Core/PerformancePkg/Dp_App/Dp.h create mode 100644 Core/PerformancePkg/Dp_App/Dp.inf create mode 100644 Core/PerformancePkg/Dp_App/DpInternal.h create mode 100644 Core/PerformancePkg/Dp_App/DpProfile.c create mode 100644 Core/PerformancePkg/Dp_App/DpStrings.uni create mode 100644 Core/PerformancePkg/Dp_App/DpTrace.c create mode 100644 Core/PerformancePkg/Dp_App/DpUtilities.c create mode 100644 Core/PerformancePkg/Dp_App/Literals.c create mode 100644 Core/PerformancePkg/Dp_App/Literals.h create mode 100644 Core/PerformancePkg/Include/Guid/PerformancePkgTokenSpace.h create mode 100644 Core/PerformancePkg/Include/Guid/TscFrequency.h create mode 100644 Core/PerformancePkg/Include/Ich/GenericIch.h create mode 100644 Core/PerformancePkg/Include/PerformanceTokens.h create mode 100644 Core/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.c create mode 100644 Core/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.inf create mode 100644 Core/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.c create mode 100644 Core/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf create mode 100644 Core/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.c create mode 100644 Core/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf create mode 100644 Core/PerformancePkg/Library/TscTimerLib/TscTimerLibInternal.h create mode 100644 Core/PerformancePkg/Library/TscTimerLib/TscTimerLibShare.c create mode 100644 Core/PerformancePkg/License.txt create mode 100644 Core/PerformancePkg/PerformancePkg.dec create mode 100644 Core/PerformancePkg/PerformancePkg.dsc (limited to 'Core') diff --git a/Core/PerformancePkg/Contributions.txt b/Core/PerformancePkg/Contributions.txt new file mode 100644 index 0000000000..f87cbd73c6 --- /dev/null +++ b/Core/PerformancePkg/Contributions.txt @@ -0,0 +1,218 @@ + +====================== += Code Contributions = +====================== + +To make a contribution to a TianoCore project, follow these steps. +1. Create a change description in the format specified below to + use in the source control commit log. +2. Your commit message must include your "Signed-off-by" signature, + and "Contributed-under" message. +3. Your "Contributed-under" message explicitly states that the + contribution is made under the terms of the specified + contribution agreement. Your "Contributed-under" message + must include the name of contribution agreement and version. + For example: Contributed-under: TianoCore Contribution Agreement 1.0 + The "TianoCore Contribution Agreement" is included below in + this document. +4. Submit your code to the TianoCore project using the process + that the project documents on its web page. If the process is + not documented, then submit the code on development email list + for the project. +5. It is preferred that contributions are submitted using the same + copyright license as the base project. When that is not possible, + then contributions using the following licenses can be accepted: + * BSD (2-clause): http://opensource.org/licenses/BSD-2-Clause + * BSD (3-clause): http://opensource.org/licenses/BSD-3-Clause + * MIT: http://opensource.org/licenses/MIT + * Python-2.0: http://opensource.org/licenses/Python-2.0 + * Zlib: http://opensource.org/licenses/Zlib + + Contributions of code put into the public domain can also be + accepted. + + Contributions using other licenses might be accepted, but further + review will be required. + +===================================================== += Change Description / Commit Message / Patch Email = +===================================================== + +Your change description should use the standard format for a +commit message, and must include your "Signed-off-by" signature +and the "Contributed-under" message. + +== Sample Change Description / Commit Message = + +=== Start of sample patch email message === + +From: Contributor Name +Subject: [PATCH] CodeModule: Brief-single-line-summary + +Full-commit-message + +Contributed-under: TianoCore Contribution Agreement 1.0 +Signed-off-by: Contributor Name +--- + +An extra message for the patch email which will not be considered part +of the commit message can be added here. + +Patch content inline or attached + +=== End of sample patch email message === + +=== Notes for sample patch email === + +* The first line of commit message is taken from the email's subject + line following [PATCH]. The remaining portion of the commit message + is the email's content until the '---' line. +* git format-patch is one way to create this format + +=== Definitions for sample patch email === + +* "CodeModule" is a short idenfier for the affected code. For + example MdePkg, or MdeModulePkg UsbBusDxe. +* "Brief-single-line-summary" is a short summary of the change. +* The entire first line should be less than ~70 characters. +* "Full-commit-message" a verbose multiple line comment describing + the change. Each line should be less than ~70 characters. +* "Contributed-under" explicitely states that the contribution is + made under the terms of the contribtion agreement. This + agreement is included below in this document. +* "Signed-off-by" is the contributor's signature identifying them + by their real/legal name and their email address. + +======================================== += TianoCore Contribution Agreement 1.0 = +======================================== + +INTEL CORPORATION ("INTEL") MAKES AVAILABLE SOFTWARE, DOCUMENTATION, +INFORMATION AND/OR OTHER MATERIALS FOR USE IN THE TIANOCORE OPEN SOURCE +PROJECT (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE +TERMS AND CONDITIONS OF THIS AGREEMENT BETWEEN YOU AND INTEL AND/OR THE +TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR +REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE +CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS +OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED +BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS +AGREEMENT AND THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE +AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT +USE THE CONTENT. + +Unless otherwise indicated, all Content made available on the TianoCore +site is provided to you under the terms and conditions of the BSD +License ("BSD"). A copy of the BSD License is available at +http://opensource.org/licenses/bsd-license.php +or when applicable, in the associated License.txt file. + +Certain other content may be made available under other licenses as +indicated in or with such Content. (For example, in a License.txt file.) + +You accept and agree to the following terms and conditions for Your +present and future Contributions submitted to TianoCore site. Except +for the license granted to Intel hereunder, You reserve all right, +title, and interest in and to Your Contributions. + +== SECTION 1: Definitions == +* "You" or "Contributor" shall mean the copyright owner or legal + entity authorized by the copyright owner that is making a + Contribution hereunder. All other entities that control, are + controlled by, or are under common control with that entity are + considered to be a single Contributor. For the purposes of this + definition, "control" means (i) the power, direct or indirect, to + cause the direction or management of such entity, whether by + contract or otherwise, or (ii) ownership of fifty percent (50%) + or more of the outstanding shares, or (iii) beneficial ownership + of such entity. +* "Contribution" shall mean any original work of authorship, + including any modifications or additions to an existing work, + that is intentionally submitted by You to the TinaoCore site for + inclusion in, or documentation of, any of the Content. For the + purposes of this definition, "submitted" means any form of + electronic, verbal, or written communication sent to the + TianoCore site or its representatives, including but not limited + to communication on electronic mailing lists, source code + control systems, and issue tracking systems that are managed by, + or on behalf of, the TianoCore site for the purpose of + discussing and improving the Content, but excluding + communication that is conspicuously marked or otherwise + designated in writing by You as "Not a Contribution." + +== SECTION 2: License for Contributions == +* Contributor hereby agrees that redistribution and use of the + Contribution in source and binary forms, with or without + modification, are permitted provided that the following + conditions are met: +** Redistributions of source code must retain the Contributor's + copyright notice, this list of conditions and the following + disclaimer. +** Redistributions in binary form must reproduce the Contributor's + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. +* Disclaimer. None of the names of Contributor, Intel, or the names + of their respective contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. +* Contributor grants a license (with the right to sublicense) under + claims of Contributor's patents that Contributor can license that + are infringed by the Contribution (as delivered by Contributor) to + make, use, distribute, sell, offer for sale, and import the + Contribution and derivative works thereof solely to the minimum + extent necessary for licensee to exercise the granted copyright + license; this patent license applies solely to those portions of + the Contribution that are unmodified. No hardware per se is + licensed. +* EXCEPT AS EXPRESSLY SET FORTH IN SECTION 3 BELOW, THE + CONTRIBUTION IS PROVIDED BY THE CONTRIBUTOR "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + CONTRIBUTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +== SECTION 3: Representations == +* You represent that You are legally entitled to grant the above + license. If your employer(s) has rights to intellectual property + that You create that includes Your Contributions, You represent + that You have received permission to make Contributions on behalf + of that employer, that Your employer has waived such rights for + Your Contributions. +* You represent that each of Your Contributions is Your original + creation (see Section 4 for submissions on behalf of others). + You represent that Your Contribution submissions include complete + details of any third-party license or other restriction + (including, but not limited to, related patents and trademarks) + of which You are personally aware and which are associated with + any part of Your Contributions. + +== SECTION 4: Third Party Contributions == +* Should You wish to submit work that is not Your original creation, + You may submit it to TianoCore site separately from any + Contribution, identifying the complete details of its source + and of any license or other restriction (including, but not + limited to, related patents, trademarks, and license agreements) + of which You are personally aware, and conspicuously marking the + work as "Submitted on behalf of a third-party: [named here]". + +== SECTION 5: Miscellaneous == +* Applicable Laws. Any claims arising under or relating to this + Agreement shall be governed by the internal substantive laws of + the State of Delaware or federal courts located in Delaware, + without regard to principles of conflict of laws. +* Language. This Agreement is in the English language only, which + language shall be controlling in all respects, and all versions + of this Agreement in any other language shall be for accommodation + only and shall not be binding. All communications and notices made + or given pursuant to this Agreement, and all documentation and + support to be provided, unless otherwise noted, shall be in the + English language. + diff --git a/Core/PerformancePkg/Dp_App/Dp.c b/Core/PerformancePkg/Dp_App/Dp.c new file mode 100644 index 0000000000..4cdc39edb4 --- /dev/null +++ b/Core/PerformancePkg/Dp_App/Dp.c @@ -0,0 +1,559 @@ +/** @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 - 2017, Intel Corporation. All rights reserved.
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
+ 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" + +// +// String token ID of help message text. +// Shell supports to find help message in the resource section of an application image if +// .MAN file is not found. This global variable is added to make build tool recognizes +// that the help string is consumed by user and then build tool will add the string into +// the resource section. Thus the application can use '-?' option to show help message in +// Shell. +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mDpStrEngHelpTokenId = STRING_TOKEN (STR_DP_HELP_INFORMATION); + +// +/// Module-Global Variables +///@{ +EFI_HII_HANDLE gHiiHandle; +SHELL_PARAM_ITEM *DpParamList = NULL; +CHAR16 *mPrintTokenBuffer = NULL; +CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1]; +CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE]; +UINT64 mInterestThreshold; +BOOLEAN mShowId = FALSE; + +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); + +PARAM_ITEM_LIST ParamList[] = { + {STRING_TOKEN (STR_DP_OPTION_QH), TypeFlag}, // -? Help + {STRING_TOKEN (STR_DP_OPTION_LH), TypeFlag}, // -h Help + {STRING_TOKEN (STR_DP_OPTION_UH), TypeFlag}, // -H Help + {STRING_TOKEN (STR_DP_OPTION_LV), TypeFlag}, // -v Verbose Mode + {STRING_TOKEN (STR_DP_OPTION_UA), TypeFlag}, // -A All, Cooked + {STRING_TOKEN (STR_DP_OPTION_UR), TypeFlag}, // -R RAW All + {STRING_TOKEN (STR_DP_OPTION_LS), TypeFlag}, // -s Summary +#if PROFILING_IMPLEMENTED + {STRING_TOKEN (STR_DP_OPTION_UP), TypeFlag}, // -P Dump Profile Data + {STRING_TOKEN (STR_DP_OPTION_UT), TypeFlag}, // -T Dump Trace Data +#endif + {STRING_TOKEN (STR_DP_OPTION_LX), TypeFlag}, // -x eXclude Cumulative Items + {STRING_TOKEN (STR_DP_OPTION_LI), TypeFlag}, // -i Display Identifier + {STRING_TOKEN (STR_DP_OPTION_LC), TypeValue}, // -c Display cumulative data. + {STRING_TOKEN (STR_DP_OPTION_LN), TypeValue}, // -n # Number of records to display for A and R + {STRING_TOKEN (STR_DP_OPTION_LT), TypeValue} // -t # Threshold of interest + }; + +///@} + +/** + Transfer the param list value and get the command line parse. + +**/ +VOID +InitialShellParamList( void ) +{ + UINT32 ListIndex; + UINT32 ListLength; + + // + // Allocate one more for the end tag. + // + ListLength = ARRAY_SIZE (ParamList) + 1; + DpParamList = AllocatePool (sizeof (SHELL_PARAM_ITEM) * ListLength); + ASSERT (DpParamList != NULL); + + for (ListIndex = 0; ListIndex < ListLength - 1; ListIndex ++) + { + DpParamList[ListIndex].Name = HiiGetString (gHiiHandle, ParamList[ListIndex].Token, NULL); + DpParamList[ListIndex].Type = ParamList[ListIndex].Type; + } + DpParamList[ListIndex].Name = NULL; + DpParamList[ListIndex].Type = 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_ID)); + PrintToken (STRING_TOKEN (STR_DP_HELP_CUM_DATA)); + PrintToken (STRING_TOKEN (STR_DP_HELP_HELP)); + Print(L"\n"); +} + +/** + Display the trailing Verbose information. +**/ +VOID +DumpStatistics( void ) +{ + EFI_STRING StringPtr; + EFI_STRING StringPtrUnknown; + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL); + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? StringPtrUnknown : 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 + FreePool (StringPtr); + FreePool (StringPtrUnknown); +} + +/** + 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 EFI_ABORTED The user aborts the operation. + @retval value Unknown error. +**/ +EFI_STATUS +EFIAPI +InitializeDp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + PERFORMANCE_PROPERTY *PerformanceProperty; + UINT32 ListIndex; + + LIST_ENTRY *ParamPackage; + CONST CHAR16 *CmdLineArg; + EFI_STRING StringPtr; + UINTN Number2Display; + + EFI_STATUS Status; + BOOLEAN SummaryMode; + BOOLEAN VerboseMode; + BOOLEAN AllMode; + BOOLEAN RawMode; + BOOLEAN TraceMode; + BOOLEAN ProfileMode; + BOOLEAN ExcludeMode; + BOOLEAN CumulativeMode; + CONST CHAR16 *CustomCumulativeToken; + PERF_CUM_DATA *CustomCumulativeData; + UINTN NameSize; + EFI_HII_PACKAGE_LIST_HEADER *PackageList; + + EFI_STRING StringDpOptionQh; + EFI_STRING StringDpOptionLh; + EFI_STRING StringDpOptionUh; + EFI_STRING StringDpOptionLv; + EFI_STRING StringDpOptionUs; + EFI_STRING StringDpOptionLs; + EFI_STRING StringDpOptionUa; + EFI_STRING StringDpOptionUr; + EFI_STRING StringDpOptionUt; + EFI_STRING StringDpOptionUp; + EFI_STRING StringDpOptionLx; + EFI_STRING StringDpOptionLn; + EFI_STRING StringDpOptionLt; + EFI_STRING StringDpOptionLi; + EFI_STRING StringDpOptionLc; + + SummaryMode = FALSE; + VerboseMode = FALSE; + AllMode = FALSE; + RawMode = FALSE; + TraceMode = FALSE; + ProfileMode = FALSE; + ExcludeMode = FALSE; + CumulativeMode = FALSE; + CustomCumulativeData = NULL; + + StringDpOptionQh = NULL; + StringDpOptionLh = NULL; + StringDpOptionUh = NULL; + StringDpOptionLv = NULL; + StringDpOptionUs = NULL; + StringDpOptionLs = NULL; + StringDpOptionUa = NULL; + StringDpOptionUr = NULL; + StringDpOptionUt = NULL; + StringDpOptionUp = NULL; + StringDpOptionLx = NULL; + StringDpOptionLn = NULL; + StringDpOptionLt = NULL; + StringDpOptionLi = NULL; + StringDpOptionLc = NULL; + StringPtr = NULL; + + // + // Retrieve HII package list from ImageHandle + // + Status = gBS->OpenProtocol ( + ImageHandle, + &gEfiHiiPackageListProtocolGuid, + (VOID **) &PackageList, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Publish HII package list to HII Database. + // + Status = gHiiDatabase->NewPackageList ( + gHiiDatabase, + PackageList, + NULL, + &gHiiHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (gHiiHandle != NULL); + + + // Initial the command list + // + InitialShellParamList (); + +/**************************************************************************** +**** Process Command Line arguments **** +****************************************************************************/ + Status = ShellCommandLineParse (DpParamList, &ParamPackage, NULL, TRUE); + + if (EFI_ERROR(Status)) { + PrintToken (STRING_TOKEN (STR_DP_INVALID_ARG)); + ShowHelp(); + } + else { + StringDpOptionQh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_QH), NULL); + StringDpOptionLh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LH), NULL); + StringDpOptionUh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UH), NULL); + + if (ShellCommandLineGetFlag (ParamPackage, StringDpOptionQh) || + ShellCommandLineGetFlag (ParamPackage, StringDpOptionLh) || + ShellCommandLineGetFlag (ParamPackage, StringDpOptionUh)) + { + ShowHelp(); + } + else { + StringDpOptionLv = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LV), NULL); + StringDpOptionUs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_US), NULL); + StringDpOptionLs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LS), NULL); + StringDpOptionUa = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UA), NULL); + StringDpOptionUr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UR), NULL); + StringDpOptionUt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UT), NULL); + StringDpOptionUp = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UP), NULL); + StringDpOptionLx = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LX), NULL); + StringDpOptionLn = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LN), NULL); + StringDpOptionLt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LT), NULL); + StringDpOptionLi = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LI), NULL); + StringDpOptionLc = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LC), NULL); + + // Boolean Options + // + VerboseMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLv); + SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, StringDpOptionUs) || + ShellCommandLineGetFlag (ParamPackage, StringDpOptionLs)); + AllMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUa); + RawMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUr); +#if PROFILING_IMPLEMENTED + TraceMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUt); + ProfileMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUp); +#endif // PROFILING_IMPLEMENTED + ExcludeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLx); + mShowId = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLi); + CumulativeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLc); + + // Options with Values + CmdLineArg = ShellCommandLineGetValue (ParamPackage, StringDpOptionLn); + if (CmdLineArg == NULL) { + Number2Display = DEFAULT_DISPLAYCOUNT; + } + else { + Number2Display = StrDecimalToUintn(CmdLineArg); + if (Number2Display == 0) { + Number2Display = MAXIMUM_DISPLAYCOUNT; + } + } + CmdLineArg = ShellCommandLineGetValue (ParamPackage, StringDpOptionLt); + 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 + } + + // + // Init the custom cumulative data. + // + CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, StringDpOptionLc); + if (CustomCumulativeToken != NULL) { + CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA)); + ASSERT (CustomCumulativeData != NULL); + CustomCumulativeData->MinDur = 0; + CustomCumulativeData->MaxDur = 0; + CustomCumulativeData->Count = 0; + CustomCumulativeData->Duration = 0; + NameSize = StrLen (CustomCumulativeToken) + 1; + CustomCumulativeData->Name = AllocateZeroPool (NameSize); + UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize); + } + +/**************************************************************************** +**** 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 + // + Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty); + if (EFI_ERROR (Status) || (PerformanceProperty == NULL)) { + PrintToken (STRING_TOKEN (STR_PERF_PROPERTY_NOT_FOUND)); + goto Done; + } + + // Convert the Frequency from Hz to KHz + TimerInfo.Frequency = (UINT32)DivU64x32 (PerformanceProperty->Frequency, 1000); + TimerInfo.StartCount = PerformanceProperty->TimerStartValue; + TimerInfo.EndCount = PerformanceProperty->TimerEndValue; + + // 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, + (EFI_STRING_ID) (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 (CustomCumulativeData); + if (CumulativeMode) { + ProcessCumulative (CustomCumulativeData); + } else if (AllMode) { + if (TraceMode) { + Status = DumpAllTrace( Number2Display, ExcludeMode); + if (Status == EFI_ABORTED) { + goto Done; + } + } + if (ProfileMode) { + DumpAllProfile( Number2Display, ExcludeMode); + } + } + else if (RawMode) { + if (TraceMode) { + Status = DumpRawTrace( Number2Display, ExcludeMode); + if (Status == EFI_ABORTED) { + goto Done; + } + } + if (ProfileMode) { + DumpRawProfile( Number2Display, ExcludeMode); + } + } + else { + //------------- Begin Cooked Mode Processing + if (TraceMode) { + ProcessPhases (); + if ( ! SummaryMode) { + Status = ProcessHandles ( ExcludeMode); + if (Status == EFI_ABORTED) { + goto Done; + } + + Status = ProcessPeims (); + if (Status == EFI_ABORTED) { + goto Done; + } + + Status = ProcessGlobal (); + if (Status == EFI_ABORTED) { + goto Done; + } + + ProcessCumulative (NULL); + } + } + if (ProfileMode) { + DumpAllProfile( Number2Display, ExcludeMode); + } + } //------------- End of Cooked Mode Processing + if ( VerboseMode || SummaryMode) { + DumpStatistics(); + } + } + } + +Done: + + // + // Free the memory allocate from HiiGetString + // + ListIndex = 0; + while (DpParamList[ListIndex].Name != NULL) { + FreePool (DpParamList[ListIndex].Name); + ListIndex ++; + } + FreePool (DpParamList); + + SafeFreePool (StringDpOptionQh); + SafeFreePool (StringDpOptionLh); + SafeFreePool (StringDpOptionUh); + SafeFreePool (StringDpOptionLv); + SafeFreePool (StringDpOptionUs); + SafeFreePool (StringDpOptionLs); + SafeFreePool (StringDpOptionUa); + SafeFreePool (StringDpOptionUr); + SafeFreePool (StringDpOptionUt); + SafeFreePool (StringDpOptionUp); + SafeFreePool (StringDpOptionLx); + SafeFreePool (StringDpOptionLn); + SafeFreePool (StringDpOptionLt); + SafeFreePool (StringDpOptionLi); + SafeFreePool (StringDpOptionLc); + SafeFreePool (StringPtr); + SafeFreePool (mPrintTokenBuffer); + + if (ParamPackage != NULL) { + ShellCommandLineFreeVarList (ParamPackage); + } + if (CustomCumulativeData != NULL) { + SafeFreePool (CustomCumulativeData->Name); + } + SafeFreePool (CustomCumulativeData); + + HiiRemovePackages (gHiiHandle); + return Status; +} diff --git a/Core/PerformancePkg/Dp_App/Dp.h b/Core/PerformancePkg/Dp_App/Dp.h new file mode 100644 index 0000000000..5fc3335279 --- /dev/null +++ b/Core/PerformancePkg/Dp_App/Dp.h @@ -0,0 +1,101 @@ +/** @file + Common declarations for the Dp Performance Reporting Utility. + + Copyright (c) 2009 - 2012, 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_ + +#include + +#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 { + CONST VOID *Handle; + CONST CHAR8 *Token; ///< Measured token string name. + CONST CHAR8 *Module; ///< Module string name. + UINT64 StartTimeStamp; ///< Start time point. + UINT64 EndTimeStamp; ///< End time point. + UINT32 Identifier; ///< Identifier. +} 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; + +typedef struct { + UINT16 Token; + SHELL_PARAM_TYPE Type; +} PARAM_ITEM_LIST; +#endif // _EFI_APP_DP_H_ diff --git a/Core/PerformancePkg/Dp_App/Dp.inf b/Core/PerformancePkg/Dp_App/Dp.inf new file mode 100644 index 0000000000..1204d8ef5b --- /dev/null +++ b/Core/PerformancePkg/Dp_App/Dp.inf @@ -0,0 +1,80 @@ +## @file +# Display Performance Application, Module information file. +# +# Copyright (c) 2009 - 2017, 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 + +# +# This flag specifies whether HII resource section is generated into PE image. +# + UEFI_HII_RESOURCE_SECTION = TRUE + +# +# 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 + Dp.h + Literals.h + Literals.c + DpInternal.h + 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 + PeCoffGetEntryPointLib + PerformanceLib + PrintLib + UefiLib + HiiLib + UefiHiiServicesLib + PcdLib + DevicePathLib + DxeServicesLib + +[Guids] + gPerformanceProtocolGuid ## CONSUMES ## SystemTable + +[Protocols] + gEfiLoadedImageProtocolGuid ## CONSUMES + gEfiHiiPackageListProtocolGuid ## CONSUMES + gEfiDriverBindingProtocolGuid ## SOMETIMES_CONSUMES + gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadedImageDevicePathProtocolGuid ## SOMETIMES_CONSUMES + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize ## CONSUMES diff --git a/Core/PerformancePkg/Dp_App/DpInternal.h b/Core/PerformancePkg/Dp_App/DpInternal.h new file mode 100644 index 0000000000..1ab36ba7ed --- /dev/null +++ b/Core/PerformancePkg/Dp_App/DpInternal.h @@ -0,0 +1,383 @@ +/** @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 - 2017, Intel Corporation. All rights reserved.
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
+ 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 _DP_INTELNAL_H_ +#define _DP_INTELNAL_H_ + +#define DP_GAUGE_STRING_LENGTH 36 + +// +/// Module-Global Variables +///@{ +extern EFI_HII_HANDLE gHiiHandle; +extern CHAR16 *mPrintTokenBuffer; +extern CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1]; +extern CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE]; +extern UINT64 mInterestThreshold; +extern BOOLEAN mShowId; + +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. 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. + + @param 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 + ); + +/** + 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 + ); + +/** + 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. + The following methods will be tried orderly: + 1. Image PDB + 2. ComponentName2 protocol + 3. FFS UI section + 4. Image GUID + 5. Image DevicePath + 6. Unknown Driver Name + + @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 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 + ); + +/** + Formatted Print using a Hii Token to reference the localized format string. + + @param[in] Token A HII token associated with a localized Unicode string. + @param[in] ... The variable argument list. + + @return The number of characters converted by UnicodeVSPrint(). + +**/ +UINTN +EFIAPI +PrintToken ( + IN UINT16 Token, + ... + ); + +/** + 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 + ); + +/** + 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. + + @param[in, out] CustomCumulativeData The pointer to the custom cumulative data. + +**/ +VOID +GatherStatistics( + IN OUT PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ); + +/** + 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. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +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. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +DumpRawTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ); + +/** + Gather and print Major Phase metrics. + +**/ +VOID +ProcessPhases( + VOID + ); + + +/** + Gather and print Handle data. + + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +ProcessHandles( + IN BOOLEAN ExcludeFlag + ); + + +/** + Gather and print PEIM data. + + Only prints complete PEIM records + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +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. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +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. + + @param[in] CustomCumulativeData The pointer to the custom cumulative data. + +**/ +VOID +ProcessCumulative( + IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + Wrap original FreePool to check NULL pointer first. + + @param[in] Buffer The pointer to the buffer to free. + +**/ +VOID +SafeFreePool ( + IN VOID *Buffer + ); + +#endif diff --git a/Core/PerformancePkg/Dp_App/DpProfile.c b/Core/PerformancePkg/Dp_App/DpProfile.c new file mode 100644 index 0000000000..15c2ef14d4 --- /dev/null +++ b/Core/PerformancePkg/Dp_App/DpProfile.c @@ -0,0 +1,102 @@ +/** @file + Measured Profiling reporting for the Dp utility. + + Copyright (c) 2009 - 2017, 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" + +/** + 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; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PROFILE), NULL); + + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? StringPtrUnknown: StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + 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; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWPROFILE), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? StringPtrUnknown: StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + return; +} diff --git a/Core/PerformancePkg/Dp_App/DpStrings.uni b/Core/PerformancePkg/Dp_App/DpStrings.uni new file mode 100644 index 0000000000..131d16bb6d --- /dev/null +++ b/Core/PerformancePkg/Dp_App/DpStrings.uni @@ -0,0 +1,281 @@ +// *++ +// +// Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+// (C) Copyright 2015 Hewlett Packard Enterprise Development LP
+// 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 Name: +// +// DpStrings.uni +// +// Abstract: +// +// String definitions for the Shell dp command +// +// Revision History: +// +// --*/ + +/=# + +#langdef en-US "English" +#langdef fr-FR "Français" + +#string STR_DP_HELP_INFORMATION #language en-US "" + ".TH DP 0 "Display Performance metrics."\r\n" + ".SH NAME\r\n" + "Display Performance metrics.\r\n" + ".SH SYNOPSIS\r\n" + " \r\n" + "If Profiling is implemented:\r\n" + "dp [-b] [-v] [-x] [-s | -A | -R] [-T] [-P] [-t value] [-n count] [-c [token]] [-i] [-?]\r\n" + "If Profiling is not implemented:\r\n" + "dp [-b] [-v] [-x] [-s | -A | -R] [-t value] [-n count] [-c [token]] [-i] [-?]\r\n" + ".SH OPTIONS\r\n" + " \r\n" + " -b display on multiple pages\n\r\n" + " -v display additional information\r\n" + " -x prevent display of individual measurements for cumulative items\r\n" + " -s display summary information only\r\n" + " -A display all measurements in a list\r\n" + " -R display all measurements in raw format\r\n" + " -T display Trace measurements only(This option is available when Profiling is implemented)\r\n" + " -P display Profile measurements only(This option is available when Profiling is implemented)\r\n" + " -t VALUE Set display threshold to VALUE microseconds\r\n" + " -n COUNT Limit display to COUNT lines in All and Raw modes\r\n" + " -i display identifier\r\n" + " -c TOKEN - Display pre-defined and custom cumulative data\r\n" + " Pre-defined cumulative token are:\r\n" + " 1. LoadImage:\r\n" + " 2. StartImage:\r\n" + " 3. DB:Start:\r\n" + " 4. DB:Support:\r\n" + " -? display dp help information\r\n" + "\r\n" + #language fr-FR "" + ".TH DP 0 "Montrer les données d'exécution"\r\n" + ".SH NAME\r\n" + "Montrer les données d'exécution\r\n" + ".SH SYNOPSIS\r\n" + " \r\n" + "If Profiling is implemented:\r\n" + "dp [-b] [-v] [-x] [-s | -A | -R] [-T] [-P] [-t value] [-n count] [-c [token]] [-i] [-?]\r\n" + "If Profiling is not implemented:\r\n" + "dp [-b] [-v] [-x] [-s | -A | -R] [-t value] [-n count] [-c [token]] [-i] [-?]\r\n" + ".SH OPTIONS\r\n" + " \r\n" + " -b montrer sur les pages multiples\r\n" + " -v display additional information\r\n" + " -x prevent display of individual measurements for cumulative items\r\n" + " -s montrer les données de statistique seulement\r\n" + " -A\r\n" + " -R\r\n" + " -T\r\n" + " -P\r\n" + " -t VALUE\r\n" + " -n COUNT\r\n" + " -i\r\n" + " -c\r\n" + " -? montrer dp aider l'information\r\n" + "\r\n" + +#string STR_DP_HELP_HEAD #language en-US "\nDisplay Performance metrics\n" + #language fr-FR "\nMontrer les données d'exécution\n" +#string STR_DP_HELP_FLAGS #language en-US "dp [-b] [-v] [-x] [-s | -A | -R] [-T] [-P] [-t value] [-n count] [-c [token]] [-i] [-?]\n" + #language fr-FR "dp [-b] [-v] [-x] [-s | -A | -R] [-T] [-P] [-t value] [-n count] [-c [token]] [-i] [-?]\n" +#string STR_DP_HELP_FLAGS_2 #language en-US "dp [-b] [-v] [-x] [-s | -A | -R] [-t value] [-n count] [-c [token]] [-i] [-?]\n" + #language fr-FR "dp [-b] [-v] [-x] [-s | -A | -R] [-t value] [-n count] [-c [token]] [-i] [-?]\n" +#string STR_DP_HELP_PAGINATE #language en-US " -b display on multiple pages\n" + #language fr-FR " -b montrer sur les pages multiples\n" +#string STR_DP_HELP_VERBOSE #language en-US " -v display additional information\n" + #language fr-FR " -v display additional information\n" +#string STR_DP_HELP_EXCLUDE #language en-US " -x prevent display of individual measurements for cumulative items.\n" + #language fr-FR " -x prevent display of individual measurements for cumulative items.\n" +#string STR_DP_HELP_STAT #language en-US " -s display summary information only\n" + #language fr-FR " -s montrer les données de statistique seulement\n" +#string STR_DP_HELP_ALL #language en-US " -A display all measurements in a list\n" + #language fr-FR " -A\n" +#string STR_DP_HELP_RAW #language en-US " -R display all measurements in raw format\n" + #language fr-FR " -R\n" +#string STR_DP_HELP_TRACE #language en-US " -T display Trace measurements only\n" + #language fr-FR " -T\n" +#string STR_DP_HELP_PROFILE #language en-US " -P display Profile measurements only\n" + #language fr-FR " -P\n" +#string STR_DP_HELP_THRESHOLD #language en-US " -t VALUE Set display threshold to VALUE microseconds\n" + #language fr-FR " -t VALUE\n" +#string STR_DP_HELP_COUNT #language en-US " -n COUNT Limit display to COUNT lines in All and Raw modes\n" + #language fr-FR " -n COUNT\n" +#string STR_DP_HELP_ID #language en-US " -i display identifier\n" + #language fr-FR " -i\n" +#string STR_DP_HELP_CUM_DATA #language en-US " -c TOKEN - Display pre-defined and custom cumulative data\r\n" + " Pre-defined cumulative token are:\r\n" + " 1. LoadImage:\r\n" + " 2. StartImage:\r\n" + " 3. DB:Start:\r\n" + " 4. DB:Support:\r\n" + #language fr-FR " -c\n" +#string STR_DP_HELP_HELP #language en-US " -? display dp help information\n" + #language fr-FR " -? montrer dp aider l'information\n" +#string STR_DP_UP #language en-US "UP" + #language fr-FR "UP" +#string STR_DP_DOWN #language en-US "DOWN" + #language fr-FR "DOWN" +#string STR_DP_DASHES #language en-US "-------------------------------------------------------------------------------\n" + #language fr-FR "-------------------------------------------------------------------------------\n" +#string STR_DP_SECTION_HEADER #language en-US "\n==[ %s ]========\n" + #language fr-FR "\n==[ %s ]========\n" +#string STR_DP_INVALID_ARG #language en-US "Invalid argument(s)\n" + #language fr-FR "Argument d'invalide(s)\n" +#string STR_DP_HANDLES_ERROR #language en-US "Locate All Handles error - %r\n" + #language fr-FR "Localiser Toute erreur de Poignées - %r\n" +#string STR_DP_ERROR_NAME #language en-US "Unknown Driver Name" + #language fr-FR "Unknown Driver Name" +#string STR_PERF_PROPERTY_NOT_FOUND #language en-US "Performance property not found\n" + #language fr-FR "Performance property not found\n" +#string STR_DP_BUILD_REVISION #language en-US "\nDP Build Version: %d.%d\n" + #language fr-FR "\nDP Construit la Version: %d,%d\n" +#string STR_DP_KHZ #language en-US "System Performance Timer Frequency: %,8d (KHz)\n" + #language fr-FR "System Performance Timer Frequency: %,8d (KHz)\n" +#string STR_DP_TIMER_PROPERTIES #language en-US "System Performance Timer counts %s from 0x%Lx to 0x%Lx\n" + #language fr-FR "System Performance Timer counts %s from 0x%Lx to 0x%Lx\n" +#string STR_DP_VERBOSE_THRESHOLD #language en-US "Measurements less than %,Ld microseconds are not displayed.\n" + #language fr-FR "Measurements less than %,Ld microseconds are not displayed.\n" +#string STR_DP_SECTION_PHASES #language en-US "Major Phases" + #language fr-FR "Major Phases" +#string STR_DP_SEC_PHASE #language en-US " SEC Phase Duration: %L8d (us)\n" + #language fr-FR " SEC Phase Duration: %L8d (us)\n" +#string STR_DP_PHASE_BDSTO #language en-US " BDS Timeout: %L8d (ms) included in BDS Duration\n" + #language fr-FR " BDS Timeout: %L8d (ms) included in BDS Duration\n" +#string STR_DP_PHASE_DURATION #language en-US "%5a Phase Duration: %L8d (ms)\n" + #language fr-FR "%5a Phase Duration: %L8d (ms)\n" +#string STR_DP_TOTAL_DURATION #language en-US "Total Duration: %L8d (ms)\n" + #language fr-FR "Total Duration: %L8d (ms)\n" +#string STR_DP_SECTION_DRIVERS #language en-US "Drivers by Handle" + #language fr-FR "Drivers by Handle" +#string STR_DP_HANDLE_SECTION #language en-US "Index: Handle Driver Name Description Time(us)\n" + #language fr-FR "Index: Poignée Nom(GUID) Description Temps(us)\n" +#string STR_DP_HANDLE_VARS #language en-US "%5d: [%3x] %36s %11s %L8d\n" + #language fr-FR "%5d: [%3x] %36s %11s %L8d\n" +#string STR_DP_HANDLE_SECTION2 #language en-US "Index: Handle Driver Name Description Time(us) ID\n" + #language fr-FR "Index: Poignée Nom(GUID) Description Temps(us) ID\n" +#string STR_DP_HANDLE_VARS2 #language en-US "%5d: [%3x] %36s %11s %L8d %5d\n" + #language fr-FR "%5d: [%3x] %36s %11s %L8d %5d\n" +#string STR_DP_SECTION_PEIMS #language en-US "PEIMs" + #language fr-FR "PEIMs" +#string STR_DP_PEIM_SECTION #language en-US "Index: Pointer Value Instance GUID Token Time(us)\n" + #language fr-FR "Index: Pointer Value Instance GUID Token Temps(us)\n" +#string STR_DP_PEIM_VARS #language en-US "%5d: 0x%11p %g PEIM %L8d\n" + #language fr-FR "%5d: 0x%11p %g PEIM %L8d\n" +#string STR_DP_PEIM_SECTION2 #language en-US "Index: Pointer Value Instance GUID Token Time(us) ID\n" + #language fr-FR "Index: Pointer Value Instance GUID Token Temps(us) ID\n" +#string STR_DP_PEIM_VARS2 #language en-US "%5d: 0x%11p %g PEIM %L8d %5d\n" + #language fr-FR "%5d: 0x%11p %g PEIM %L8d %5d\n" +#string STR_DP_SECTION_GENERAL #language en-US "General" + #language fr-FR "General" +#string STR_DP_GLOBAL_SECTION #language en-US "Index Name Description Time(us)\n" + #language fr-FR "Index Nom Description Temps(us)\n" +#string STR_DP_GLOBAL_VARS #language en-US "%5d:%25s %31s %L8d\n" + #language fr-FR "%5d:%25s %31s %L8d\n" +#string STR_DP_GLOBAL_SECTION2 #language en-US "Index Name Description Time(us) ID\n" + #language fr-FR "Index Nom Description Temps(us) ID\n" +#string STR_DP_GLOBAL_VARS2 #language en-US "%5d:%25s %31s %L8d %5d\n" + #language fr-FR "%5d:%25s %31s %L8d %5d\n" +#string STR_DP_SECTION_CUMULATIVE #language en-US "Cumulative" + #language fr-FR "Cumulative" +#string STR_DP_CUMULATIVE_SECT_1 #language en-US "(Times in microsec.) Cumulative Average Shortest Longest\n" + #language fr-FR "(Times in microsec.) Cumulative Average Shortest Longest\n" +#string STR_DP_CUMULATIVE_SECT_2 #language en-US " Name Count Duration Duration Duration Duration\n" + #language fr-FR " Name Count Duration Duration Duration Duration\n" +#string STR_DP_CUMULATIVE_STATS #language en-US "%11a %8d %L10d %L10d %L10d %L10d\n" + #language fr-FR "%11a %8d %L10d %L10d %L10d %L10d\n" +#string STR_DP_SECTION_STATISTICS #language en-US "Statistics" + #language fr-FR "Statistics" +#string STR_DP_STATS_NUMTRACE #language en-US "There were %d measurements taken, of which:\n" + #language fr-FR "There were %d measurements taken, of which:\n" +#string STR_DP_STATS_NUMINCOMPLETE #language en-US "%,8d are incomplete.\n" + #language fr-FR "%,8d are incomplete.\n" +#string STR_DP_STATS_NUMPHASES #language en-US "%,8d are major execution phases.\n" + #language fr-FR "%,8d are major execution phases.\n" +#string STR_DP_STATS_NUMHANDLES #language en-US "%,8d have non-NULL handles, %d are NULL.\n" + #language fr-FR "%,8d have non-NULL handles, %d are NULL.\n" +#string STR_DP_STATS_NUMPEIMS #language en-US "%,8d are PEIMs.\n" + #language fr-FR "%,8d are PEIMs.\n" +#string STR_DP_STATS_NUMGLOBALS #language en-US "%,8d are general measurements.\n" + #language fr-FR "%,8d are general measurements.\n" +#string STR_DP_STATS_NUMPROFILE #language en-US "%,8d are profiling records.\n" + #language fr-FR "%,8d are profiling records.\n" +#string STR_DP_SECTION_PROFILE #language en-US "Sequential Profile Records" + #language fr-FR "Sequential Profile Records" +#string STR_DP_SECTION_ALL #language en-US "Sequential Trace Records" + #language fr-FR "Sequential Trace Records" +#string STR_DP_ALL_HEADR #language en-US "\nIndex Handle Module Token Time(us)\n" + #language fr-FR "\nIndex Handle Module Token Temps(us)\n" +#string STR_DP_ALL_VARS #language en-US "%5d:%3s0x%08p %36s %13s %L8d\n" + #language fr-FR "%5d:%3s0x%08p %36s %13s %L8d\n" +#string STR_DP_ALL_DASHES2 #language en-US "-------------------------------------------------------------------------------------\n" + #language fr-FR "-------------------------------------------------------------------------------------\n" +#string STR_DP_ALL_HEADR2 #language en-US "\nIndex Handle Module Token Time(us) ID\n" + #language fr-FR "\nIndex Handle Module Token Temps(us) ID\n" +#string STR_DP_ALL_VARS2 #language en-US "%5d:%3s0x%08p %36s %13s %L8d %5d\n" + #language fr-FR "%5d:%3s0x%08p %36s %13s %L8d %5d\n" +#string STR_DP_SECTION_RAWTRACE #language en-US "RAW Trace" + #language fr-FR "RAW Trace" +#string STR_DP_SECTION_RAWPROFILE #language en-US "RAW Profile" + #language fr-FR "RAW Profile" +#string STR_DP_RAW_DASHES #language en-US "---------------------------------------------------------------------------------------------------------------------------\n" + #language fr-FR "---------------------------------------------------------------------------------------------------------------------------\n" +#string STR_DP_RAW_VARS #language en-US "%5d: %16LX %16LX %16LX %31a %31a\n" + #language fr-FR "%5d: %16LX %16LX %16LX %31a %31a\n" +#string STR_DP_RAW_HEADR #language en-US "\nIndex Handle Start Count End Count Token Module\n" + #language fr-FR "\nIndex Handle Start Count End Count Token Module\n" +#string STR_DP_RAW_DASHES2 #language en-US "---------------------------------------------------------------------------------------------------------------------------------\n" + #language fr-FR "---------------------------------------------------------------------------------------------------------------------------------\n" +#string STR_DP_RAW_VARS2 #language en-US "%5d: %16LX %16LX %16LX %31a %31a %5d\n" + #language fr-FR "%5d: %16LX %16LX %16LX %31a %31a %5d\n" +#string STR_DP_RAW_HEADR2 #language en-US "\nIndex Handle Start Count End Count Token Module ID\n" + #language fr-FR "\nIndex Handle Start Count End Count Token Module ID\n" +#string STR_DP_OPTION_UA #language en-US "-A" + #language fr-FR "-A" +#string STR_DP_OPTION_LA #language en-US "-a" + #language fr-FR "-a" +#string STR_DP_OPTION_LN #language en-US "-n" + #language fr-FR "-n" +#string STR_DP_OPTION_LT #language en-US "-t" + #language fr-FR "-t" +#string STR_DP_OPTION_UP #language en-US "-P" + #language fr-FR "-P" +#string STR_DP_OPTION_UR #language en-US "-R" + #language fr-FR "-R" +#string STR_DP_OPTION_LS #language en-US "-s" + #language fr-FR "-s" +#string STR_DP_OPTION_US #language en-US "-S" + #language fr-FR "-S" +#string STR_DP_OPTION_UT #language en-US "-T" + #language fr-FR "-T" +#string STR_DP_OPTION_LV #language en-US "-v" + #language fr-FR "-v" +#string STR_DP_OPTION_QH #language en-US "-?" + #language fr-FR "-?" +#string STR_DP_OPTION_LH #language en-US "-h" + #language fr-FR "-h" +#string STR_DP_OPTION_UH #language en-US "-H" + #language fr-FR "-H" +#string STR_DP_OPTION_LX #language en-US "-x" + #language fr-FR "-x" +#string STR_DP_OPTION_LI #language en-US "-i" + #language fr-FR "-i" +#string STR_DP_OPTION_LC #language en-US "-c" + #language fr-FR "-c" +#string STR_DP_INCOMPLETE #language en-US " I " + #language fr-FR " I " +#string STR_DP_COMPLETE #language en-US " " + #language fr-FR " " +#string STR_ALIT_UNKNOWN #language en-US "Unknown" + #language fr-FR "Unknown" \ No newline at end of file diff --git a/Core/PerformancePkg/Dp_App/DpTrace.c b/Core/PerformancePkg/Dp_App/DpTrace.c new file mode 100644 index 0000000000..9b4e0ed289 --- /dev/null +++ b/Core/PerformancePkg/Dp_App/DpTrace.c @@ -0,0 +1,879 @@ +/** @file + Trace reporting for the Dp utility. + + Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
+ 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" + +/** + 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. + + @param[in, out] CustomCumulativeData A pointer to the cumtom cumulative data. + +**/ +VOID +GatherStatistics( + IN OUT PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINTN LogEntryKey; + INTN TIndex; + + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurementEx ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 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; + } + } + + // + // Collect the data for custom cumulative data. + // + if ((CustomCumulativeData != NULL) && (AsciiStrCmp (Measurement.Token, CustomCumulativeData->Name) == 0)) { + CustomCumulativeData->Duration += Duration; + CustomCumulativeData->Count++; + if (Duration < CustomCumulativeData->MinDur) { + CustomCumulativeData->MinDur = Duration; + } + if (Duration > CustomCumulativeData->MaxDur) { + CustomCumulativeData->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. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +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 HandleCount; + EFI_STATUS Status; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (IncFlag == NULL) ? StringPtrUnknown : IncFlag); + FreePool (StringPtrUnknown); + + // Get Handle information + // + Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &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. + // + if (mShowId) { + PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR2) ); + PrintToken (STRING_TOKEN (STR_DP_ALL_DASHES2) ); + } else { + 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 = GetPerformanceMeasurementEx ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + ) + { + ++Index; // Count every record. First record is 1. + ElapsedTime = 0; + SafeFreePool ((VOID *) IncFlag); + if (Measurement.EndTimeStamp != 0) { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL); + } + else { + IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL); // Mark incomplete records + } + if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) || + ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) + ) { // Ignore "uninteresting" or excluded records + continue; + } + ++Count; // Count the number of records printed + + // If Handle is non-zero, see if we can determine a name for the driver + AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString)); // Use Module by default + AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken)); + if (Measurement.Handle != NULL) { + // See if the Handle is in the HandleBuffer + for (TIndex = 0; TIndex < HandleCount; TIndex++) { + if (Measurement.Handle == HandleBuffer[TIndex]) { + GetNameFromHandle (HandleBuffer[TIndex]); + break; + } + } + } + + if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) { + UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle); + } + + // Ensure that the argument strings are not too long. + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + mUnicodeToken[13] = 0; + + if (mShowId) { + PrintToken( STRING_TOKEN (STR_DP_ALL_VARS2), + Index, // 1 based, Which measurement record is being printed + IncFlag, + Measurement.Handle, + mGaugeString, + mUnicodeToken, + ElapsedTime, + Measurement.Identifier + ); + } else { + PrintToken( STRING_TOKEN (STR_DP_ALL_VARS), + Index, // 1 based, Which measurement record is being printed + IncFlag, + Measurement.Handle, + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + SafeFreePool ((VOID *) IncFlag); + return Status; +} + +/** + 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. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +DumpRawTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 ElapsedTime; + UINT64 Duration; + UINTN LogEntryKey; + UINTN Count; + UINTN Index; + + EFI_STRING StringPtr; + EFI_STRING StringPtrUnknown; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + if (mShowId) { + PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR2) ); + PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES2) ); + } else { + 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 = GetPerformanceMeasurementEx ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 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 + + if (mShowId) { + PrintToken (STRING_TOKEN (STR_DP_RAW_VARS2), + Index, // 1 based, Which measurement record is being printed + Measurement.Handle, + Measurement.StartTimeStamp, + Measurement.EndTimeStamp, + Measurement.Token, + Measurement.Module, + Measurement.Identifier + ); + } else { + 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 + ); + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + return Status; +} + +/** + Gather and print Major Phase metrics. + +**/ +VOID +ProcessPhases( + VOID + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 BdsTimeoutValue; + UINT64 SecTime; + UINT64 PeiTime; + UINT64 DxeTime; + UINT64 BdsTime; + UINT64 ElapsedTime; + UINT64 Duration; + UINT64 Total; + EFI_STRING StringPtr; + UINTN LogEntryKey; + EFI_STRING StringPtrUnknown; + + BdsTimeoutValue = 0; + SecTime = 0; + PeiTime = 0; + DxeTime = 0; + BdsTime = 0; + // + // Get Execution Phase Statistics + // + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurementEx ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + 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; + } + } + + 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); + } + + PrintToken (STRING_TOKEN (STR_DP_TOTAL_DURATION), Total); +} + +/** + Gather and print Handle data. + + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +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 HandleCount; + EFI_STATUS Status; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &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 + + if (mShowId) { + PrintToken (STRING_TOKEN (STR_DP_HANDLE_SECTION2) ); + } else { + PrintToken (STRING_TOKEN (STR_DP_HANDLE_SECTION) ); + } + PrintToken (STRING_TOKEN (STR_DP_DASHES) ); + + LogEntryKey = 0; + Count = 0; + while ((LogEntryKey = GetPerformanceMeasurementEx ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 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 + AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken)); + // See if the Handle is in the HandleBuffer + for (Index = 0; Index < HandleCount; 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[DP_GAUGE_STRING_LENGTH] = 0; + mUnicodeToken[11] = 0; + if (mGaugeString[0] != 0) { + // Display the record if it has a valid handle. + if (mShowId) { + PrintToken ( + STRING_TOKEN (STR_DP_HANDLE_VARS2), + Count, // 1 based, Which measurement record is being printed + Index + 1, // 1 based, Which handle is being printed + mGaugeString, + mUnicodeToken, + ElapsedTime, + Measurement.Identifier + ); + } else { + 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 + ); + } + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + return Status; +} + +/** + Gather and print PEIM data. + + Only prints complete PEIM records + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +ProcessPeims( + VOID +) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINT64 ElapsedTime; + EFI_STRING StringPtr; + UINTN LogEntryKey; + UINTN TIndex; + EFI_STRING StringPtrUnknown; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + if (mShowId) { + PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION2)); + } else { + PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION)); + } + PrintToken (STRING_TOKEN (STR_DP_DASHES)); + TIndex = 0; + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurementEx ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 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) { + // PEIM FILE Handle is the start address of its FFS file that contains its file guid. + if (mShowId) { + PrintToken (STRING_TOKEN (STR_DP_PEIM_VARS2), + TIndex, // 1 based, Which measurement record is being printed + Measurement.Handle, // base address + Measurement.Handle, // file guid + ElapsedTime, + Measurement.Identifier + ); + } else { + PrintToken (STRING_TOKEN (STR_DP_PEIM_VARS), + TIndex, // 1 based, Which measurement record is being printed + Measurement.Handle, // base address + Measurement.Handle, // file guid + ElapsedTime + ); + } + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + return Status; +} + +/** + 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. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +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 + EFI_STRING StringPtrUnknown; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? StringPtrUnknown: StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + if (mShowId) { + PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION2)); + } else { + PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION)); + } + PrintToken (STRING_TOKEN (STR_DP_DASHES)); + + Index = 1; + LogEntryKey = 0; + + while ((LogEntryKey = GetPerformanceMeasurementEx ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString)); + AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken)); + mGaugeString[25] = 0; + mUnicodeToken[31] = 0; + if ( ! ( IsPhase( &Measurement) || + (Measurement.Handle != NULL) || + (Measurement.EndTimeStamp == 0) + )) + { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + if (ElapsedTime >= mInterestThreshold) { + if (mShowId) { + PrintToken ( + STRING_TOKEN (STR_DP_GLOBAL_VARS2), + Index, + mGaugeString, + mUnicodeToken, + ElapsedTime, + Measurement.Identifier + ); + } else { + PrintToken ( + STRING_TOKEN (STR_DP_GLOBAL_VARS), + Index, + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + } + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + Index++; + } + return Status; +} + +/** + 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. + + @param[in] CustomCumulativeData A pointer to the cumtom cumulative data. + +**/ +VOID +ProcessCumulative( + IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ) +{ + UINT64 AvgDur; // the computed average duration + UINT64 Dur; + UINT64 MinDur; + UINT64 MaxDur; + EFI_STRING StringPtr; + UINTN TIndex; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL); + PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), + (StringPtr == NULL) ? StringPtrUnknown: StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + 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) { + if (CumData[TIndex].Count != 0) { + AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count); + AvgDur = DurationInMicroSeconds(AvgDur); + Dur = DurationInMicroSeconds(CumData[TIndex].Duration); + MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur); + MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur); + + PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS), + CumData[TIndex].Name, + CumData[TIndex].Count, + Dur, + AvgDur, + MinDur, + MaxDur + ); + } + } + + // + // Print the custom cumulative data. + // + if (CustomCumulativeData != NULL) { + if (CustomCumulativeData->Count != 0) { + AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count); + AvgDur = DurationInMicroSeconds (AvgDur); + Dur = DurationInMicroSeconds (CustomCumulativeData->Duration); + MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur); + MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur); + } else { + AvgDur = 0; + Dur = 0; + MaxDur = 0; + MinDur = 0; + } + PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS), + CustomCumulativeData->Name, + CustomCumulativeData->Count, + Dur, + AvgDur, + MinDur, + MaxDur + ); + } +} diff --git a/Core/PerformancePkg/Dp_App/DpUtilities.c b/Core/PerformancePkg/Dp_App/DpUtilities.c new file mode 100644 index 0000000000..d3a9b6eab3 --- /dev/null +++ b/Core/PerformancePkg/Dp_App/DpUtilities.c @@ -0,0 +1,489 @@ +/** @file + Utility functions used by the Dp application. + + Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ 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 +#include +#include +#include + +#include + +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +/** + Wrap original FreePool to check NULL pointer first. + + @param[in] Buffer The pointer to the buffer to free. + +**/ +VOID +SafeFreePool ( + IN VOID *Buffer + ) +{ + if (Buffer != NULL) { + FreePool (Buffer); + } +} + +/** + 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. + + @param 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; + + if (Measurement->EndTimeStamp == 0) { + return 0; + } + + // 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, (DP_GAUGE_STRING_LENGTH + 1) * sizeof (CHAR16)); + + if (PdbFileName == NULL) { + StrCpyS (UnicodeBuffer, DP_GAUGE_STRING_LENGTH + 1, L" "); + } else { + StartIndex = 0; + for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++) + ; + for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) { + if ((PdbFileName[IndexA] == '\\') || (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 >= DP_GAUGE_STRING_LENGTH) { + UnicodeBuffer[DP_GAUGE_STRING_LENGTH] = 0; + break; + } + } + } +} + +/** + Get a human readable name for an image handle. + The following methods will be tried orderly: + 1. Image PDB + 2. ComponentName2 protocol + 3. FFS UI section + 4. Image GUID + 5. Image DevicePath + 6. Unknown Driver Name + + @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; + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_GUID *NameGuid; + CHAR16 *NameString; + UINTN StringSize; + CHAR8 *PlatformLanguage; + CHAR8 *BestLanguage; + EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2; + + Image = NULL; + LoadedImageDevicePath = NULL; + DevicePath = NULL; + BestLanguage = NULL; + PlatformLanguage = NULL; + + // + // Method 1: Get the name string from image PDB + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &Image + ); + + if (EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol ( + DriverBinding->ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &Image + ); + } + } + + if (!EFI_ERROR (Status)) { + PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase); + + if (PdbFileName != NULL) { + GetShortPdbFileName (PdbFileName, mGaugeString); + return; + } + } + + // + // Method 2: Get the name string from ComponentName2 protocol + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiComponentName2ProtocolGuid, + (VOID **) &ComponentName2 + ); + if (!EFI_ERROR (Status)) { + // + // Get the current platform language setting + // + GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL); + + BestLanguage = GetBestLanguage( + ComponentName2->SupportedLanguages, + FALSE, + PlatformLanguage, + ComponentName2->SupportedLanguages, + NULL + ); + + SafeFreePool (PlatformLanguage); + Status = ComponentName2->GetDriverName ( + ComponentName2, + BestLanguage, + &StringPtr + ); + SafeFreePool (BestLanguage); + if (!EFI_ERROR (Status)) { + StrnCpyS ( + mGaugeString, + DP_GAUGE_STRING_LENGTH + 1, + StringPtr, + DP_GAUGE_STRING_LENGTH + ); + return; + } + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID **) &LoadedImageDevicePath + ); + if (!EFI_ERROR (Status) && (LoadedImageDevicePath != NULL)) { + DevicePath = LoadedImageDevicePath; + } else if (Image != NULL) { + DevicePath = Image->FilePath; + } + + if (DevicePath != NULL) { + // + // Try to get image GUID from image DevicePath + // + NameGuid = NULL; + while (!IsDevicePathEndType (DevicePath)) { + NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath); + if (NameGuid != NULL) { + break; + } + DevicePath = NextDevicePathNode (DevicePath); + } + + if (NameGuid != NULL) { + // + // Try to get the image's FFS UI section by image GUID + // + NameString = NULL; + StringSize = 0; + Status = GetSectionFromAnyFv ( + NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **) &NameString, + &StringSize + ); + + if (!EFI_ERROR (Status)) { + // + // Method 3. Get the name string from FFS UI section + // + StrnCpyS ( + mGaugeString, + DP_GAUGE_STRING_LENGTH + 1, + NameString, + DP_GAUGE_STRING_LENGTH + ); + FreePool (NameString); + } else { + // + // Method 4: Get the name string from image GUID + // + UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", NameGuid); + } + return; + } else { + // + // Method 5: Get the name string from image DevicePath + // + NameString = ConvertDevicePathToText (DevicePath, TRUE, FALSE); + if (NameString != NULL) { + StrnCpyS ( + mGaugeString, + DP_GAUGE_STRING_LENGTH + 1, + NameString, + DP_GAUGE_STRING_LENGTH + ); + FreePool (NameString); + return; + } + } + } + + // + // Method 6: Unknown Driver Name + // + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_ERROR_NAME), NULL); + ASSERT (StringPtr != NULL); + StrCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr); + FreePool (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. + @param[in] ... The variable argument list. + + @return The number of characters converted by UnicodeVSPrint(). + +**/ +UINTN +EFIAPI +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); + VA_END (Marker); + + if (Return > 0 && gST->ConOut != NULL) { + gST->ConOut->OutputString (gST->ConOut, mPrintTokenBuffer); + } + FreePool (StringPtr); + 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/Core/PerformancePkg/Dp_App/Literals.c b/Core/PerformancePkg/Dp_App/Literals.c new file mode 100644 index 0000000000..c1cddfb9ff --- /dev/null +++ b/Core/PerformancePkg/Dp_App/Literals.c @@ -0,0 +1,22 @@ +/** @file + Definitions of ASCII string literals used by DP. + + Copyright (c) 2009 - 2017, 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_PEI[] = PEI_TOK; +CHAR8 const ALit_BDS[] = BDS_TOK; +CHAR8 const ALit_BdsTO[] = "BdsTimeOut"; +CHAR8 const ALit_PEIM[] = "PEIM"; diff --git a/Core/PerformancePkg/Dp_App/Literals.h b/Core/PerformancePkg/Dp_App/Literals.h new file mode 100644 index 0000000000..8aec09c024 --- /dev/null +++ b/Core/PerformancePkg/Dp_App/Literals.h @@ -0,0 +1,26 @@ +/** @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[]; + +#endif // _LITERALS_H_ diff --git a/Core/PerformancePkg/Include/Guid/PerformancePkgTokenSpace.h b/Core/PerformancePkg/Include/Guid/PerformancePkgTokenSpace.h new file mode 100644 index 0000000000..86dfe87d84 --- /dev/null +++ b/Core/PerformancePkg/Include/Guid/PerformancePkgTokenSpace.h @@ -0,0 +1,25 @@ +/** @file + GUID for PerformancePkg PCD Token Space + + Copyright (c) 2011, 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 _PERFORMANCEPKG_TOKEN_SPACE_GUID_H_ +#define _PERFORMANCEPKG_TOKEN_SPACE_GUID_H_ + +#define PERFORMANCEPKG_TOKEN_SPACE_GUID \ + { \ + 0x669346ef, 0xFDad, 0x4aeb, { 0x08, 0xa6, 0x21, 0x46, 0x2d, 0x3f, 0xef, 0x7d } \ + } + +extern EFI_GUID gPerformancePkgTokenSpaceGuid; + +#endif diff --git a/Core/PerformancePkg/Include/Guid/TscFrequency.h b/Core/PerformancePkg/Include/Guid/TscFrequency.h new file mode 100644 index 0000000000..f7c4a1c394 --- /dev/null +++ b/Core/PerformancePkg/Include/Guid/TscFrequency.h @@ -0,0 +1,25 @@ +/** @file + GUID for TSC frequency + + Copyright (c) 2011, 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 _TSC_FREQUENCY_GUID_H_ +#define _TSC_FREQUENCY_GUID_H_ + +#define EFI_TSC_FREQUENCY_GUID \ + { \ + 0xdba6a7e3, 0xbb57, 0x4be7, { 0x8a, 0xf8, 0xd5, 0x78, 0xdb, 0x7e, 0x56, 0x87 } \ + } + +extern EFI_GUID gEfiTscFrequencyGuid; + +#endif diff --git a/Core/PerformancePkg/Include/Ich/GenericIch.h b/Core/PerformancePkg/Include/Ich/GenericIch.h new file mode 100644 index 0000000000..697ea049ee --- /dev/null +++ b/Core/PerformancePkg/Include/Ich/GenericIch.h @@ -0,0 +1,55 @@ +/** @file + Generic definitions for registers in the Intel Ich devices. + + These definitions should work for any version of Ich. + + Copyright (c) 2009 - 2011, 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_ + +/** 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. +**/ +///@{ + +/// 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. +///@} + +/// IchAcpiCntr Control for the ICH's ACPI Counter. +///@{ +#define R_ICH_LPC_ACPI_BASE 0x40 +#define B_ICH_LPC_ACPI_BASE_BAR 0x0000FF80 +#define R_ICH_LPC_ACPI_CNT 0x44 +#define B_ICH_LPC_ACPI_CNT_ACPI_EN 0x80 +///@} + +/// 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/Core/PerformancePkg/Include/PerformanceTokens.h b/Core/PerformancePkg/Include/PerformanceTokens.h new file mode 100644 index 0000000000..bbbc48d776 --- /dev/null +++ b/Core/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/Core/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.c b/Core/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.c new file mode 100644 index 0000000000..c49f786641 --- /dev/null +++ b/Core/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.c @@ -0,0 +1,45 @@ +/** @file + A Base 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 - 2011, 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 "TscTimerLibInternal.h" + +/** Get TSC frequency. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalGetTscFrequency ( + VOID + ) +{ + return InternalCalculateTscFrequency (); +} + diff --git a/Core/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.inf b/Core/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.inf new file mode 100644 index 0000000000..9d622687b5 --- /dev/null +++ b/Core/PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.inf @@ -0,0 +1,59 @@ +## @file +# Base Timer Library which uses the Time Stamp Counter in the processor. +# +# Note: There will be 1ms penalty to get TSC frequency every time +# by waiting for 3579 clocks of the ACPI timer, or 1ms. +# +# Note: This library is a sample implementation that depends on chipset ACPI timer. +# It may not work on new generation chipset. PcAtChipsetPkg AcpiTimerLib is +# the generic timer library that can replace this one. +# +# 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 - 2015, 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 = BaseTscTimerLib + FILE_GUID = D29338B9-50FE-4e4f-B7D4-A150A2C1F4FB + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + TscTimerLibShare.c + BaseTscTimerLib.c + TscTimerLibInternal.h + + +[Packages] + MdePkg/MdePkg.dec + PerformancePkg/PerformancePkg.dec + + +[LibraryClasses] + PcdLib + PciLib + IoLib + BaseLib + +[Pcd.common] + gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress ## SOMETIMES_CONSUMES diff --git a/Core/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.c b/Core/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.c new file mode 100644 index 0000000000..c540d420da --- /dev/null +++ b/Core/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.c @@ -0,0 +1,102 @@ +/** @file + A Dxe 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 - 2011, 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 "TscTimerLibInternal.h" + +UINT64 mTscFrequency; + +/** The constructor function determines the actual TSC frequency. + + First, Get TSC frequency from system configuration table with TSC frequency GUID, + if the table is not found, install it. + This function will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +DxeTscTimerLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT64 *TscFrequency; + + TscFrequency = NULL; + // + // Get TSC frequency from system configuration table with TSC frequency GUID. + // + Status = EfiGetSystemConfigurationTable (&gEfiTscFrequencyGuid, (VOID **) &TscFrequency); + if (Status == EFI_SUCCESS) { + ASSERT (TscFrequency != NULL); + mTscFrequency = *TscFrequency; + return EFI_SUCCESS; + } + + // + // TSC frequency GUID system configuration table is not found, install it. + // + + Status = gBS->AllocatePool (EfiBootServicesData, sizeof (UINT64), (VOID **) &TscFrequency); + ASSERT_EFI_ERROR (Status); + + *TscFrequency = InternalCalculateTscFrequency (); + // + // TscFrequency now points to the number of TSC counts per second, install system configuration table for it. + // + gBS->InstallConfigurationTable (&gEfiTscFrequencyGuid, TscFrequency); + + mTscFrequency = *TscFrequency; + return EFI_SUCCESS; +} + +/** Get TSC frequency. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalGetTscFrequency ( + VOID + ) +{ + return mTscFrequency; +} + diff --git a/Core/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf b/Core/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf new file mode 100644 index 0000000000..16db5f73ea --- /dev/null +++ b/Core/PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf @@ -0,0 +1,64 @@ +## @file +# Dxe Timer Library which uses the Time Stamp Counter in the processor. +# +# Note: This library is a sample implementation that depends on chipset ACPI timer. +# It may not work on new generation chipset. PcAtChipsetPkg AcpiTimerLib is +# the generic timer library that can replace this one. +# +# 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 - 2015, 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 = DxeTscTimerLib + FILE_GUID = 95ab030f-b4fd-4ee4-92a5-9e04e87634d9 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE + + CONSTRUCTOR = DxeTscTimerLibConstructor + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + TscTimerLibShare.c + DxeTscTimerLib.c + TscTimerLibInternal.h + + +[Packages] + MdePkg/MdePkg.dec + PerformancePkg/PerformancePkg.dec + + +[LibraryClasses] + UefiBootServicesTableLib + PcdLib + PciLib + IoLib + BaseLib + UefiLib + DebugLib + +[Guids] + gEfiTscFrequencyGuid ## CONSUMES ## SystemTable + +[Pcd.common] + gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress ## SOMETIMES_CONSUMES diff --git a/Core/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.c b/Core/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.c new file mode 100644 index 0000000000..af3600b007 --- /dev/null +++ b/Core/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.c @@ -0,0 +1,76 @@ +/** @file + A Pei 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 - 2011, 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 "TscTimerLibInternal.h" + +/** Get TSC frequency from TSC frequency GUID HOB, if the HOB is not found, build it. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalGetTscFrequency ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + VOID *DataInHob; + UINT64 TscFrequency; + + // + // Get TSC frequency from TSC frequency GUID HOB. + // + GuidHob = GetFirstGuidHob (&gEfiTscFrequencyGuid); + if (GuidHob != NULL) { + DataInHob = GET_GUID_HOB_DATA (GuidHob); + TscFrequency = * (UINT64 *) DataInHob; + return TscFrequency; + } + + // + // TSC frequency GUID HOB is not found, build it. + // + + TscFrequency = InternalCalculateTscFrequency (); + // + // TscFrequency is now equal to the number of TSC counts per second, build GUID HOB for it. + // + BuildGuidDataHob ( + &gEfiTscFrequencyGuid, + &TscFrequency, + sizeof (UINT64) + ); + + return TscFrequency; +} + diff --git a/Core/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf b/Core/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf new file mode 100644 index 0000000000..68e34e0ede --- /dev/null +++ b/Core/PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf @@ -0,0 +1,60 @@ +## @file +# Pei Timer Library which uses the Time Stamp Counter in the processor. +# +# Note: This library is a sample implementation that depends on chipset ACPI timer. +# It may not work on new generation chipset. PcAtChipsetPkg AcpiTimerLib is +# the generic timer library that can replace this one. +# +# 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 - 2015, 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 = PeiTscTimerLib + FILE_GUID = 342C36C0-15DF-43b4-9EC9-FBF748BFB3D1 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib|PEIM PEI_CORE + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + TscTimerLibShare.c + PeiTscTimerLib.c + TscTimerLibInternal.h + + +[Packages] + MdePkg/MdePkg.dec + PerformancePkg/PerformancePkg.dec + + +[LibraryClasses] + PcdLib + PciLib + IoLib + BaseLib + HobLib + +[Guids] + gEfiTscFrequencyGuid ## PRODUCES ## HOB + +[Pcd.common] + gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress ## SOMETIMES_CONSUMES diff --git a/Core/PerformancePkg/Library/TscTimerLib/TscTimerLibInternal.h b/Core/PerformancePkg/Library/TscTimerLib/TscTimerLibInternal.h new file mode 100644 index 0000000000..a4ed0ebb31 --- /dev/null +++ b/Core/PerformancePkg/Library/TscTimerLib/TscTimerLibInternal.h @@ -0,0 +1,55 @@ +/** @file + Internal header file for TscTimerLib instances. + + Copyright (c) 2009 - 2011, 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 _TSC_TIMER_LIB_INTERNAL_H_ +#define _TSC_TIMER_LIB_INTERNAL_H_ + +#include + +#include +#include +#include +#include +#include + +/** Get TSC frequency. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalGetTscFrequency ( + VOID + ); + +/** Calculate 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. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalCalculateTscFrequency ( + VOID + ); + +#endif diff --git a/Core/PerformancePkg/Library/TscTimerLib/TscTimerLibShare.c b/Core/PerformancePkg/Library/TscTimerLib/TscTimerLibShare.c new file mode 100644 index 0000000000..161af00237 --- /dev/null +++ b/Core/PerformancePkg/Library/TscTimerLib/TscTimerLibShare.c @@ -0,0 +1,275 @@ +/** @file + The 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 - 2011, 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 "TscTimerLibInternal.h" + +/** Calculate 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. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalCalculateTscFrequency ( + VOID + ) +{ + UINT64 StartTSC; + UINT64 EndTSC; + UINT32 TimerAddr; + UINT32 Ticks; + UINT64 TscFrequency; + + // + // 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); + } + + // + // ACPI I/O space should be enabled now, locate the ACPI Timer. + // ACPI I/O base address maybe have be initialized by other driver with different value, + // So get it from PCI space directly. + // + TimerAddr = ((PciRead16 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_BASE))) & B_ICH_LPC_ACPI_BASE_BAR) + R_ACPI_PM1_TMR; + 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 + + TscFrequency = MultU64x32 ( + (EndTSC - StartTSC), // Number of TSC counts in 1ms + 1000 // Number of ms in a second + ); + + return TscFrequency; +} + +/** 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. + +**/ +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 ( + InternalGetTscFrequency (), + 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 ( + InternalGetTscFrequency (), + (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 InternalGetTscFrequency (); +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + UINT64 Frequency; + UINT64 NanoSeconds; + UINT64 Remainder; + INTN Shift; + + Frequency = GetPerformanceCounterProperties (NULL, NULL); + + // + // Ticks + // Time = --------- x 1,000,000,000 + // Frequency + // + NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u); + + // + // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit. + // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34, + // i.e. highest bit set in Remainder should <= 33. + // + Shift = MAX (0, HighBitSet64 (Remainder) - 33); + Remainder = RShiftU64 (Remainder, (UINTN) Shift); + Frequency = RShiftU64 (Frequency, (UINTN) Shift); + NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL); + + return NanoSeconds; +} diff --git a/Core/PerformancePkg/License.txt b/Core/PerformancePkg/License.txt new file mode 100644 index 0000000000..be68999be6 --- /dev/null +++ b/Core/PerformancePkg/License.txt @@ -0,0 +1,25 @@ +Copyright (c) 2012, Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Core/PerformancePkg/PerformancePkg.dec b/Core/PerformancePkg/PerformancePkg.dec new file mode 100644 index 0000000000..f39dc0bc95 --- /dev/null +++ b/Core/PerformancePkg/PerformancePkg.dec @@ -0,0 +1,37 @@ +## @file +# Build description file to generate Shell DP application and +# Performance Libraries. +# +# Copyright (c) 2009 - 2011, 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.2 + DEC_SPECIFICATION = 0x00010005 + +[Includes] + Include + +[Guids] + ## 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 }} + + ## Include/Guid/TscFrequency.h + gEfiTscFrequencyGuid = { 0xdba6a7e3, 0xbb57, 0x4be7, { 0x8a, 0xf8, 0xd5, 0x78, 0xdb, 0x7e, 0x56, 0x87 }} + +[PcdsFixedAtBuild] + ## 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/Core/PerformancePkg/PerformancePkg.dsc b/Core/PerformancePkg/PerformancePkg.dsc new file mode 100644 index 0000000000..95cc905cbb --- /dev/null +++ b/Core/PerformancePkg/PerformancePkg.dsc @@ -0,0 +1,68 @@ +## @file +# Build description file to generate Shell DP application. +# +# Copyright (c) 2009 - 2017, 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.2 + OUTPUT_DIRECTORY = Build/PerformancePkg + SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + 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 + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.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 + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + PerformanceLib|MdeModulePkg/Library/DxeSmmPerformanceLib/DxeSmmPerformanceLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + +[Components.IA32, Components.X64] + PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf + PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf + PerformancePkg/Library/TscTimerLib/BaseTscTimerLib.inf + +[Components] + PerformancePkg/Dp_App/Dp.inf + +[BuildOptions] + *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES -- cgit v1.2.3