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