]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c
Minor code enhancement.
[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
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
5c08e117 190 //\r
191 // Put Detailed performance data into memory\r
192 //\r
193 Handles = NULL;\r
194 Status = gBS->LocateHandleBuffer (\r
195 AllHandles,\r
196 NULL,\r
197 NULL,\r
198 &NoHandles,\r
199 &Handles\r
200 );\r
201 if (EFI_ERROR (Status)) {\r
5c08e117 202 return ;\r
203 }\r
02c9c470 204\r
205\r
206 AcpiLowMemoryLength = 0x4000;\r
207 if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {\r
208 //\r
209 // Allocate a block of memory that contain performance data to OS\r
210 //\r
211 Status = gBS->AllocatePages (\r
212 AllocateMaxAddress,\r
213 EfiReservedMemoryType,\r
214 EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),\r
215 &mAcpiLowMemoryBase\r
216 );\r
217 if (EFI_ERROR (Status)) {\r
218 FreePool (Handles);\r
219 return ;\r
220 }\r
221 }\r
222\r
223\r
224 Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));\r
225 LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);\r
226\r
227\r
5c08e117 228 \r
229 //\r
230 // Get DXE drivers performance\r
231 //\r
232 for (Index = 0; Index < NoHandles; Index++) {\r
233 Ticker = 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 if ((Handle == Handles[Index]) && (EndTicker != 0)) {\r
243 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
244 }\r
245 }\r
246\r
247 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
248\r
249 if (Duration > 0) {\r
250\r
251 GetNameFromHandle (Handles[Index], GaugeString);\r
252\r
253 AsciiStrCpy (mPerfData.Token, GaugeString);\r
254 mPerfData.Duration = Duration;\r
255\r
256 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
257 Ptr += sizeof (PERF_DATA);\r
258\r
259 mPerfHeader.Count++;\r
260 if (mPerfHeader.Count == LimitCount) {\r
261 goto Done;\r
262 }\r
263 }\r
264 }\r
265\r
266 FreePool (Handles);\r
267\r
268 //\r
269 // Get inserted performance data\r
270 //\r
271 LogEntryKey = 0;\r
272 while ((LogEntryKey = GetPerformanceMeasurement (\r
273 LogEntryKey,\r
274 &Handle,\r
275 &Token,\r
276 &Module,\r
277 &StartTicker,\r
278 &EndTicker)) != 0) {\r
279 if (Handle == NULL && EndTicker != 0) {\r
280\r
281 ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
282\r
283 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);\r
284 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
285\r
286 mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
287\r
288 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
289 Ptr += sizeof (PERF_DATA);\r
290\r
291 mPerfHeader.Count++;\r
292 if (mPerfHeader.Count == LimitCount) {\r
293 goto Done;\r
294 }\r
295 }\r
296 }\r
297\r
298Done:\r
299\r
300 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
301\r
302 //\r
02c9c470 303 // Put performance data to Reserved memory\r
5c08e117 304 //\r
305 CopyMem (\r
02c9c470 306 (UINTN *) (UINTN) mAcpiLowMemoryBase,\r
5c08e117 307 &mPerfHeader,\r
308 sizeof (PERF_HEADER)\r
309 );\r
310\r
311 gRT->SetVariable (\r
312 L"PerfDataMemAddr",\r
6055758f 313 &gPerformanceProtocolGuid,\r
5c08e117 314 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
315 sizeof (EFI_PHYSICAL_ADDRESS),\r
02c9c470 316 &mAcpiLowMemoryBase\r
5c08e117 317 );\r
318\r
319 return ;\r
320}\r