]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c
Update the copyright notice format
[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
07341a33 266 if (StartTicker == 1) {\r
267 StartTicker = StartValue;\r
268 }\r
269 if (EndTicker == 1) {\r
270 EndTicker = StartValue;\r
271 }\r
5c08e117 272 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
273 }\r
274 }\r
275\r
276 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
277\r
278 if (Duration > 0) {\r
279\r
280 GetNameFromHandle (Handles[Index], GaugeString);\r
281\r
282 AsciiStrCpy (mPerfData.Token, GaugeString);\r
283 mPerfData.Duration = Duration;\r
284\r
285 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
286 Ptr += sizeof (PERF_DATA);\r
287\r
288 mPerfHeader.Count++;\r
289 if (mPerfHeader.Count == LimitCount) {\r
290 goto Done;\r
291 }\r
292 }\r
293 }\r
294\r
5c08e117 295 //\r
296 // Get inserted performance data\r
297 //\r
298 LogEntryKey = 0;\r
b5a144ec 299 EntryIndex = 0;\r
5c08e117 300 while ((LogEntryKey = GetPerformanceMeasurement (\r
301 LogEntryKey,\r
302 &Handle,\r
303 &Token,\r
304 &Module,\r
305 &StartTicker,\r
306 &EndTicker)) != 0) {\r
b5a144ec 307 if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {\r
5c08e117 308\r
309 ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
310\r
311 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);\r
07341a33 312 if (StartTicker == 1) {\r
313 StartTicker = StartValue;\r
314 }\r
315 if (EndTicker == 1) {\r
316 EndTicker = StartValue;\r
317 }\r
5c08e117 318 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
319\r
320 mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
321\r
322 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
323 Ptr += sizeof (PERF_DATA);\r
324\r
325 mPerfHeader.Count++;\r
326 if (mPerfHeader.Count == LimitCount) {\r
327 goto Done;\r
328 }\r
329 }\r
b5a144ec 330 EntryIndex++;\r
5c08e117 331 }\r
332\r
333Done:\r
334\r
b5a144ec 335 FreePool (Handles);\r
336 FreePool (PerfEntriesAsDxeHandle);\r
337\r
5c08e117 338 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
339\r
340 //\r
02c9c470 341 // Put performance data to Reserved memory\r
5c08e117 342 //\r
343 CopyMem (\r
02c9c470 344 (UINTN *) (UINTN) mAcpiLowMemoryBase,\r
5c08e117 345 &mPerfHeader,\r
346 sizeof (PERF_HEADER)\r
347 );\r
348\r
349 gRT->SetVariable (\r
350 L"PerfDataMemAddr",\r
6055758f 351 &gPerformanceProtocolGuid,\r
5c08e117 352 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
353 sizeof (EFI_PHYSICAL_ADDRESS),\r
02c9c470 354 &mAcpiLowMemoryBase\r
5c08e117 355 );\r
356\r
357 return ;\r
358}\r