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