• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Shell command for Displaying Performance Metrics.
3 
4   The Dp command reads performance data and presents it in several
5   different formats depending upon the needs of the user.  Both
6   Trace and Measured Profiling information is processed and presented.
7 
8   Dp uses the "PerformanceLib" to read the measurement records.
9   The "TimerLib" provides information about the timer, such as frequency,
10   beginning, and ending counter values.
11   Measurement records contain identifying information (Handle, Token, Module)
12   and start and end time values.
13   Dp uses this information to group records in different ways.  It also uses
14   timer information to calculate elapsed time for each measurement.
15 
16   Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
17   (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
18   This program and the accompanying materials
19   are licensed and made available under the terms and conditions of the BSD License
20   which accompanies this distribution.  The full text of the license may be found at
21   http://opensource.org/licenses/bsd-license.php
22 
23   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
24   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 **/
26 
27 #include "UefiDpLib.h"
28 #include <Guid/GlobalVariable.h>
29 #include <Library/PrintLib.h>
30 #include <Library/HandleParsingLib.h>
31 #include <Library/DevicePathLib.h>
32 
33 #include <Library/ShellLib.h>
34 #include <Library/BaseLib.h>
35 #include <Library/MemoryAllocationLib.h>
36 #include <Library/DebugLib.h>
37 #include <Library/TimerLib.h>
38 #include <Library/UefiLib.h>
39 
40 #include <Guid/Performance.h>
41 
42 #include "PerformanceTokens.h"
43 #include "Dp.h"
44 #include "Literals.h"
45 #include "DpInternal.h"
46 
47 //
48 /// Module-Global Variables
49 ///@{
50 CHAR16           mGaugeString[DP_GAUGE_STRING_LENGTH + 1];
51 CHAR16           mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];
52 UINT64           mInterestThreshold;
53 BOOLEAN          mShowId = FALSE;
54 
55 PERF_SUMMARY_DATA SummaryData = { 0 };    ///< Create the SummaryData structure and init. to ZERO.
56 
57 /// Timer Specific Information.
58 TIMER_INFO TimerInfo;
59 
60 /// Items for which to gather cumulative statistics.
61 PERF_CUM_DATA CumData[] = {
62   PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK),
63   PERF_INIT_CUM_DATA (START_IMAGE_TOK),
64   PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK),
65   PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK)
66 };
67 
68 /// Number of items for which we are gathering cumulative statistics.
69 UINT32 const      NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA);
70 
71 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
72   {L"-v", TypeFlag},   // -v   Verbose Mode
73   {L"-A", TypeFlag},   // -A   All, Cooked
74   {L"-R", TypeFlag},   // -R   RAW All
75   {L"-s", TypeFlag},   // -s   Summary
76 #if PROFILING_IMPLEMENTED
77   {L"-P", TypeFlag},   // -P   Dump Profile Data
78   {L"-T", TypeFlag},   // -T   Dump Trace Data
79 #endif // PROFILING_IMPLEMENTED
80   {L"-x", TypeFlag},   // -x   eXclude Cumulative Items
81   {L"-i", TypeFlag},   // -i   Display Identifier
82   {L"-c", TypeValue},  // -c   Display cumulative data.
83   {L"-n", TypeValue},  // -n # Number of records to display for A and R
84   {L"-t", TypeValue},  // -t # Threshold of interest
85   {NULL, TypeMax}
86   };
87 
88 ///@}
89 
90 /**
91    Display the trailing Verbose information.
92 **/
93 VOID
DumpStatistics(void)94 DumpStatistics( void )
95 {
96   EFI_STRING                StringPtr;
97   EFI_STRING                StringPtrUnknown;
98   StringPtr        = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);
99   StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
100   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
101               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
102   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), gDpHiiHandle,      SummaryData.NumTrace);
103   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), gDpHiiHandle, SummaryData.NumIncomplete);
104   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), gDpHiiHandle,     SummaryData.NumSummary);
105   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), gDpHiiHandle,    SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);
106   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), gDpHiiHandle,      SummaryData.NumPEIMs);
107   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), gDpHiiHandle,    SummaryData.NumGlobal);
108 #if PROFILING_IMPLEMENTED
109   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPROFILE), gDpHiiHandle,    SummaryData.NumProfile);
110 #endif // PROFILING_IMPLEMENTED
111   SHELL_FREE_NON_NULL (StringPtr);
112   SHELL_FREE_NON_NULL (StringPtrUnknown);
113 }
114 
115 /**
116   Initialize the cumulative data.
117 
118 **/
119 VOID
InitCumulativeData(VOID)120 InitCumulativeData (
121   VOID
122   )
123 {
124   UINTN                             Index;
125 
126   for (Index = 0; Index < NumCum; ++Index) {
127     CumData[Index].Count = 0;
128     CumData[Index].MinDur = PERF_MAXDUR;
129     CumData[Index].MaxDur = 0;
130     CumData[Index].Duration = 0;
131   }
132 }
133 
134 /**
135   Dump performance data.
136 
137   @param[in]  ImageHandle     The image handle.
138   @param[in]  SystemTable     The system table.
139 
140   @retval EFI_SUCCESS            Command completed successfully.
141   @retval EFI_INVALID_PARAMETER  Command usage error.
142   @retval value                  Unknown error.
143 
144 **/
145 SHELL_STATUS
146 EFIAPI
ShellCommandRunDp(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)147 ShellCommandRunDp (
148   IN EFI_HANDLE               ImageHandle,
149   IN EFI_SYSTEM_TABLE         *SystemTable
150   )
151 {
152   LIST_ENTRY                *ParamPackage;
153   CONST CHAR16              *CmdLineArg;
154   EFI_STATUS                Status;
155 
156   UINT64                    Freq;
157   UINT64                    Ticker;
158   UINTN                     Number2Display;
159 
160   EFI_STRING                StringPtr;
161   BOOLEAN                   SummaryMode;
162   BOOLEAN                   VerboseMode;
163   BOOLEAN                   AllMode;
164   BOOLEAN                   RawMode;
165   BOOLEAN                   TraceMode;
166   BOOLEAN                   ProfileMode;
167   BOOLEAN                   ExcludeMode;
168   BOOLEAN                   CumulativeMode;
169   CONST CHAR16              *CustomCumulativeToken;
170   PERF_CUM_DATA             *CustomCumulativeData;
171 
172   StringPtr   = NULL;
173   SummaryMode = FALSE;
174   VerboseMode = FALSE;
175   AllMode     = FALSE;
176   RawMode     = FALSE;
177   TraceMode   = FALSE;
178   ProfileMode = FALSE;
179   ExcludeMode = FALSE;
180   CumulativeMode = FALSE;
181   CustomCumulativeData = NULL;
182 
183   // Get DP's entry time as soon as possible.
184   // This is used as the Shell-Phase end time.
185   //
186   Ticker  = GetPerformanceCounter ();
187 
188   //
189   // initialize the shell lib (we must be in non-auto-init...)
190   //
191   Status = ShellInitialize();
192   ASSERT_EFI_ERROR(Status);
193 
194   Status = CommandInit();
195   ASSERT_EFI_ERROR(Status);
196 
197   //
198   // Process Command Line arguments
199   //
200   Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);
201   if (EFI_ERROR(Status)) {
202     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), gDpHiiHandle);
203     return SHELL_INVALID_PARAMETER;
204   }
205 
206   //
207   // Boolean options
208   //
209   VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v");
210   SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s"));
211   AllMode     = ShellCommandLineGetFlag (ParamPackage, L"-A");
212   RawMode     = ShellCommandLineGetFlag (ParamPackage, L"-R");
213 #if PROFILING_IMPLEMENTED
214   TraceMode   = ShellCommandLineGetFlag (ParamPackage, L"-T");
215   ProfileMode = ShellCommandLineGetFlag (ParamPackage, L"-P");
216 #endif  // PROFILING_IMPLEMENTED
217   ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x");
218   mShowId     = ShellCommandLineGetFlag (ParamPackage, L"-i");
219   CumulativeMode = ShellCommandLineGetFlag (ParamPackage, L"-c");
220 
221   // Options with Values
222   CmdLineArg  = ShellCommandLineGetValue (ParamPackage, L"-n");
223   if (CmdLineArg == NULL) {
224     Number2Display = DEFAULT_DISPLAYCOUNT;
225   } else {
226     Number2Display = StrDecimalToUintn(CmdLineArg);
227     if (Number2Display == 0) {
228       Number2Display = MAXIMUM_DISPLAYCOUNT;
229     }
230   }
231 
232   CmdLineArg  = ShellCommandLineGetValue (ParamPackage, L"-t");
233   if (CmdLineArg == NULL) {
234     mInterestThreshold = DEFAULT_THRESHOLD;  // 1ms := 1,000 us
235   } else {
236     mInterestThreshold = StrDecimalToUint64(CmdLineArg);
237   }
238 
239   // Handle Flag combinations and default behaviors
240   // If both TraceMode and ProfileMode are FALSE, set them both to TRUE
241   if ((! TraceMode) && (! ProfileMode)) {
242     TraceMode   = TRUE;
243 #if PROFILING_IMPLEMENTED
244     ProfileMode = TRUE;
245 #endif  // PROFILING_IMPLEMENTED
246   }
247 
248   //
249   // Initialize the pre-defined cumulative data.
250   //
251   InitCumulativeData ();
252 
253   //
254   // Init the custom cumulative data.
255   //
256   CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, L"-c");
257   if (CustomCumulativeToken != NULL) {
258     CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));
259     ASSERT (CustomCumulativeData != NULL);
260     CustomCumulativeData->MinDur = 0;
261     CustomCumulativeData->MaxDur = 0;
262     CustomCumulativeData->Count  = 0;
263     CustomCumulativeData->Duration = 0;
264     CustomCumulativeData->Name   = AllocateZeroPool (StrLen (CustomCumulativeToken) + 1);
265     UnicodeStrToAsciiStr (CustomCumulativeToken, CustomCumulativeData->Name);
266   }
267 
268   //
269   // Timer specific processing
270   //
271   // Get the Performance counter characteristics:
272   //          Freq = Frequency in Hz
273   //    StartCount = Value loaded into the counter when it starts counting
274   //      EndCount = Value counter counts to before it needs to be reset
275   //
276   Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);
277 
278   // Convert the Frequency from Hz to KHz
279   TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);
280 
281   // Determine in which direction the performance counter counts.
282   TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);
283 
284   //
285   // Print header
286   //
287   // print DP's build version
288   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), gDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION);
289 
290   // print performance timer characteristics
291   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), gDpHiiHandle, TimerInfo.Frequency);
292 
293   if (VerboseMode && !RawMode) {
294     StringPtr = HiiGetString (gDpHiiHandle,
295                   (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), NULL);
296     ASSERT (StringPtr != NULL);
297     // Print Timer count range and direction
298     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TIMER_PROPERTIES), gDpHiiHandle,
299                 StringPtr,
300                 TimerInfo.StartCount,
301                 TimerInfo.EndCount
302                 );
303     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), gDpHiiHandle, mInterestThreshold);
304   }
305 
306 /****************************************************************************
307 ****            Print Sections based on command line options
308 ****
309 ****  Option modes have the following priority:
310 ****    v Verbose     --  Valid in combination with any other options
311 ****    t Threshold   --  Modifies All, Raw, and Cooked output
312 ****                      Default is 0 for All and Raw mode
313 ****                      Default is DEFAULT_THRESHOLD for "Cooked" mode
314 ****    n Number2Display  Used by All and Raw mode.  Otherwise ignored.
315 ****    A All         --  R and S options are ignored
316 ****    R Raw         --  S option is ignored
317 ****    s Summary     --  Modifies "Cooked" output only
318 ****    Cooked (Default)
319 ****
320 ****  The All, Raw, and Cooked modes are modified by the Trace and Profile
321 ****  options.
322 ****    !T && !P  := (0) Default, Both are displayed
323 ****     T && !P  := (1) Only Trace records are displayed
324 ****    !T &&  P  := (2) Only Profile records are displayed
325 ****     T &&  P  := (3) Same as Default, both are displayed
326 ****************************************************************************/
327   GatherStatistics (CustomCumulativeData);
328   if (CumulativeMode) {
329     ProcessCumulative (CustomCumulativeData);
330   } else if (AllMode) {
331     if (TraceMode) {
332       DumpAllTrace( Number2Display, ExcludeMode);
333     }
334     if (ProfileMode) {
335       DumpAllProfile( Number2Display, ExcludeMode);
336     }
337   } else if (RawMode) {
338     if (TraceMode) {
339       DumpRawTrace( Number2Display, ExcludeMode);
340     }
341     if (ProfileMode) {
342       DumpRawProfile( Number2Display, ExcludeMode);
343     }
344   } else {
345     //------------- Begin Cooked Mode Processing
346     if (TraceMode) {
347       ProcessPhases ( Ticker );
348       if ( ! SummaryMode) {
349         Status = ProcessHandles ( ExcludeMode);
350         if ( ! EFI_ERROR( Status)) {
351           ProcessPeims ();
352           ProcessGlobal ();
353           ProcessCumulative (NULL);
354         }
355       }
356     }
357     if (ProfileMode) {
358       DumpAllProfile( Number2Display, ExcludeMode);
359     }
360   } //------------- End of Cooked Mode Processing
361   if ( VerboseMode || SummaryMode) {
362     DumpStatistics();
363   }
364 
365   SHELL_FREE_NON_NULL (StringPtr);
366   if (CustomCumulativeData != NULL) {
367     SHELL_FREE_NON_NULL (CustomCumulativeData->Name);
368   }
369   SHELL_FREE_NON_NULL (CustomCumulativeData);
370 
371   return SHELL_SUCCESS;
372 }
373