]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c
Update the copyright notice format
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / GenericBdsLib / Performance.c
... / ...
CommitLineData
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
6Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>\r
7This 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
21EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase = 0x0FFFFFFFFULL;\r
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
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
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
173\r
174 //\r
175 // Retrieve time stamp count as early as possible\r
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
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
208 return ;\r
209 }\r
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
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
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
253 EntryIndex = 0;\r
254 while ((LogEntryKey = GetPerformanceMeasurement (\r
255 LogEntryKey,\r
256 &Handle,\r
257 &Token,\r
258 &Module,\r
259 &StartTicker,\r
260 &EndTicker)) != 0) {\r
261 if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {\r
262 PerfEntriesAsDxeHandle[EntryIndex] = TRUE;\r
263 }\r
264 EntryIndex++;\r
265 if ((Handle == Handles[Index]) && (EndTicker != 0)) {\r
266 if (StartTicker == 1) {\r
267 StartTicker = StartValue;\r
268 }\r
269 if (EndTicker == 1) {\r
270 EndTicker = StartValue;\r
271 }\r
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
295 //\r
296 // Get inserted performance data\r
297 //\r
298 LogEntryKey = 0;\r
299 EntryIndex = 0;\r
300 while ((LogEntryKey = GetPerformanceMeasurement (\r
301 LogEntryKey,\r
302 &Handle,\r
303 &Token,\r
304 &Module,\r
305 &StartTicker,\r
306 &EndTicker)) != 0) {\r
307 if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {\r
308\r
309 ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
310\r
311 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);\r
312 if (StartTicker == 1) {\r
313 StartTicker = StartValue;\r
314 }\r
315 if (EndTicker == 1) {\r
316 EndTicker = StartValue;\r
317 }\r
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
330 EntryIndex++;\r
331 }\r
332\r
333Done:\r
334\r
335 FreePool (Handles);\r
336 FreePool (PerfEntriesAsDxeHandle);\r
337\r
338 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
339\r
340 //\r
341 // Put performance data to Reserved memory\r
342 //\r
343 CopyMem (\r
344 (UINTN *) (UINTN) mAcpiLowMemoryBase,\r
345 &mPerfHeader,\r
346 sizeof (PERF_HEADER)\r
347 );\r
348\r
349 gRT->SetVariable (\r
350 L"PerfDataMemAddr",\r
351 &gPerformanceProtocolGuid,\r
352 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
353 sizeof (EFI_PHYSICAL_ADDRESS),\r
354 &mAcpiLowMemoryBase\r
355 );\r
356\r
357 return ;\r
358}\r