]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c
Add missing status code in several modules.
[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 - 2012, 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 UINT32 mAcpiLowMemoryLength = 0x4000;
23
24 /**
25 Get the short verion of PDB file name to be
26 used in performance data logging.
27
28 @param PdbFileName The long PDB file name.
29 @param GaugeString The output string to be logged by performance logger.
30
31 **/
32 VOID
33 GetShortPdbFileName (
34 IN CONST CHAR8 *PdbFileName,
35 OUT CHAR8 *GaugeString
36 )
37 {
38 UINTN Index;
39 UINTN Index1;
40 UINTN StartIndex;
41 UINTN EndIndex;
42
43 if (PdbFileName == NULL) {
44 AsciiStrCpy (GaugeString, " ");
45 } else {
46 StartIndex = 0;
47 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
48 ;
49
50 for (Index = 0; PdbFileName[Index] != 0; Index++) {
51 if (PdbFileName[Index] == '\\') {
52 StartIndex = Index + 1;
53 }
54
55 if (PdbFileName[Index] == '.') {
56 EndIndex = Index;
57 }
58 }
59
60 Index1 = 0;
61 for (Index = StartIndex; Index < EndIndex; Index++) {
62 GaugeString[Index1] = PdbFileName[Index];
63 Index1++;
64 if (Index1 == PERF_TOKEN_LENGTH - 1) {
65 break;
66 }
67 }
68
69 GaugeString[Index1] = 0;
70 }
71
72 return ;
73 }
74
75 /**
76 Get the name from the Driver handle, which can be a handle with
77 EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.
78 This name can be used in performance data logging.
79
80 @param Handle Driver handle.
81 @param GaugeString The output string to be logged by performance logger.
82
83 **/
84 VOID
85 GetNameFromHandle (
86 IN EFI_HANDLE Handle,
87 OUT CHAR8 *GaugeString
88 )
89 {
90 EFI_STATUS Status;
91 EFI_LOADED_IMAGE_PROTOCOL *Image;
92 CHAR8 *PdbFileName;
93 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
94
95 AsciiStrCpy (GaugeString, " ");
96
97 //
98 // Get handle name from image protocol
99 //
100 Status = gBS->HandleProtocol (
101 Handle,
102 &gEfiLoadedImageProtocolGuid,
103 (VOID **) &Image
104 );
105
106 if (EFI_ERROR (Status)) {
107 Status = gBS->OpenProtocol (
108 Handle,
109 &gEfiDriverBindingProtocolGuid,
110 (VOID **) &DriverBinding,
111 NULL,
112 NULL,
113 EFI_OPEN_PROTOCOL_GET_PROTOCOL
114 );
115 if (EFI_ERROR (Status)) {
116 return ;
117 }
118 //
119 // Get handle name from image protocol
120 //
121 Status = gBS->HandleProtocol (
122 DriverBinding->ImageHandle,
123 &gEfiLoadedImageProtocolGuid,
124 (VOID **) &Image
125 );
126 }
127
128 PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
129
130 if (PdbFileName != NULL) {
131 GetShortPdbFileName (PdbFileName, GaugeString);
132 }
133
134 return ;
135 }
136
137 /**
138
139 Allocates a block of memory to store performance data.
140
141 **/
142 VOID
143 AllocateMemoryForPerformanceData (
144 VOID
145 )
146 {
147 EFI_STATUS Status;
148
149 if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {
150 //
151 // Allocate a block of memory that contain performance data to OS
152 //
153 Status = gBS->AllocatePages (
154 AllocateMaxAddress,
155 EfiReservedMemoryType,
156 EFI_SIZE_TO_PAGES (mAcpiLowMemoryLength),
157 &mAcpiLowMemoryBase
158 );
159 if (!EFI_ERROR (Status)) {
160 gRT->SetVariable (
161 L"PerfDataMemAddr",
162 &gPerformanceProtocolGuid,
163 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
164 sizeof (EFI_PHYSICAL_ADDRESS),
165 &mAcpiLowMemoryBase
166 );
167 }
168 }
169 }
170
171 /**
172
173 Writes performance data of booting into the allocated memory.
174 OS can process these records.
175
176 @param Event The triggered event.
177 @param Context Context for this event.
178
179 **/
180 VOID
181 EFIAPI
182 WriteBootToOsPerformanceData (
183 IN EFI_EVENT Event,
184 IN VOID *Context
185 )
186 {
187 EFI_STATUS Status;
188 UINT32 LimitCount;
189 EFI_HANDLE *Handles;
190 UINTN NoHandles;
191 CHAR8 GaugeString[PERF_TOKEN_LENGTH];
192 UINT8 *Ptr;
193 UINT32 Index;
194 UINT64 Ticker;
195 UINT64 Freq;
196 UINT32 Duration;
197 UINTN LogEntryKey;
198 CONST VOID *Handle;
199 CONST CHAR8 *Token;
200 CONST CHAR8 *Module;
201 UINT64 StartTicker;
202 UINT64 EndTicker;
203 UINT64 StartValue;
204 UINT64 EndValue;
205 BOOLEAN CountUp;
206 UINTN EntryIndex;
207 UINTN NumPerfEntries;
208 //
209 // List of flags indicating PerfEntry contains DXE handle
210 //
211 BOOLEAN *PerfEntriesAsDxeHandle;
212
213 //
214 // Record the performance data for End of BDS
215 //
216 PERF_END(NULL, "BDS", NULL, 0);
217
218 if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {
219 return;
220 }
221
222 //
223 // Retrieve time stamp count as early as possible
224 //
225 Ticker = GetPerformanceCounter ();
226
227 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
228
229 Freq = DivU64x32 (Freq, 1000);
230
231 mPerfHeader.CpuFreq = Freq;
232
233 //
234 // Record BDS raw performance data
235 //
236 if (EndValue >= StartValue) {
237 mPerfHeader.BDSRaw = Ticker - StartValue;
238 CountUp = TRUE;
239 } else {
240 mPerfHeader.BDSRaw = StartValue - Ticker;
241 CountUp = FALSE;
242 }
243
244 //
245 // Put Detailed performance data into memory
246 //
247 Handles = NULL;
248 Status = gBS->LocateHandleBuffer (
249 AllHandles,
250 NULL,
251 NULL,
252 &NoHandles,
253 &Handles
254 );
255 if (EFI_ERROR (Status)) {
256 return ;
257 }
258
259 Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));
260 LimitCount = (mAcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
261
262 NumPerfEntries = 0;
263 LogEntryKey = 0;
264 while ((LogEntryKey = GetPerformanceMeasurement (
265 LogEntryKey,
266 &Handle,
267 &Token,
268 &Module,
269 &StartTicker,
270 &EndTicker)) != 0) {
271 NumPerfEntries++;
272 }
273 PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
274 ASSERT (PerfEntriesAsDxeHandle != NULL);
275
276 //
277 // Get DXE drivers performance
278 //
279 for (Index = 0; Index < NoHandles; Index++) {
280 Ticker = 0;
281 LogEntryKey = 0;
282 EntryIndex = 0;
283 while ((LogEntryKey = GetPerformanceMeasurement (
284 LogEntryKey,
285 &Handle,
286 &Token,
287 &Module,
288 &StartTicker,
289 &EndTicker)) != 0) {
290 if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
291 PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
292 }
293 EntryIndex++;
294 if ((Handle == Handles[Index]) && (EndTicker != 0)) {
295 if (StartTicker == 1) {
296 StartTicker = StartValue;
297 }
298 if (EndTicker == 1) {
299 EndTicker = StartValue;
300 }
301 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
302 }
303 }
304
305 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
306
307 if (Duration > 0) {
308
309 GetNameFromHandle (Handles[Index], GaugeString);
310
311 AsciiStrCpy (mPerfData.Token, GaugeString);
312 mPerfData.Duration = Duration;
313
314 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
315 Ptr += sizeof (PERF_DATA);
316
317 mPerfHeader.Count++;
318 if (mPerfHeader.Count == LimitCount) {
319 goto Done;
320 }
321 }
322 }
323
324 //
325 // Get inserted performance data
326 //
327 LogEntryKey = 0;
328 EntryIndex = 0;
329 while ((LogEntryKey = GetPerformanceMeasurement (
330 LogEntryKey,
331 &Handle,
332 &Token,
333 &Module,
334 &StartTicker,
335 &EndTicker)) != 0) {
336 if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {
337
338 ZeroMem (&mPerfData, sizeof (PERF_DATA));
339
340 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);
341 if (StartTicker == 1) {
342 StartTicker = StartValue;
343 }
344 if (EndTicker == 1) {
345 EndTicker = StartValue;
346 }
347 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
348
349 mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
350
351 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
352 Ptr += sizeof (PERF_DATA);
353
354 mPerfHeader.Count++;
355 if (mPerfHeader.Count == LimitCount) {
356 goto Done;
357 }
358 }
359 EntryIndex++;
360 }
361
362 Done:
363
364 FreePool (Handles);
365 FreePool (PerfEntriesAsDxeHandle);
366
367 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
368
369 //
370 // Put performance data to Reserved memory
371 //
372 CopyMem (
373 (UINTN *) (UINTN) mAcpiLowMemoryBase,
374 &mPerfHeader,
375 sizeof (PERF_HEADER)
376 );
377
378 return ;
379 }