]> git.proxmox.com Git - mirror_edk2.git/blame - Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c
Upload BSD-licensed Vlv2TbltDevicePkg and Vlv2DeviceRefCodePkg to
[mirror_edk2.git] / Vlv2TbltDevicePkg / Override / IntelFrameworkModulePkg / Library / GenericBdsLib / Performance.c
CommitLineData
3cbfba02
DW
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 - 2013, 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 Writes performance data of booting into the allocated memory.\r
139 OS can process these records.\r
140\r
141 @param Event The triggered event.\r
142 @param Context Context for this event.\r
143\r
144**/\r
145VOID\r
146EFIAPI\r
147WriteBootToOsPerformanceData (\r
148 IN EFI_EVENT Event,\r
149 IN VOID *Context\r
150 )\r
151{\r
152 EFI_STATUS Status;\r
153 UINT32 LimitCount;\r
154 EFI_HANDLE *Handles;\r
155 UINTN NoHandles;\r
156 CHAR8 GaugeString[PERF_TOKEN_LENGTH];\r
157 UINT8 *Ptr;\r
158 UINT32 Index;\r
159 UINT64 Ticker;\r
160 UINT64 Freq;\r
161 UINT32 Duration;\r
162 UINTN LogEntryKey;\r
163 CONST VOID *Handle;\r
164 CONST CHAR8 *Token;\r
165 CONST CHAR8 *Module;\r
166 UINT64 StartTicker;\r
167 UINT64 EndTicker;\r
168 UINT64 StartValue;\r
169 UINT64 EndValue;\r
170 BOOLEAN CountUp;\r
171 UINTN EntryIndex;\r
172 UINTN NumPerfEntries;\r
173 //\r
174 // List of flags indicating PerfEntry contains DXE handle\r
175 //\r
176 BOOLEAN *PerfEntriesAsDxeHandle;\r
177 UINTN VarSize;\r
178\r
179 //\r
180 // Record the performance data for End of BDS\r
181 //\r
182 PERF_END(NULL, "BDS", NULL, 0);\r
183\r
184 //\r
185 // Retrieve time stamp count as early as possible\r
186 //\r
187 Ticker = GetPerformanceCounter ();\r
188\r
189 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
190 \r
191 Freq = DivU64x32 (Freq, 1000);\r
192\r
193 mPerfHeader.CpuFreq = Freq;\r
194\r
195 //\r
196 // Record BDS raw performance data\r
197 //\r
198 if (EndValue >= StartValue) {\r
199 mPerfHeader.BDSRaw = Ticker - StartValue;\r
200 CountUp = TRUE;\r
201 } else {\r
202 mPerfHeader.BDSRaw = StartValue - Ticker;\r
203 CountUp = FALSE;\r
204 }\r
205\r
206 if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {\r
207 VarSize = sizeof (EFI_PHYSICAL_ADDRESS);\r
208 Status = gRT->GetVariable (\r
209 L"PerfDataMemAddr",\r
210 &gPerformanceProtocolGuid,\r
211 NULL,\r
212 &VarSize,\r
213 &mAcpiLowMemoryBase\r
214 );\r
215 if (EFI_ERROR (Status)) {\r
216 //\r
217 // Fail to get the variable, return.\r
218 //\r
219 return;\r
220 }\r
221 }\r
222\r
223 //\r
224 // Put Detailed performance data into memory\r
225 //\r
226 Handles = NULL;\r
227 Status = gBS->LocateHandleBuffer (\r
228 AllHandles,\r
229 NULL,\r
230 NULL,\r
231 &NoHandles,\r
232 &Handles\r
233 );\r
234 if (EFI_ERROR (Status)) {\r
235 return ;\r
236 }\r
237\r
238 Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));\r
239 LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);\r
240\r
241 NumPerfEntries = 0;\r
242 LogEntryKey = 0;\r
243 while ((LogEntryKey = GetPerformanceMeasurement (\r
244 LogEntryKey,\r
245 &Handle,\r
246 &Token,\r
247 &Module,\r
248 &StartTicker,\r
249 &EndTicker)) != 0) {\r
250 NumPerfEntries++;\r
251 }\r
252 PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));\r
253 ASSERT (PerfEntriesAsDxeHandle != NULL);\r
254 \r
255 //\r
256 // Get DXE drivers performance\r
257 //\r
258 for (Index = 0; Index < NoHandles; Index++) {\r
259 Ticker = 0;\r
260 LogEntryKey = 0;\r
261 EntryIndex = 0;\r
262 while ((LogEntryKey = GetPerformanceMeasurement (\r
263 LogEntryKey,\r
264 &Handle,\r
265 &Token,\r
266 &Module,\r
267 &StartTicker,\r
268 &EndTicker)) != 0) {\r
269 if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {\r
270 PerfEntriesAsDxeHandle[EntryIndex] = TRUE;\r
271 }\r
272 EntryIndex++;\r
273 if ((Handle == Handles[Index]) && (EndTicker != 0)) {\r
274 if (StartTicker == 1) {\r
275 StartTicker = StartValue;\r
276 }\r
277 if (EndTicker == 1) {\r
278 EndTicker = StartValue;\r
279 }\r
280 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
281 }\r
282 }\r
283\r
284 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
285\r
286 if (Duration > 0) {\r
287\r
288 GetNameFromHandle (Handles[Index], GaugeString);\r
289\r
290 AsciiStrCpy (mPerfData.Token, GaugeString);\r
291 mPerfData.Duration = Duration;\r
292\r
293 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
294 Ptr += sizeof (PERF_DATA);\r
295\r
296 mPerfHeader.Count++;\r
297 if (mPerfHeader.Count == LimitCount) {\r
298 goto Done;\r
299 }\r
300 }\r
301 }\r
302\r
303 //\r
304 // Get inserted performance data\r
305 //\r
306 LogEntryKey = 0;\r
307 EntryIndex = 0;\r
308 while ((LogEntryKey = GetPerformanceMeasurement (\r
309 LogEntryKey,\r
310 &Handle,\r
311 &Token,\r
312 &Module,\r
313 &StartTicker,\r
314 &EndTicker)) != 0) {\r
315 if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {\r
316\r
317 ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
318\r
319 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);\r
320 if (StartTicker == 1) {\r
321 StartTicker = StartValue;\r
322 }\r
323 if (EndTicker == 1) {\r
324 EndTicker = StartValue;\r
325 }\r
326 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
327\r
328 mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
329\r
330 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
331 Ptr += sizeof (PERF_DATA);\r
332\r
333 mPerfHeader.Count++;\r
334 if (mPerfHeader.Count == LimitCount) {\r
335 goto Done;\r
336 }\r
337 }\r
338 EntryIndex++;\r
339 }\r
340\r
341Done:\r
342\r
343 FreePool (Handles);\r
344 FreePool (PerfEntriesAsDxeHandle);\r
345\r
346 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
347\r
348 //\r
349 // Put performance data to Reserved memory\r
350 //\r
351 CopyMem (\r
352 (UINTN *) (UINTN) mAcpiLowMemoryBase,\r
353 &mPerfHeader,\r
354 sizeof (PERF_HEADER)\r
355 );\r
356\r
357 return ;\r
358}\r