]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c
Update the copyright notice format
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / GenericBdsLib / Performance.c
1 /** @file
2 This file include the file which can help to get the system
3 performance, all the function will only include if the performance
4 switch is set.
5
6 Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include "InternalBdsLib.h"
18
19 PERF_HEADER mPerfHeader;
20 PERF_DATA mPerfData;
21 EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase = 0x0FFFFFFFFULL;
22
23 /**
24 Get the short verion of PDB file name to be
25 used in performance data logging.
26
27 @param PdbFileName The long PDB file name.
28 @param GaugeString The output string to be logged by performance logger.
29
30 **/
31 VOID
32 GetShortPdbFileName (
33 IN CONST CHAR8 *PdbFileName,
34 OUT CHAR8 *GaugeString
35 )
36 {
37 UINTN Index;
38 UINTN Index1;
39 UINTN StartIndex;
40 UINTN EndIndex;
41
42 if (PdbFileName == NULL) {
43 AsciiStrCpy (GaugeString, " ");
44 } else {
45 StartIndex = 0;
46 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
47 ;
48
49 for (Index = 0; PdbFileName[Index] != 0; Index++) {
50 if (PdbFileName[Index] == '\\') {
51 StartIndex = Index + 1;
52 }
53
54 if (PdbFileName[Index] == '.') {
55 EndIndex = Index;
56 }
57 }
58
59 Index1 = 0;
60 for (Index = StartIndex; Index < EndIndex; Index++) {
61 GaugeString[Index1] = PdbFileName[Index];
62 Index1++;
63 if (Index1 == PERF_TOKEN_LENGTH - 1) {
64 break;
65 }
66 }
67
68 GaugeString[Index1] = 0;
69 }
70
71 return ;
72 }
73
74 /**
75 Get the name from the Driver handle, which can be a handle with
76 EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.
77 This name can be used in performance data logging.
78
79 @param Handle Driver handle.
80 @param GaugeString The output string to be logged by performance logger.
81
82 **/
83 VOID
84 GetNameFromHandle (
85 IN EFI_HANDLE Handle,
86 OUT CHAR8 *GaugeString
87 )
88 {
89 EFI_STATUS Status;
90 EFI_LOADED_IMAGE_PROTOCOL *Image;
91 CHAR8 *PdbFileName;
92 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
93
94 AsciiStrCpy (GaugeString, " ");
95
96 //
97 // Get handle name from image protocol
98 //
99 Status = gBS->HandleProtocol (
100 Handle,
101 &gEfiLoadedImageProtocolGuid,
102 (VOID **) &Image
103 );
104
105 if (EFI_ERROR (Status)) {
106 Status = gBS->OpenProtocol (
107 Handle,
108 &gEfiDriverBindingProtocolGuid,
109 (VOID **) &DriverBinding,
110 NULL,
111 NULL,
112 EFI_OPEN_PROTOCOL_GET_PROTOCOL
113 );
114 if (EFI_ERROR (Status)) {
115 return ;
116 }
117 //
118 // Get handle name from image protocol
119 //
120 Status = gBS->HandleProtocol (
121 DriverBinding->ImageHandle,
122 &gEfiLoadedImageProtocolGuid,
123 (VOID **) &Image
124 );
125 }
126
127 PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
128
129 if (PdbFileName != NULL) {
130 GetShortPdbFileName (PdbFileName, GaugeString);
131 }
132
133 return ;
134 }
135
136 /**
137
138 Allocates a block of memory and writes performance data of booting into it.
139 OS can processing these record.
140
141 **/
142 VOID
143 WriteBootToOsPerformanceData (
144 VOID
145 )
146 {
147 EFI_STATUS Status;
148 UINT32 AcpiLowMemoryLength;
149 UINT32 LimitCount;
150 EFI_HANDLE *Handles;
151 UINTN NoHandles;
152 CHAR8 GaugeString[PERF_TOKEN_LENGTH];
153 UINT8 *Ptr;
154 UINT32 Index;
155 UINT64 Ticker;
156 UINT64 Freq;
157 UINT32 Duration;
158 UINTN LogEntryKey;
159 CONST VOID *Handle;
160 CONST CHAR8 *Token;
161 CONST CHAR8 *Module;
162 UINT64 StartTicker;
163 UINT64 EndTicker;
164 UINT64 StartValue;
165 UINT64 EndValue;
166 BOOLEAN CountUp;
167 UINTN EntryIndex;
168 UINTN NumPerfEntries;
169 //
170 // List of flags indicating PerfEntry contains DXE handle
171 //
172 BOOLEAN *PerfEntriesAsDxeHandle;
173
174 //
175 // Retrieve time stamp count as early as possible
176 //
177 Ticker = GetPerformanceCounter ();
178
179 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
180
181 Freq = DivU64x32 (Freq, 1000);
182
183 mPerfHeader.CpuFreq = Freq;
184
185 //
186 // Record BDS raw performance data
187 //
188 if (EndValue >= StartValue) {
189 mPerfHeader.BDSRaw = Ticker - StartValue;
190 CountUp = TRUE;
191 } else {
192 mPerfHeader.BDSRaw = StartValue - Ticker;
193 CountUp = FALSE;
194 }
195
196 //
197 // Put Detailed performance data into memory
198 //
199 Handles = NULL;
200 Status = gBS->LocateHandleBuffer (
201 AllHandles,
202 NULL,
203 NULL,
204 &NoHandles,
205 &Handles
206 );
207 if (EFI_ERROR (Status)) {
208 return ;
209 }
210
211
212 AcpiLowMemoryLength = 0x4000;
213 if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {
214 //
215 // Allocate a block of memory that contain performance data to OS
216 //
217 Status = gBS->AllocatePages (
218 AllocateMaxAddress,
219 EfiReservedMemoryType,
220 EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),
221 &mAcpiLowMemoryBase
222 );
223 if (EFI_ERROR (Status)) {
224 FreePool (Handles);
225 return ;
226 }
227 }
228
229
230 Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));
231 LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
232
233 NumPerfEntries = 0;
234 LogEntryKey = 0;
235 while ((LogEntryKey = GetPerformanceMeasurement (
236 LogEntryKey,
237 &Handle,
238 &Token,
239 &Module,
240 &StartTicker,
241 &EndTicker)) != 0) {
242 NumPerfEntries++;
243 }
244 PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
245 ASSERT (PerfEntriesAsDxeHandle != NULL);
246
247 //
248 // Get DXE drivers performance
249 //
250 for (Index = 0; Index < NoHandles; Index++) {
251 Ticker = 0;
252 LogEntryKey = 0;
253 EntryIndex = 0;
254 while ((LogEntryKey = GetPerformanceMeasurement (
255 LogEntryKey,
256 &Handle,
257 &Token,
258 &Module,
259 &StartTicker,
260 &EndTicker)) != 0) {
261 if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
262 PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
263 }
264 EntryIndex++;
265 if ((Handle == Handles[Index]) && (EndTicker != 0)) {
266 if (StartTicker == 1) {
267 StartTicker = StartValue;
268 }
269 if (EndTicker == 1) {
270 EndTicker = StartValue;
271 }
272 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
273 }
274 }
275
276 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
277
278 if (Duration > 0) {
279
280 GetNameFromHandle (Handles[Index], GaugeString);
281
282 AsciiStrCpy (mPerfData.Token, GaugeString);
283 mPerfData.Duration = Duration;
284
285 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
286 Ptr += sizeof (PERF_DATA);
287
288 mPerfHeader.Count++;
289 if (mPerfHeader.Count == LimitCount) {
290 goto Done;
291 }
292 }
293 }
294
295 //
296 // Get inserted performance data
297 //
298 LogEntryKey = 0;
299 EntryIndex = 0;
300 while ((LogEntryKey = GetPerformanceMeasurement (
301 LogEntryKey,
302 &Handle,
303 &Token,
304 &Module,
305 &StartTicker,
306 &EndTicker)) != 0) {
307 if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {
308
309 ZeroMem (&mPerfData, sizeof (PERF_DATA));
310
311 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);
312 if (StartTicker == 1) {
313 StartTicker = StartValue;
314 }
315 if (EndTicker == 1) {
316 EndTicker = StartValue;
317 }
318 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
319
320 mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
321
322 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
323 Ptr += sizeof (PERF_DATA);
324
325 mPerfHeader.Count++;
326 if (mPerfHeader.Count == LimitCount) {
327 goto Done;
328 }
329 }
330 EntryIndex++;
331 }
332
333 Done:
334
335 FreePool (Handles);
336 FreePool (PerfEntriesAsDxeHandle);
337
338 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
339
340 //
341 // Put performance data to Reserved memory
342 //
343 CopyMem (
344 (UINTN *) (UINTN) mAcpiLowMemoryBase,
345 &mPerfHeader,
346 sizeof (PERF_HEADER)
347 );
348
349 gRT->SetVariable (
350 L"PerfDataMemAddr",
351 &gPerformanceProtocolGuid,
352 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
353 sizeof (EFI_PHYSICAL_ADDRESS),
354 &mAcpiLowMemoryBase
355 );
356
357 return ;
358 }