878ddf1f |
1 | /*++\r |
2 | \r |
fa332de7 |
3 | Copyright (c) 2006 - 2007, Intel Corporation\r |
4 | All rights reserved. This program and the accompanying materials\r |
5 | are licensed and made available under the terms and conditions of the BSD License\r |
6 | which accompanies this distribution. The full text of the license may be found at\r |
7 | http://opensource.org/licenses/bsd-license.php\r |
8 | \r |
9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r |
10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r |
878ddf1f |
11 | \r |
12 | Module Name:\r |
13 | \r |
14 | Performance.c\r |
15 | \r |
16 | Abstract:\r |
17 | \r |
18 | This file include the file which can help to get the system\r |
19 | performance, all the function will only include if the performance\r |
20 | switch is set.\r |
21 | \r |
22 | --*/\r |
23 | \r |
24 | #include "Performance.h"\r |
25 | \r |
878ddf1f |
26 | \r |
27 | STATIC\r |
28 | VOID\r |
29 | GetShortPdbFileName (\r |
30 | CHAR8 *PdbFileName,\r |
31 | CHAR8 *GaugeString\r |
32 | )\r |
33 | /*++\r |
34 | \r |
35 | Routine Description:\r |
fa332de7 |
36 | \r |
878ddf1f |
37 | Arguments:\r |
38 | \r |
39 | Returns:\r |
40 | \r |
41 | --*/\r |
42 | {\r |
43 | UINTN Index;\r |
44 | UINTN Index1;\r |
45 | UINTN StartIndex;\r |
46 | UINTN EndIndex;\r |
47 | \r |
48 | if (PdbFileName == NULL) {\r |
49 | AsciiStrCpy (GaugeString, " ");\r |
50 | } else {\r |
51 | StartIndex = 0;\r |
52 | for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r |
53 | ;\r |
54 | \r |
55 | for (Index = 0; PdbFileName[Index] != 0; Index++) {\r |
56 | if (PdbFileName[Index] == '\\') {\r |
57 | StartIndex = Index + 1;\r |
58 | }\r |
59 | \r |
60 | if (PdbFileName[Index] == '.') {\r |
61 | EndIndex = Index;\r |
62 | }\r |
63 | }\r |
64 | \r |
65 | Index1 = 0;\r |
66 | for (Index = StartIndex; Index < EndIndex; Index++) {\r |
67 | GaugeString[Index1] = PdbFileName[Index];\r |
68 | Index1++;\r |
69 | if (Index1 == PERF_TOKEN_LENGTH - 1) {\r |
70 | break;\r |
71 | }\r |
72 | }\r |
73 | \r |
74 | GaugeString[Index1] = 0;\r |
75 | }\r |
76 | \r |
77 | return ;\r |
78 | }\r |
79 | \r |
2ce31132 |
80 | \r |
81 | \r |
878ddf1f |
82 | STATIC\r |
83 | CHAR8 *\r |
84 | GetPdbPath (\r |
85 | VOID *ImageBase\r |
86 | )\r |
87 | /*++\r |
88 | \r |
89 | Routine Description:\r |
90 | \r |
91 | Located PDB path name in PE image\r |
92 | \r |
93 | Arguments:\r |
94 | \r |
95 | ImageBase - base of PE to search\r |
96 | \r |
97 | Returns:\r |
98 | \r |
99 | Pointer into image at offset of PDB file name if PDB file name is found,\r |
100 | Otherwise a pointer to an empty string.\r |
101 | \r |
102 | --*/\r |
103 | {\r |
2ce31132 |
104 | PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r |
105 | \r |
106 | ZeroMem (&ImageContext, sizeof (ImageContext));\r |
107 | ImageContext.Handle = ImageBase;\r |
108 | ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r |
878ddf1f |
109 | \r |
2ce31132 |
110 | PeCoffLoaderGetImageInfo (&ImageContext);\r |
111 | \r |
112 | return ImageContext.PdbPointer;\r |
878ddf1f |
113 | }\r |
114 | \r |
2ce31132 |
115 | \r |
878ddf1f |
116 | STATIC\r |
117 | VOID\r |
118 | GetNameFromHandle (\r |
119 | IN EFI_HANDLE Handle,\r |
120 | OUT CHAR8 *GaugeString\r |
121 | )\r |
122 | {\r |
123 | EFI_STATUS Status;\r |
124 | EFI_LOADED_IMAGE_PROTOCOL *Image;\r |
125 | CHAR8 *PdbFileName;\r |
126 | EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r |
127 | \r |
128 | AsciiStrCpy (GaugeString, " ");\r |
129 | \r |
130 | //\r |
131 | // Get handle name from image protocol\r |
132 | //\r |
133 | Status = gBS->HandleProtocol (\r |
134 | Handle,\r |
135 | &gEfiLoadedImageProtocolGuid,\r |
136 | &Image\r |
137 | );\r |
138 | \r |
139 | if (EFI_ERROR (Status)) {\r |
140 | Status = gBS->OpenProtocol (\r |
141 | Handle,\r |
142 | &gEfiDriverBindingProtocolGuid,\r |
143 | (VOID **) &DriverBinding,\r |
144 | NULL,\r |
145 | NULL,\r |
146 | EFI_OPEN_PROTOCOL_GET_PROTOCOL\r |
147 | );\r |
148 | if (EFI_ERROR (Status)) {\r |
149 | return ;\r |
150 | }\r |
151 | //\r |
152 | // Get handle name from image protocol\r |
153 | //\r |
154 | Status = gBS->HandleProtocol (\r |
155 | DriverBinding->ImageHandle,\r |
156 | &gEfiLoadedImageProtocolGuid,\r |
157 | &Image\r |
158 | );\r |
159 | }\r |
160 | \r |
161 | PdbFileName = GetPdbPath (Image->ImageBase);\r |
162 | \r |
163 | if (PdbFileName != NULL) {\r |
164 | GetShortPdbFileName (PdbFileName, GaugeString);\r |
165 | }\r |
166 | \r |
167 | return ;\r |
168 | }\r |
169 | \r |
170 | \r |
171 | \r |
172 | VOID\r |
173 | WriteBootToOsPerformanceData (\r |
174 | VOID\r |
175 | )\r |
176 | /*++\r |
177 | \r |
178 | Routine Description:\r |
fa332de7 |
179 | \r |
878ddf1f |
180 | Allocates a block of memory and writes performance data of booting to OS into it.\r |
181 | \r |
182 | Arguments:\r |
fa332de7 |
183 | \r |
878ddf1f |
184 | None\r |
fa332de7 |
185 | \r |
878ddf1f |
186 | Returns:\r |
187 | \r |
188 | None\r |
189 | \r |
190 | --*/\r |
191 | {\r |
192 | EFI_STATUS Status;\r |
193 | EFI_CPU_ARCH_PROTOCOL *Cpu;\r |
194 | EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase;\r |
195 | UINT32 mAcpiLowMemoryLength;\r |
196 | UINT32 LimitCount;\r |
197 | PERF_HEADER mPerfHeader;\r |
198 | PERF_DATA mPerfData;\r |
199 | EFI_HANDLE *Handles;\r |
200 | UINTN NoHandles;\r |
201 | CHAR8 GaugeString[PERF_TOKEN_LENGTH];\r |
202 | UINT8 *Ptr;\r |
203 | UINT32 mIndex;\r |
204 | UINT64 Ticker;\r |
205 | UINT64 Freq;\r |
206 | UINT32 Duration;\r |
207 | UINT64 CurrentTicker;\r |
208 | UINT64 TimerPeriod;\r |
209 | UINTN LogEntryKey;\r |
210 | CONST VOID *Handle;\r |
211 | CONST CHAR8 *Token;\r |
212 | CONST CHAR8 *Module;\r |
213 | UINT64 StartTicker;\r |
214 | UINT64 EndTicker;\r |
215 | \r |
216 | //\r |
217 | // Retrive time stamp count as early as possilbe\r |
218 | //\r |
219 | Ticker = AsmReadTsc ();\r |
220 | \r |
221 | //\r |
222 | // Allocate a block of memory that contain performance data to OS\r |
223 | //\r |
cb44bbdb |
224 | mAcpiLowMemoryBase = 0xFFFFFFFF;\r |
878ddf1f |
225 | Status = gBS->AllocatePages (\r |
cb44bbdb |
226 | AllocateMaxAddress,\r |
227 | EfiReservedMemoryType,\r |
878ddf1f |
228 | 4,\r |
229 | &mAcpiLowMemoryBase\r |
230 | );\r |
231 | if (EFI_ERROR (Status)) {\r |
232 | return ;\r |
233 | }\r |
234 | \r |
cb44bbdb |
235 | mAcpiLowMemoryLength = EFI_PAGES_TO_SIZE(4);\r |
878ddf1f |
236 | \r |
237 | Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));\r |
238 | LimitCount = (mAcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);\r |
239 | \r |
240 | //\r |
241 | // Initialize performance data structure\r |
242 | //\r |
243 | ZeroMem (&mPerfHeader, sizeof (PERF_HEADER));\r |
244 | \r |
245 | //\r |
246 | // Get CPU frequency\r |
247 | //\r |
248 | Status = gBS->LocateProtocol (\r |
249 | &gEfiCpuArchProtocolGuid,\r |
250 | NULL,\r |
251 | &Cpu\r |
252 | );\r |
253 | if (EFI_ERROR (Status)) {\r |
cb44bbdb |
254 | gBS->FreePages (mAcpiLowMemoryBase, 4);\r |
878ddf1f |
255 | return ;\r |
256 | }\r |
257 | //\r |
258 | // Get Cpu Frequency\r |
259 | //\r |
260 | Status = Cpu->GetTimerValue (Cpu, 0, &(CurrentTicker), &TimerPeriod);\r |
261 | if (EFI_ERROR (Status)) {\r |
cb44bbdb |
262 | gBS->FreePages (mAcpiLowMemoryBase, 4);\r |
878ddf1f |
263 | return ;\r |
264 | }\r |
265 | \r |
266 | Freq = DivU64x32 (1000000000000, (UINTN) TimerPeriod);\r |
267 | \r |
268 | mPerfHeader.CpuFreq = Freq;\r |
269 | \r |
270 | //\r |
271 | // Record BDS raw performance data\r |
272 | //\r |
273 | mPerfHeader.BDSRaw = Ticker;\r |
274 | \r |
275 | //\r |
276 | // Put Detailed performance data into memory\r |
277 | //\r |
278 | Handles = NULL;\r |
279 | Status = gBS->LocateHandleBuffer (\r |
280 | AllHandles,\r |
281 | NULL,\r |
282 | NULL,\r |
283 | &NoHandles,\r |
284 | &Handles\r |
285 | );\r |
286 | if (EFI_ERROR (Status)) {\r |
cb44bbdb |
287 | gBS->FreePages (mAcpiLowMemoryBase, 4);\r |
878ddf1f |
288 | return ;\r |
289 | }\r |
290 | //\r |
291 | // Get DXE drivers performance\r |
292 | //\r |
293 | for (mIndex = 0; mIndex < NoHandles; mIndex++) {\r |
294 | Ticker = 0;\r |
295 | LogEntryKey = 0;\r |
296 | while ((LogEntryKey = GetPerformanceMeasurement (\r |
297 | LogEntryKey,\r |
298 | &Handle,\r |
299 | &Token,\r |
300 | &Module,\r |
301 | &StartTicker,\r |
302 | &EndTicker)) != 0) {\r |
303 | if ((Handle == Handles[mIndex]) && (StartTicker < EndTicker)) {\r |
304 | Ticker += (EndTicker - StartTicker);\r |
305 | }\r |
306 | }\r |
307 | \r |
308 | Duration = (UINT32) DivU64x32 (\r |
309 | Ticker,\r |
310 | (UINT32) Freq\r |
311 | );\r |
312 | \r |
313 | if (Duration > 0) {\r |
314 | ZeroMem (&mPerfData, sizeof (PERF_DATA));\r |
315 | \r |
316 | GetNameFromHandle (Handles[mIndex], GaugeString);\r |
317 | \r |
318 | AsciiStrCpy (mPerfData.Token, GaugeString);\r |
319 | mPerfData.Duration = Duration;\r |
320 | \r |
321 | CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r |
322 | Ptr += sizeof (PERF_DATA);\r |
323 | \r |
324 | mPerfHeader.Count++;\r |
325 | if (mPerfHeader.Count == LimitCount) {\r |
326 | goto Done;\r |
327 | }\r |
328 | }\r |
329 | }\r |
330 | \r |
fa332de7 |
331 | FreePool (Handles);\r |
878ddf1f |
332 | \r |
333 | //\r |
334 | // Get inserted performance data\r |
335 | //\r |
336 | LogEntryKey = 0;\r |
337 | while ((LogEntryKey = GetPerformanceMeasurement (\r |
338 | LogEntryKey,\r |
339 | &Handle,\r |
340 | &Token,\r |
341 | &Module,\r |
342 | &StartTicker,\r |
343 | &EndTicker)) != 0) {\r |
344 | if ((Handle == NULL) && (StartTicker <= EndTicker)) {\r |
345 | \r |
346 | ZeroMem (&mPerfData, sizeof (PERF_DATA));\r |
347 | \r |
348 | AsciiStrnCpy (mPerfData.Token, Token, DXE_PERFORMANCE_STRING_SIZE);\r |
349 | mPerfData.Duration = (UINT32) DivU64x32 (\r |
350 | EndTicker - StartTicker,\r |
351 | (UINT32) Freq\r |
352 | );\r |
353 | \r |
354 | CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r |
355 | Ptr += sizeof (PERF_DATA);\r |
356 | \r |
357 | mPerfHeader.Count++;\r |
358 | if (mPerfHeader.Count == LimitCount) {\r |
359 | goto Done;\r |
360 | }\r |
361 | }\r |
362 | }\r |
363 | \r |
364 | Done:\r |
365 | \r |
878ddf1f |
366 | mPerfHeader.Signiture = 0x66726550;\r |
367 | \r |
368 | //\r |
369 | // Put performance data to memory\r |
370 | //\r |
371 | CopyMem (\r |
372 | (UINT32 *) (UINT32) mAcpiLowMemoryBase,\r |
373 | &mPerfHeader,\r |
374 | sizeof (PERF_HEADER)\r |
375 | );\r |
376 | \r |
377 | gRT->SetVariable (\r |
378 | L"PerfDataMemAddr",\r |
20515cd1 |
379 | &gEfiGenericPlatformVariableGuid,\r |
878ddf1f |
380 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r |
381 | sizeof (UINT32),\r |
382 | (VOID *) &mAcpiLowMemoryBase\r |
383 | );\r |
384 | \r |
385 | return ;\r |
386 | }\r |