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