]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c
Update for the performance infrastructure changes:
[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
6Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
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
21\r
22/**\r
23 Get the short verion of PDB file name to be\r
24 used in performance data logging.\r
25\r
26 @param PdbFileName The long PDB file name.\r
27 @param GaugeString The output string to be logged by performance logger.\r
28\r
29**/\r
30VOID\r
31GetShortPdbFileName (\r
32 IN CONST CHAR8 *PdbFileName,\r
33 OUT CHAR8 *GaugeString\r
34 )\r
35{\r
36 UINTN Index;\r
37 UINTN Index1;\r
38 UINTN StartIndex;\r
39 UINTN EndIndex;\r
40\r
41 if (PdbFileName == NULL) {\r
42 AsciiStrCpy (GaugeString, " ");\r
43 } else {\r
44 StartIndex = 0;\r
45 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r
46 ;\r
47\r
48 for (Index = 0; PdbFileName[Index] != 0; Index++) {\r
49 if (PdbFileName[Index] == '\\') {\r
50 StartIndex = Index + 1;\r
51 }\r
52\r
53 if (PdbFileName[Index] == '.') {\r
54 EndIndex = Index;\r
55 }\r
56 }\r
57\r
58 Index1 = 0;\r
59 for (Index = StartIndex; Index < EndIndex; Index++) {\r
60 GaugeString[Index1] = PdbFileName[Index];\r
61 Index1++;\r
62 if (Index1 == PERF_TOKEN_LENGTH - 1) {\r
63 break;\r
64 }\r
65 }\r
66\r
67 GaugeString[Index1] = 0;\r
68 }\r
69\r
70 return ;\r
71}\r
72\r
73/**\r
74 Get the name from the Driver handle, which can be a handle with\r
75 EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.\r
76 This name can be used in performance data logging.\r
77\r
78 @param Handle Driver handle.\r
79 @param GaugeString The output string to be logged by performance logger.\r
80\r
81**/\r
82VOID\r
83GetNameFromHandle (\r
84 IN EFI_HANDLE Handle,\r
85 OUT CHAR8 *GaugeString\r
86 )\r
87{\r
88 EFI_STATUS Status;\r
89 EFI_LOADED_IMAGE_PROTOCOL *Image;\r
90 CHAR8 *PdbFileName;\r
91 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
92\r
93 AsciiStrCpy (GaugeString, " ");\r
94\r
95 //\r
96 // Get handle name from image protocol\r
97 //\r
98 Status = gBS->HandleProtocol (\r
99 Handle,\r
100 &gEfiLoadedImageProtocolGuid,\r
101 (VOID **) &Image\r
102 );\r
103\r
104 if (EFI_ERROR (Status)) {\r
105 Status = gBS->OpenProtocol (\r
106 Handle,\r
107 &gEfiDriverBindingProtocolGuid,\r
108 (VOID **) &DriverBinding,\r
109 NULL,\r
110 NULL,\r
111 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
112 );\r
113 if (EFI_ERROR (Status)) {\r
114 return ;\r
115 }\r
116 //\r
117 // Get handle name from image protocol\r
118 //\r
119 Status = gBS->HandleProtocol (\r
120 DriverBinding->ImageHandle,\r
121 &gEfiLoadedImageProtocolGuid,\r
122 (VOID **) &Image\r
123 );\r
124 }\r
125\r
126 PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);\r
127\r
128 if (PdbFileName != NULL) {\r
129 GetShortPdbFileName (PdbFileName, GaugeString);\r
130 }\r
131\r
132 return ;\r
133}\r
134\r
135/**\r
136\r
137 Allocates a block of memory and writes performance data of booting into it.\r
138 OS can processing these record.\r
139 \r
140**/\r
141VOID\r
142WriteBootToOsPerformanceData (\r
143 VOID\r
144 )\r
145{\r
146 EFI_STATUS Status;\r
147 EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase;\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\r
168 //\r
6055758f 169 // Retrieve time stamp count as early as possible\r
5c08e117 170 //\r
171 Ticker = GetPerformanceCounter ();\r
172\r
173 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
174 \r
175 Freq = DivU64x32 (Freq, 1000);\r
176\r
177 mPerfHeader.CpuFreq = Freq;\r
178\r
179 //\r
180 // Record BDS raw performance data\r
181 //\r
182 if (EndValue >= StartValue) {\r
183 mPerfHeader.BDSRaw = Ticker - StartValue;\r
184 CountUp = TRUE;\r
185 } else {\r
186 mPerfHeader.BDSRaw = StartValue - Ticker;\r
187 CountUp = FALSE;\r
188 }\r
189\r
190 AcpiLowMemoryLength = 0x2000;\r
191\r
192 //\r
193 // Allocate a block of memory that contain performance data to OS\r
194 //\r
195 Status = gBS->AllocatePages (\r
196 AllocateAnyPages,\r
197 EfiACPIReclaimMemory,\r
198 EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),\r
199 &AcpiLowMemoryBase\r
200 );\r
201 if (EFI_ERROR (Status)) {\r
202 return ;\r
203 }\r
204\r
205\r
206 Ptr = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER));\r
207 LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);\r
208\r
209 //\r
210 // Put Detailed performance data into memory\r
211 //\r
212 Handles = NULL;\r
213 Status = gBS->LocateHandleBuffer (\r
214 AllHandles,\r
215 NULL,\r
216 NULL,\r
217 &NoHandles,\r
218 &Handles\r
219 );\r
220 if (EFI_ERROR (Status)) {\r
221 gBS->FreePages (AcpiLowMemoryBase, 1);\r
222 return ;\r
223 }\r
224 \r
225 //\r
226 // Get DXE drivers performance\r
227 //\r
228 for (Index = 0; Index < NoHandles; Index++) {\r
229 Ticker = 0;\r
230 LogEntryKey = 0;\r
231 while ((LogEntryKey = GetPerformanceMeasurement (\r
232 LogEntryKey,\r
233 &Handle,\r
234 &Token,\r
235 &Module,\r
236 &StartTicker,\r
237 &EndTicker)) != 0) {\r
238 if ((Handle == Handles[Index]) && (EndTicker != 0)) {\r
239 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
240 }\r
241 }\r
242\r
243 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
244\r
245 if (Duration > 0) {\r
246\r
247 GetNameFromHandle (Handles[Index], GaugeString);\r
248\r
249 AsciiStrCpy (mPerfData.Token, GaugeString);\r
250 mPerfData.Duration = Duration;\r
251\r
252 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
253 Ptr += sizeof (PERF_DATA);\r
254\r
255 mPerfHeader.Count++;\r
256 if (mPerfHeader.Count == LimitCount) {\r
257 goto Done;\r
258 }\r
259 }\r
260 }\r
261\r
262 FreePool (Handles);\r
263\r
264 //\r
265 // Get inserted performance data\r
266 //\r
267 LogEntryKey = 0;\r
268 while ((LogEntryKey = GetPerformanceMeasurement (\r
269 LogEntryKey,\r
270 &Handle,\r
271 &Token,\r
272 &Module,\r
273 &StartTicker,\r
274 &EndTicker)) != 0) {\r
275 if (Handle == NULL && EndTicker != 0) {\r
276\r
277 ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
278\r
279 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);\r
280 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
281\r
282 mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
283\r
284 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
285 Ptr += sizeof (PERF_DATA);\r
286\r
287 mPerfHeader.Count++;\r
288 if (mPerfHeader.Count == LimitCount) {\r
289 goto Done;\r
290 }\r
291 }\r
292 }\r
293\r
294Done:\r
295\r
296 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
297\r
298 //\r
299 // Put performance data to ACPI memory\r
300 //\r
301 CopyMem (\r
302 (UINTN *) (UINTN) AcpiLowMemoryBase,\r
303 &mPerfHeader,\r
304 sizeof (PERF_HEADER)\r
305 );\r
306\r
307 gRT->SetVariable (\r
308 L"PerfDataMemAddr",\r
6055758f 309 &gPerformanceProtocolGuid,\r
5c08e117 310 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
311 sizeof (EFI_PHYSICAL_ADDRESS),\r
312 &AcpiLowMemoryBase\r
313 );\r
314\r
315 return ;\r
316}\r