]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiDpLib/Dp.c
ShellPkg/UefiDpLib: Fix a DP cumulative data issue
[mirror_edk2.git] / ShellPkg / Library / UefiDpLib / Dp.c
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 - 2013, 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"-n", TypeValue}, // -n # Number of records to display for A and R
83 {L"-t", TypeValue}, // -t # Threshold of interest
84 {NULL, TypeMax}
85 };
86
87 ///@}
88
89 /**
90 Display the trailing Verbose information.
91 **/
92 VOID
93 DumpStatistics( void )
94 {
95 EFI_STRING StringPtr;
96 EFI_STRING StringPtrUnknown;
97 StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);
98 StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
99 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
100 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
101 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), gDpHiiHandle, SummaryData.NumTrace);
102 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), gDpHiiHandle, SummaryData.NumIncomplete);
103 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), gDpHiiHandle, SummaryData.NumSummary);
104 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), gDpHiiHandle, SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);
105 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), gDpHiiHandle, SummaryData.NumPEIMs);
106 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), gDpHiiHandle, SummaryData.NumGlobal);
107 #if PROFILING_IMPLEMENTED
108 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPROFILE), gDpHiiHandle, SummaryData.NumProfile);
109 #endif // PROFILING_IMPLEMENTED
110 SHELL_FREE_NON_NULL (StringPtr);
111 SHELL_FREE_NON_NULL (StringPtrUnknown);
112 }
113
114 /**
115 Initialize the cumulative data.
116
117 **/
118 VOID
119 InitCumulativeData (
120 VOID
121 )
122 {
123 UINTN Index;
124
125 for (Index = 0; Index < NumCum; ++Index) {
126 CumData[Index].Count = 0;
127 CumData[Index].MinDur = PERF_MAXDUR;
128 CumData[Index].MaxDur = 0;
129 CumData[Index].Duration = 0;
130 }
131 }
132
133 /**
134 Dump performance data.
135
136 @param[in] ImageHandle The image handle.
137 @param[in] SystemTable The system table.
138
139 @retval EFI_SUCCESS Command completed successfully.
140 @retval EFI_INVALID_PARAMETER Command usage error.
141 @retval value Unknown error.
142
143 **/
144 SHELL_STATUS
145 EFIAPI
146 ShellCommandRunDp (
147 IN EFI_HANDLE ImageHandle,
148 IN EFI_SYSTEM_TABLE *SystemTable
149 )
150 {
151 LIST_ENTRY *ParamPackage;
152 CONST CHAR16 *CmdLineArg;
153 EFI_STATUS Status;
154
155 UINT64 Freq;
156 UINT64 Ticker;
157 UINTN Number2Display;
158
159 EFI_STRING StringPtr;
160 BOOLEAN SummaryMode;
161 BOOLEAN VerboseMode;
162 BOOLEAN AllMode;
163 BOOLEAN RawMode;
164 BOOLEAN TraceMode;
165 BOOLEAN ProfileMode;
166 BOOLEAN ExcludeMode;
167
168 StringPtr = NULL;
169 SummaryMode = FALSE;
170 VerboseMode = FALSE;
171 AllMode = FALSE;
172 RawMode = FALSE;
173 TraceMode = FALSE;
174 ProfileMode = FALSE;
175 ExcludeMode = FALSE;
176
177 // Get DP's entry time as soon as possible.
178 // This is used as the Shell-Phase end time.
179 //
180 Ticker = GetPerformanceCounter ();
181
182 //
183 // initialize the shell lib (we must be in non-auto-init...)
184 //
185 Status = ShellInitialize();
186 ASSERT_EFI_ERROR(Status);
187
188 Status = CommandInit();
189 ASSERT_EFI_ERROR(Status);
190
191 //
192 // Process Command Line arguments
193 //
194 Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);
195 if (EFI_ERROR(Status)) {
196 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), gDpHiiHandle);
197 return SHELL_INVALID_PARAMETER;
198 }
199
200 //
201 // Boolean options
202 //
203 VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v");
204 SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s"));
205 AllMode = ShellCommandLineGetFlag (ParamPackage, L"-A");
206 RawMode = ShellCommandLineGetFlag (ParamPackage, L"-R");
207 #if PROFILING_IMPLEMENTED
208 TraceMode = ShellCommandLineGetFlag (ParamPackage, L"-T");
209 ProfileMode = ShellCommandLineGetFlag (ParamPackage, L"-P");
210 #endif // PROFILING_IMPLEMENTED
211 ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x");
212 mShowId = ShellCommandLineGetFlag (ParamPackage, L"-i");
213
214 // Options with Values
215 CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-n");
216 if (CmdLineArg == NULL) {
217 Number2Display = DEFAULT_DISPLAYCOUNT;
218 } else {
219 Number2Display = StrDecimalToUintn(CmdLineArg);
220 if (Number2Display == 0) {
221 Number2Display = MAXIMUM_DISPLAYCOUNT;
222 }
223 }
224
225 CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t");
226 if (CmdLineArg == NULL) {
227 mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us
228 } else {
229 mInterestThreshold = StrDecimalToUint64(CmdLineArg);
230 }
231
232 // Handle Flag combinations and default behaviors
233 // If both TraceMode and ProfileMode are FALSE, set them both to TRUE
234 if ((! TraceMode) && (! ProfileMode)) {
235 TraceMode = TRUE;
236 #if PROFILING_IMPLEMENTED
237 ProfileMode = TRUE;
238 #endif // PROFILING_IMPLEMENTED
239 }
240
241 //
242 // Initialize the pre-defined cumulative data.
243 //
244 InitCumulativeData ();
245
246 //
247 // Timer specific processing
248 //
249 // Get the Performance counter characteristics:
250 // Freq = Frequency in Hz
251 // StartCount = Value loaded into the counter when it starts counting
252 // EndCount = Value counter counts to before it needs to be reset
253 //
254 Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);
255
256 // Convert the Frequency from Hz to KHz
257 TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);
258
259 // Determine in which direction the performance counter counts.
260 TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);
261
262 //
263 // Print header
264 //
265 // print DP's build version
266 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), gDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION);
267
268 // print performance timer characteristics
269 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), gDpHiiHandle, TimerInfo.Frequency);
270
271 if (VerboseMode && !RawMode) {
272 StringPtr = HiiGetString (gDpHiiHandle,
273 (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), NULL);
274 ASSERT (StringPtr != NULL);
275 // Print Timer count range and direction
276 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TIMER_PROPERTIES), gDpHiiHandle,
277 StringPtr,
278 TimerInfo.StartCount,
279 TimerInfo.EndCount
280 );
281 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), gDpHiiHandle, mInterestThreshold);
282 }
283
284 /****************************************************************************
285 **** Print Sections based on command line options
286 ****
287 **** Option modes have the following priority:
288 **** v Verbose -- Valid in combination with any other options
289 **** t Threshold -- Modifies All, Raw, and Cooked output
290 **** Default is 0 for All and Raw mode
291 **** Default is DEFAULT_THRESHOLD for "Cooked" mode
292 **** n Number2Display Used by All and Raw mode. Otherwise ignored.
293 **** A All -- R and S options are ignored
294 **** R Raw -- S option is ignored
295 **** s Summary -- Modifies "Cooked" output only
296 **** Cooked (Default)
297 ****
298 **** The All, Raw, and Cooked modes are modified by the Trace and Profile
299 **** options.
300 **** !T && !P := (0) Default, Both are displayed
301 **** T && !P := (1) Only Trace records are displayed
302 **** !T && P := (2) Only Profile records are displayed
303 **** T && P := (3) Same as Default, both are displayed
304 ****************************************************************************/
305 GatherStatistics();
306 if (AllMode) {
307 if (TraceMode) {
308 DumpAllTrace( Number2Display, ExcludeMode);
309 }
310 if (ProfileMode) {
311 DumpAllProfile( Number2Display, ExcludeMode);
312 }
313 } else if (RawMode) {
314 if (TraceMode) {
315 DumpRawTrace( Number2Display, ExcludeMode);
316 }
317 if (ProfileMode) {
318 DumpRawProfile( Number2Display, ExcludeMode);
319 }
320 } else {
321 //------------- Begin Cooked Mode Processing
322 if (TraceMode) {
323 ProcessPhases ( Ticker );
324 if ( ! SummaryMode) {
325 Status = ProcessHandles ( ExcludeMode);
326 if ( ! EFI_ERROR( Status)) {
327 ProcessPeims ();
328 ProcessGlobal ();
329 ProcessCumulative ();
330 }
331 }
332 }
333 if (ProfileMode) {
334 DumpAllProfile( Number2Display, ExcludeMode);
335 }
336 } //------------- End of Cooked Mode Processing
337 if ( VerboseMode || SummaryMode) {
338 DumpStatistics();
339 }
340
341 SHELL_FREE_NON_NULL (StringPtr);
342
343 return SHELL_SUCCESS;
344 }