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