80b98563f067bba215341e813da49b31d6c02ce0
[mirror_edk2.git] / EdkNt32Pkg / Library / EdkGenericBdsLib / Performance.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Performance.c
15
16 Abstract:
17
18 This file include the file which can help to get the system
19 performance, all the function will only include if the performance
20 switch is set.
21
22 --*/
23
24 #include "Performance.h"
25
26 VOID
27 ClearDebugRegisters (
28 VOID
29 )
30 {
31 //
32 // BugBug: We should not need to do this. We need to root cause this bug!!!!
33 //
34 AsmWriteDr0 (0);
35 AsmWriteDr1 (0);
36 }
37
38 STATIC
39 VOID
40 GetShortPdbFileName (
41 CHAR8 *PdbFileName,
42 CHAR8 *GaugeString
43 )
44 /*++
45
46 Routine Description:
47
48 Arguments:
49
50 Returns:
51
52 --*/
53 {
54 UINTN Index;
55 UINTN Index1;
56 UINTN StartIndex;
57 UINTN EndIndex;
58
59 if (PdbFileName == NULL) {
60 AsciiStrCpy (GaugeString, " ");
61 } else {
62 StartIndex = 0;
63 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
64 ;
65
66 for (Index = 0; PdbFileName[Index] != 0; Index++) {
67 if (PdbFileName[Index] == '\\') {
68 StartIndex = Index + 1;
69 }
70
71 if (PdbFileName[Index] == '.') {
72 EndIndex = Index;
73 }
74 }
75
76 Index1 = 0;
77 for (Index = StartIndex; Index < EndIndex; Index++) {
78 GaugeString[Index1] = PdbFileName[Index];
79 Index1++;
80 if (Index1 == PERF_TOKEN_LENGTH - 1) {
81 break;
82 }
83 }
84
85 GaugeString[Index1] = 0;
86 }
87
88 return ;
89 }
90
91
92
93 STATIC
94 CHAR8 *
95 GetPdbPath (
96 VOID *ImageBase
97 )
98 /*++
99
100 Routine Description:
101
102 Located PDB path name in PE image
103
104 Arguments:
105
106 ImageBase - base of PE to search
107
108 Returns:
109
110 Pointer into image at offset of PDB file name if PDB file name is found,
111 Otherwise a pointer to an empty string.
112
113 --*/
114 {
115 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
116
117 ZeroMem (&ImageContext, sizeof (ImageContext));
118 ImageContext.Handle = ImageBase;
119 ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
120
121 PeCoffLoaderGetImageInfo (&ImageContext);
122
123 return ImageContext.PdbPointer;
124 }
125
126
127 STATIC
128 VOID
129 GetNameFromHandle (
130 IN EFI_HANDLE Handle,
131 OUT CHAR8 *GaugeString
132 )
133 {
134 EFI_STATUS Status;
135 EFI_LOADED_IMAGE_PROTOCOL *Image;
136 CHAR8 *PdbFileName;
137 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
138
139 AsciiStrCpy (GaugeString, " ");
140
141 //
142 // Get handle name from image protocol
143 //
144 Status = gBS->HandleProtocol (
145 Handle,
146 &gEfiLoadedImageProtocolGuid,
147 &Image
148 );
149
150 if (EFI_ERROR (Status)) {
151 Status = gBS->OpenProtocol (
152 Handle,
153 &gEfiDriverBindingProtocolGuid,
154 (VOID **) &DriverBinding,
155 NULL,
156 NULL,
157 EFI_OPEN_PROTOCOL_GET_PROTOCOL
158 );
159 if (EFI_ERROR (Status)) {
160 return ;
161 }
162 //
163 // Get handle name from image protocol
164 //
165 Status = gBS->HandleProtocol (
166 DriverBinding->ImageHandle,
167 &gEfiLoadedImageProtocolGuid,
168 &Image
169 );
170 }
171
172 PdbFileName = GetPdbPath (Image->ImageBase);
173
174 if (PdbFileName != NULL) {
175 GetShortPdbFileName (PdbFileName, GaugeString);
176 }
177
178 return ;
179 }
180
181
182
183 VOID
184 WriteBootToOsPerformanceData (
185 VOID
186 )
187 /*++
188
189 Routine Description:
190
191 Allocates a block of memory and writes performance data of booting to OS into it.
192
193 Arguments:
194
195 None
196
197 Returns:
198
199 None
200
201 --*/
202 {
203 EFI_STATUS Status;
204 EFI_CPU_ARCH_PROTOCOL *Cpu;
205 EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase;
206 UINT32 mAcpiLowMemoryLength;
207 UINT32 LimitCount;
208 PERF_HEADER mPerfHeader;
209 PERF_DATA mPerfData;
210 EFI_HANDLE *Handles;
211 UINTN NoHandles;
212 CHAR8 GaugeString[PERF_TOKEN_LENGTH];
213 UINT8 *Ptr;
214 UINT32 mIndex;
215 UINT64 Ticker;
216 UINT64 Freq;
217 UINT32 Duration;
218 UINT64 CurrentTicker;
219 UINT64 TimerPeriod;
220 UINTN LogEntryKey;
221 CONST VOID *Handle;
222 CONST CHAR8 *Token;
223 CONST CHAR8 *Module;
224 UINT64 StartTicker;
225 UINT64 EndTicker;
226
227 //
228 // Retrive time stamp count as early as possilbe
229 //
230 Ticker = AsmReadTsc ();
231
232 //
233 // Allocate a block of memory that contain performance data to OS
234 //
235 mAcpiLowMemoryBase = 0xFFFFFFFF;
236 Status = gBS->AllocatePages (
237 AllocateMaxAddress,
238 EfiReservedMemoryType,
239 4,
240 &mAcpiLowMemoryBase
241 );
242 if (EFI_ERROR (Status)) {
243 return ;
244 }
245
246 mAcpiLowMemoryLength = EFI_PAGES_TO_SIZE(4);
247
248 Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));
249 LimitCount = (mAcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
250
251 //
252 // Initialize performance data structure
253 //
254 ZeroMem (&mPerfHeader, sizeof (PERF_HEADER));
255
256 //
257 // Get CPU frequency
258 //
259 Status = gBS->LocateProtocol (
260 &gEfiCpuArchProtocolGuid,
261 NULL,
262 &Cpu
263 );
264 if (EFI_ERROR (Status)) {
265 gBS->FreePages (mAcpiLowMemoryBase, 4);
266 return ;
267 }
268 //
269 // Get Cpu Frequency
270 //
271 Status = Cpu->GetTimerValue (Cpu, 0, &(CurrentTicker), &TimerPeriod);
272 if (EFI_ERROR (Status)) {
273 gBS->FreePages (mAcpiLowMemoryBase, 4);
274 return ;
275 }
276
277 Freq = DivU64x32 (1000000000000, (UINTN) TimerPeriod);
278
279 mPerfHeader.CpuFreq = Freq;
280
281 //
282 // Record BDS raw performance data
283 //
284 mPerfHeader.BDSRaw = Ticker;
285
286 //
287 // Put Detailed performance data into memory
288 //
289 Handles = NULL;
290 Status = gBS->LocateHandleBuffer (
291 AllHandles,
292 NULL,
293 NULL,
294 &NoHandles,
295 &Handles
296 );
297 if (EFI_ERROR (Status)) {
298 gBS->FreePages (mAcpiLowMemoryBase, 4);
299 return ;
300 }
301 //
302 // Get DXE drivers performance
303 //
304 for (mIndex = 0; mIndex < NoHandles; mIndex++) {
305 Ticker = 0;
306 LogEntryKey = 0;
307 while ((LogEntryKey = GetPerformanceMeasurement (
308 LogEntryKey,
309 &Handle,
310 &Token,
311 &Module,
312 &StartTicker,
313 &EndTicker)) != 0) {
314 if ((Handle == Handles[mIndex]) && (StartTicker < EndTicker)) {
315 Ticker += (EndTicker - StartTicker);
316 }
317 }
318
319 Duration = (UINT32) DivU64x32 (
320 Ticker,
321 (UINT32) Freq
322 );
323
324 if (Duration > 0) {
325 ZeroMem (&mPerfData, sizeof (PERF_DATA));
326
327 GetNameFromHandle (Handles[mIndex], GaugeString);
328
329 AsciiStrCpy (mPerfData.Token, GaugeString);
330 mPerfData.Duration = Duration;
331
332 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
333 Ptr += sizeof (PERF_DATA);
334
335 mPerfHeader.Count++;
336 if (mPerfHeader.Count == LimitCount) {
337 goto Done;
338 }
339 }
340 }
341
342 gBS->FreePool (Handles);
343
344 //
345 // Get inserted performance data
346 //
347 LogEntryKey = 0;
348 while ((LogEntryKey = GetPerformanceMeasurement (
349 LogEntryKey,
350 &Handle,
351 &Token,
352 &Module,
353 &StartTicker,
354 &EndTicker)) != 0) {
355 if ((Handle == NULL) && (StartTicker <= EndTicker)) {
356
357 ZeroMem (&mPerfData, sizeof (PERF_DATA));
358
359 AsciiStrnCpy (mPerfData.Token, Token, DXE_PERFORMANCE_STRING_SIZE);
360 mPerfData.Duration = (UINT32) DivU64x32 (
361 EndTicker - StartTicker,
362 (UINT32) Freq
363 );
364
365 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
366 Ptr += sizeof (PERF_DATA);
367
368 mPerfHeader.Count++;
369 if (mPerfHeader.Count == LimitCount) {
370 goto Done;
371 }
372 }
373 }
374
375 Done:
376
377 ClearDebugRegisters ();
378
379 mPerfHeader.Signiture = 0x66726550;
380
381 //
382 // Put performance data to memory
383 //
384 CopyMem (
385 (UINT32 *) (UINT32) mAcpiLowMemoryBase,
386 &mPerfHeader,
387 sizeof (PERF_HEADER)
388 );
389
390 gRT->SetVariable (
391 L"PerfDataMemAddr",
392 &gEfiGlobalVariableGuid,
393 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
394 sizeof (UINT32),
395 (VOID *) &mAcpiLowMemoryBase
396 );
397
398 return ;
399 }