]>
Commit | Line | Data |
---|---|---|
1d112229 RN |
1 | /** @file |
2 | This file include the file which can help to get the system | |
3 | performance, all the function will only include if the performance | |
4 | switch is set. | |
5 | ||
6 | Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR> | |
7 | This program and the accompanying materials | |
8 | are licensed and made available under the terms and conditions of the BSD License | |
9 | which accompanies this distribution. The full text of the license may be found at | |
10 | http://opensource.org/licenses/bsd-license.php | |
11 | ||
12 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
13 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
14 | ||
15 | **/ | |
16 | ||
17 | #include "InternalBm.h" | |
18 | ||
19 | PERF_HEADER mBmPerfHeader; | |
20 | PERF_DATA mBmPerfData; | |
21 | EFI_PHYSICAL_ADDRESS mBmAcpiLowMemoryBase = 0x0FFFFFFFFULL; | |
22 | ||
23 | /** | |
24 | Get the short verion of PDB file name to be | |
25 | used in performance data logging. | |
26 | ||
27 | @param PdbFileName The long PDB file name. | |
28 | @param GaugeString The output string to be logged by performance logger. | |
29 | ||
30 | **/ | |
31 | VOID | |
32 | BmGetShortPdbFileName ( | |
33 | IN CONST CHAR8 *PdbFileName, | |
34 | OUT CHAR8 *GaugeString | |
35 | ) | |
36 | { | |
37 | UINTN Index; | |
38 | UINTN Index1; | |
39 | UINTN StartIndex; | |
40 | UINTN EndIndex; | |
41 | ||
42 | if (PdbFileName == NULL) { | |
43 | AsciiStrCpy (GaugeString, " "); | |
44 | } else { | |
45 | StartIndex = 0; | |
46 | for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++) | |
47 | ; | |
48 | ||
49 | for (Index = 0; PdbFileName[Index] != 0; Index++) { | |
50 | if (PdbFileName[Index] == '\\') { | |
51 | StartIndex = Index + 1; | |
52 | } | |
53 | ||
54 | if (PdbFileName[Index] == '.') { | |
55 | EndIndex = Index; | |
56 | } | |
57 | } | |
58 | ||
59 | Index1 = 0; | |
60 | for (Index = StartIndex; Index < EndIndex; Index++) { | |
61 | GaugeString[Index1] = PdbFileName[Index]; | |
62 | Index1++; | |
63 | if (Index1 == PERF_TOKEN_LENGTH - 1) { | |
64 | break; | |
65 | } | |
66 | } | |
67 | ||
68 | GaugeString[Index1] = 0; | |
69 | } | |
70 | ||
71 | return ; | |
72 | } | |
73 | ||
74 | /** | |
75 | Get the name from the Driver handle, which can be a handle with | |
76 | EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed. | |
77 | This name can be used in performance data logging. | |
78 | ||
79 | @param Handle Driver handle. | |
80 | @param GaugeString The output string to be logged by performance logger. | |
81 | ||
82 | **/ | |
83 | VOID | |
84 | BmGetNameFromHandle ( | |
85 | IN EFI_HANDLE Handle, | |
86 | OUT CHAR8 *GaugeString | |
87 | ) | |
88 | { | |
89 | EFI_STATUS Status; | |
90 | EFI_LOADED_IMAGE_PROTOCOL *Image; | |
91 | CHAR8 *PdbFileName; | |
92 | EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; | |
93 | ||
94 | AsciiStrCpy (GaugeString, " "); | |
95 | ||
96 | // | |
97 | // Get handle name from image protocol | |
98 | // | |
99 | Status = gBS->HandleProtocol ( | |
100 | Handle, | |
101 | &gEfiLoadedImageProtocolGuid, | |
102 | (VOID **) &Image | |
103 | ); | |
104 | ||
105 | if (EFI_ERROR (Status)) { | |
106 | Status = gBS->OpenProtocol ( | |
107 | Handle, | |
108 | &gEfiDriverBindingProtocolGuid, | |
109 | (VOID **) &DriverBinding, | |
110 | NULL, | |
111 | NULL, | |
112 | EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
113 | ); | |
114 | if (EFI_ERROR (Status)) { | |
115 | return ; | |
116 | } | |
117 | // | |
118 | // Get handle name from image protocol | |
119 | // | |
120 | Status = gBS->HandleProtocol ( | |
121 | DriverBinding->ImageHandle, | |
122 | &gEfiLoadedImageProtocolGuid, | |
123 | (VOID **) &Image | |
124 | ); | |
125 | } | |
126 | ||
127 | PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase); | |
128 | ||
129 | if (PdbFileName != NULL) { | |
130 | BmGetShortPdbFileName (PdbFileName, GaugeString); | |
131 | } | |
132 | ||
133 | return ; | |
134 | } | |
135 | ||
136 | /** | |
137 | ||
138 | Writes performance data of booting into the allocated memory. | |
139 | OS can process these records. | |
140 | ||
141 | @param Event The triggered event. | |
142 | @param Context Context for this event. | |
143 | ||
144 | **/ | |
145 | VOID | |
146 | EFIAPI | |
147 | BmWriteBootToOsPerformanceData ( | |
148 | IN EFI_EVENT Event, | |
149 | IN VOID *Context | |
150 | ) | |
151 | { | |
152 | EFI_STATUS Status; | |
153 | UINT32 LimitCount; | |
154 | EFI_HANDLE *Handles; | |
155 | UINTN NoHandles; | |
156 | CHAR8 GaugeString[PERF_TOKEN_LENGTH]; | |
157 | UINT8 *Ptr; | |
158 | UINT32 Index; | |
159 | UINT64 Ticker; | |
160 | UINT64 Freq; | |
161 | UINT32 Duration; | |
162 | UINTN LogEntryKey; | |
163 | CONST VOID *Handle; | |
164 | CONST CHAR8 *Token; | |
165 | CONST CHAR8 *Module; | |
166 | UINT64 StartTicker; | |
167 | UINT64 EndTicker; | |
168 | UINT64 StartValue; | |
169 | UINT64 EndValue; | |
170 | BOOLEAN CountUp; | |
171 | UINTN EntryIndex; | |
172 | UINTN NumPerfEntries; | |
173 | // | |
174 | // List of flags indicating PerfEntry contains DXE handle | |
175 | // | |
176 | BOOLEAN *PerfEntriesAsDxeHandle; | |
177 | UINTN VarSize; | |
178 | ||
179 | // | |
180 | // Record the performance data for End of BDS | |
181 | // | |
182 | PERF_END(NULL, "BDS", NULL, 0); | |
183 | ||
184 | // | |
185 | // Retrieve time stamp count as early as possible | |
186 | // | |
187 | Ticker = GetPerformanceCounter (); | |
188 | ||
189 | Freq = GetPerformanceCounterProperties (&StartValue, &EndValue); | |
190 | ||
191 | Freq = DivU64x32 (Freq, 1000); | |
192 | ||
193 | mBmPerfHeader.CpuFreq = Freq; | |
194 | ||
195 | // | |
196 | // Record BDS raw performance data | |
197 | // | |
198 | if (EndValue >= StartValue) { | |
199 | mBmPerfHeader.BDSRaw = Ticker - StartValue; | |
200 | CountUp = TRUE; | |
201 | } else { | |
202 | mBmPerfHeader.BDSRaw = StartValue - Ticker; | |
203 | CountUp = FALSE; | |
204 | } | |
205 | ||
206 | if (mBmAcpiLowMemoryBase == 0x0FFFFFFFF) { | |
207 | VarSize = sizeof (EFI_PHYSICAL_ADDRESS); | |
208 | Status = gRT->GetVariable ( | |
209 | L"PerfDataMemAddr", | |
210 | &gPerformanceProtocolGuid, | |
211 | NULL, | |
212 | &VarSize, | |
213 | &mBmAcpiLowMemoryBase | |
214 | ); | |
215 | if (EFI_ERROR (Status)) { | |
216 | // | |
217 | // Fail to get the variable, return. | |
218 | // | |
219 | return; | |
220 | } | |
221 | } | |
222 | ||
223 | // | |
224 | // Put Detailed performance data into memory | |
225 | // | |
226 | Handles = NULL; | |
227 | Status = gBS->LocateHandleBuffer ( | |
228 | AllHandles, | |
229 | NULL, | |
230 | NULL, | |
231 | &NoHandles, | |
232 | &Handles | |
233 | ); | |
234 | if (EFI_ERROR (Status)) { | |
235 | return ; | |
236 | } | |
237 | ||
238 | Ptr = (UINT8 *) ((UINT32) mBmAcpiLowMemoryBase + sizeof (PERF_HEADER)); | |
239 | LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA); | |
240 | ||
241 | NumPerfEntries = 0; | |
242 | LogEntryKey = 0; | |
243 | while ((LogEntryKey = GetPerformanceMeasurement ( | |
244 | LogEntryKey, | |
245 | &Handle, | |
246 | &Token, | |
247 | &Module, | |
248 | &StartTicker, | |
249 | &EndTicker)) != 0) { | |
250 | NumPerfEntries++; | |
251 | } | |
252 | PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN)); | |
253 | ASSERT (PerfEntriesAsDxeHandle != NULL); | |
254 | ||
255 | // | |
256 | // Get DXE drivers performance | |
257 | // | |
258 | for (Index = 0; Index < NoHandles; Index++) { | |
259 | Ticker = 0; | |
260 | LogEntryKey = 0; | |
261 | EntryIndex = 0; | |
262 | while ((LogEntryKey = GetPerformanceMeasurement ( | |
263 | LogEntryKey, | |
264 | &Handle, | |
265 | &Token, | |
266 | &Module, | |
267 | &StartTicker, | |
268 | &EndTicker)) != 0) { | |
269 | if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) { | |
270 | PerfEntriesAsDxeHandle[EntryIndex] = TRUE; | |
271 | } | |
272 | EntryIndex++; | |
273 | if ((Handle == Handles[Index]) && (EndTicker != 0)) { | |
274 | if (StartTicker == 1) { | |
275 | StartTicker = StartValue; | |
276 | } | |
277 | if (EndTicker == 1) { | |
278 | EndTicker = StartValue; | |
279 | } | |
280 | Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker); | |
281 | } | |
282 | } | |
283 | ||
284 | Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq); | |
285 | ||
286 | if (Duration > 0) { | |
287 | ||
288 | BmGetNameFromHandle (Handles[Index], GaugeString); | |
289 | ||
290 | AsciiStrCpy (mBmPerfData.Token, GaugeString); | |
291 | mBmPerfData.Duration = Duration; | |
292 | ||
293 | CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA)); | |
294 | Ptr += sizeof (PERF_DATA); | |
295 | ||
296 | mBmPerfHeader.Count++; | |
297 | if (mBmPerfHeader.Count == LimitCount) { | |
298 | goto Done; | |
299 | } | |
300 | } | |
301 | } | |
302 | ||
303 | // | |
304 | // Get inserted performance data | |
305 | // | |
306 | LogEntryKey = 0; | |
307 | EntryIndex = 0; | |
308 | while ((LogEntryKey = GetPerformanceMeasurement ( | |
309 | LogEntryKey, | |
310 | &Handle, | |
311 | &Token, | |
312 | &Module, | |
313 | &StartTicker, | |
314 | &EndTicker)) != 0) { | |
315 | if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) { | |
316 | ||
317 | ZeroMem (&mBmPerfData, sizeof (PERF_DATA)); | |
318 | ||
319 | AsciiStrnCpy (mBmPerfData.Token, Token, PERF_TOKEN_LENGTH); | |
320 | if (StartTicker == 1) { | |
321 | StartTicker = StartValue; | |
322 | } | |
323 | if (EndTicker == 1) { | |
324 | EndTicker = StartValue; | |
325 | } | |
326 | Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker); | |
327 | ||
328 | mBmPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq); | |
329 | ||
330 | CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA)); | |
331 | Ptr += sizeof (PERF_DATA); | |
332 | ||
333 | mBmPerfHeader.Count++; | |
334 | if (mBmPerfHeader.Count == LimitCount) { | |
335 | goto Done; | |
336 | } | |
337 | } | |
338 | EntryIndex++; | |
339 | } | |
340 | ||
341 | Done: | |
342 | ||
343 | FreePool (Handles); | |
344 | FreePool (PerfEntriesAsDxeHandle); | |
345 | ||
346 | mBmPerfHeader.Signiture = PERFORMANCE_SIGNATURE; | |
347 | ||
348 | // | |
349 | // Put performance data to Reserved memory | |
350 | // | |
351 | CopyMem ( | |
352 | (UINTN *) (UINTN) mBmAcpiLowMemoryBase, | |
353 | &mBmPerfHeader, | |
354 | sizeof (PERF_HEADER) | |
355 | ); | |
356 | ||
357 | return ; | |
358 | } |