]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c
Update for the performance infrastructure changes:
[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 - 2008, Intel Corporation. <BR>
7 All rights reserved. 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
22 /**
23 Get the short verion of PDB file name to be
24 used in performance data logging.
25
26 @param PdbFileName The long PDB file name.
27 @param GaugeString The output string to be logged by performance logger.
28
29 **/
30 VOID
31 GetShortPdbFileName (
32 IN CONST CHAR8 *PdbFileName,
33 OUT CHAR8 *GaugeString
34 )
35 {
36 UINTN Index;
37 UINTN Index1;
38 UINTN StartIndex;
39 UINTN EndIndex;
40
41 if (PdbFileName == NULL) {
42 AsciiStrCpy (GaugeString, " ");
43 } else {
44 StartIndex = 0;
45 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
46 ;
47
48 for (Index = 0; PdbFileName[Index] != 0; Index++) {
49 if (PdbFileName[Index] == '\\') {
50 StartIndex = Index + 1;
51 }
52
53 if (PdbFileName[Index] == '.') {
54 EndIndex = Index;
55 }
56 }
57
58 Index1 = 0;
59 for (Index = StartIndex; Index < EndIndex; Index++) {
60 GaugeString[Index1] = PdbFileName[Index];
61 Index1++;
62 if (Index1 == PERF_TOKEN_LENGTH - 1) {
63 break;
64 }
65 }
66
67 GaugeString[Index1] = 0;
68 }
69
70 return ;
71 }
72
73 /**
74 Get the name from the Driver handle, which can be a handle with
75 EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.
76 This name can be used in performance data logging.
77
78 @param Handle Driver handle.
79 @param GaugeString The output string to be logged by performance logger.
80
81 **/
82 VOID
83 GetNameFromHandle (
84 IN EFI_HANDLE Handle,
85 OUT CHAR8 *GaugeString
86 )
87 {
88 EFI_STATUS Status;
89 EFI_LOADED_IMAGE_PROTOCOL *Image;
90 CHAR8 *PdbFileName;
91 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
92
93 AsciiStrCpy (GaugeString, " ");
94
95 //
96 // Get handle name from image protocol
97 //
98 Status = gBS->HandleProtocol (
99 Handle,
100 &gEfiLoadedImageProtocolGuid,
101 (VOID **) &Image
102 );
103
104 if (EFI_ERROR (Status)) {
105 Status = gBS->OpenProtocol (
106 Handle,
107 &gEfiDriverBindingProtocolGuid,
108 (VOID **) &DriverBinding,
109 NULL,
110 NULL,
111 EFI_OPEN_PROTOCOL_GET_PROTOCOL
112 );
113 if (EFI_ERROR (Status)) {
114 return ;
115 }
116 //
117 // Get handle name from image protocol
118 //
119 Status = gBS->HandleProtocol (
120 DriverBinding->ImageHandle,
121 &gEfiLoadedImageProtocolGuid,
122 (VOID **) &Image
123 );
124 }
125
126 PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
127
128 if (PdbFileName != NULL) {
129 GetShortPdbFileName (PdbFileName, GaugeString);
130 }
131
132 return ;
133 }
134
135 /**
136
137 Allocates a block of memory and writes performance data of booting into it.
138 OS can processing these record.
139
140 **/
141 VOID
142 WriteBootToOsPerformanceData (
143 VOID
144 )
145 {
146 EFI_STATUS Status;
147 EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase;
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
168 //
169 // Retrieve time stamp count as early as possible
170 //
171 Ticker = GetPerformanceCounter ();
172
173 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
174
175 Freq = DivU64x32 (Freq, 1000);
176
177 mPerfHeader.CpuFreq = Freq;
178
179 //
180 // Record BDS raw performance data
181 //
182 if (EndValue >= StartValue) {
183 mPerfHeader.BDSRaw = Ticker - StartValue;
184 CountUp = TRUE;
185 } else {
186 mPerfHeader.BDSRaw = StartValue - Ticker;
187 CountUp = FALSE;
188 }
189
190 AcpiLowMemoryLength = 0x2000;
191
192 //
193 // Allocate a block of memory that contain performance data to OS
194 //
195 Status = gBS->AllocatePages (
196 AllocateAnyPages,
197 EfiACPIReclaimMemory,
198 EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),
199 &AcpiLowMemoryBase
200 );
201 if (EFI_ERROR (Status)) {
202 return ;
203 }
204
205
206 Ptr = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER));
207 LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
208
209 //
210 // Put Detailed performance data into memory
211 //
212 Handles = NULL;
213 Status = gBS->LocateHandleBuffer (
214 AllHandles,
215 NULL,
216 NULL,
217 &NoHandles,
218 &Handles
219 );
220 if (EFI_ERROR (Status)) {
221 gBS->FreePages (AcpiLowMemoryBase, 1);
222 return ;
223 }
224
225 //
226 // Get DXE drivers performance
227 //
228 for (Index = 0; Index < NoHandles; Index++) {
229 Ticker = 0;
230 LogEntryKey = 0;
231 while ((LogEntryKey = GetPerformanceMeasurement (
232 LogEntryKey,
233 &Handle,
234 &Token,
235 &Module,
236 &StartTicker,
237 &EndTicker)) != 0) {
238 if ((Handle == Handles[Index]) && (EndTicker != 0)) {
239 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
240 }
241 }
242
243 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
244
245 if (Duration > 0) {
246
247 GetNameFromHandle (Handles[Index], GaugeString);
248
249 AsciiStrCpy (mPerfData.Token, GaugeString);
250 mPerfData.Duration = Duration;
251
252 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
253 Ptr += sizeof (PERF_DATA);
254
255 mPerfHeader.Count++;
256 if (mPerfHeader.Count == LimitCount) {
257 goto Done;
258 }
259 }
260 }
261
262 FreePool (Handles);
263
264 //
265 // Get inserted performance data
266 //
267 LogEntryKey = 0;
268 while ((LogEntryKey = GetPerformanceMeasurement (
269 LogEntryKey,
270 &Handle,
271 &Token,
272 &Module,
273 &StartTicker,
274 &EndTicker)) != 0) {
275 if (Handle == NULL && EndTicker != 0) {
276
277 ZeroMem (&mPerfData, sizeof (PERF_DATA));
278
279 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);
280 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
281
282 mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
283
284 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
285 Ptr += sizeof (PERF_DATA);
286
287 mPerfHeader.Count++;
288 if (mPerfHeader.Count == LimitCount) {
289 goto Done;
290 }
291 }
292 }
293
294 Done:
295
296 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
297
298 //
299 // Put performance data to ACPI memory
300 //
301 CopyMem (
302 (UINTN *) (UINTN) AcpiLowMemoryBase,
303 &mPerfHeader,
304 sizeof (PERF_HEADER)
305 );
306
307 gRT->SetVariable (
308 L"PerfDataMemAddr",
309 &gPerformanceProtocolGuid,
310 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
311 sizeof (EFI_PHYSICAL_ADDRESS),
312 &AcpiLowMemoryBase
313 );
314
315 return ;
316 }