]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/GenericBdsLib/Performance.c
29547a3b4249475a73d03343ee250b16404cd24b
[mirror_edk2.git] / MdeModulePkg / 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 STATIC PERF_HEADER mPerfHeader;
20 STATIC PERF_DATA mPerfData;
21
22 STATIC
23 VOID
24 GetShortPdbFileName (
25 CHAR8 *PdbFileName,
26 CHAR8 *GaugeString
27 )
28 /*++
29
30 Routine Description:
31
32 Arguments:
33
34 Returns:
35
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 STATIC
76 VOID
77 GetNameFromHandle (
78 IN EFI_HANDLE Handle,
79 OUT CHAR8 *GaugeString
80 )
81 {
82 EFI_STATUS Status;
83 EFI_LOADED_IMAGE_PROTOCOL *Image;
84 CHAR8 *PdbFileName;
85 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
86
87 AsciiStrCpy (GaugeString, " ");
88
89 //
90 // Get handle name from image protocol
91 //
92 Status = gBS->HandleProtocol (
93 Handle,
94 &gEfiLoadedImageProtocolGuid,
95 (VOID **) &Image
96 );
97
98 if (EFI_ERROR (Status)) {
99 Status = gBS->OpenProtocol (
100 Handle,
101 &gEfiDriverBindingProtocolGuid,
102 (VOID **) &DriverBinding,
103 NULL,
104 NULL,
105 EFI_OPEN_PROTOCOL_GET_PROTOCOL
106 );
107 if (EFI_ERROR (Status)) {
108 return ;
109 }
110 //
111 // Get handle name from image protocol
112 //
113 Status = gBS->HandleProtocol (
114 DriverBinding->ImageHandle,
115 &gEfiLoadedImageProtocolGuid,
116 (VOID **) &Image
117 );
118 }
119
120 PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
121
122 if (PdbFileName != NULL) {
123 GetShortPdbFileName (PdbFileName, GaugeString);
124 }
125
126 return ;
127 }
128
129 VOID
130 WriteBootToOsPerformanceData (
131 VOID
132 )
133 /*++
134
135 Routine Description:
136
137 Allocates a block of memory and writes performance data of booting to OS into it.
138
139 Arguments:
140
141 None
142
143 Returns:
144
145 None
146
147 --*/
148 {
149 EFI_STATUS Status;
150 EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase;
151 UINT32 AcpiLowMemoryLength;
152 UINT32 LimitCount;
153 EFI_HANDLE *Handles;
154 UINTN NoHandles;
155 CHAR8 GaugeString[PERF_TOKEN_LENGTH];
156 UINT8 *Ptr;
157 UINT32 Index;
158 UINT64 Ticker;
159 UINT64 Freq;
160 UINT32 Duration;
161 UINTN LogEntryKey;
162 CONST VOID *Handle;
163 CONST CHAR8 *Token;
164 CONST CHAR8 *Module;
165 UINT64 StartTicker;
166 UINT64 EndTicker;
167 UINT64 StartValue;
168 UINT64 EndValue;
169 BOOLEAN CountUp;
170
171 //
172 // Retrive time stamp count as early as possilbe
173 //
174 Ticker = GetPerformanceCounter ();
175
176 Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
177
178 Freq = DivU64x32 (Freq, 1000);
179
180 mPerfHeader.CpuFreq = Freq;
181
182 //
183 // Record BDS raw performance data
184 //
185 if (EndValue >= StartValue) {
186 mPerfHeader.BDSRaw = Ticker - StartValue;
187 CountUp = TRUE;
188 } else {
189 mPerfHeader.BDSRaw = StartValue - Ticker;
190 CountUp = FALSE;
191 }
192
193 AcpiLowMemoryLength = 0x2000;
194
195 //
196 // Allocate a block of memory that contain performance data to OS
197 //
198 Status = gBS->AllocatePages (
199 AllocateAnyPages,
200 EfiACPIReclaimMemory,
201 EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),
202 &AcpiLowMemoryBase
203 );
204 if (EFI_ERROR (Status)) {
205 return ;
206 }
207
208
209 Ptr = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER));
210 LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
211
212 //
213 // Put Detailed performance data into memory
214 //
215 Handles = NULL;
216 Status = gBS->LocateHandleBuffer (
217 AllHandles,
218 NULL,
219 NULL,
220 &NoHandles,
221 &Handles
222 );
223 if (EFI_ERROR (Status)) {
224 gBS->FreePages (AcpiLowMemoryBase, 1);
225 return ;
226 }
227 //
228 // Get DXE drivers performance
229 //
230 for (Index = 0; Index < NoHandles; Index++) {
231 Ticker = 0;
232 LogEntryKey = 0;
233 while ((LogEntryKey = GetPerformanceMeasurement (
234 LogEntryKey,
235 &Handle,
236 &Token,
237 &Module,
238 &StartTicker,
239 &EndTicker)) != 0) {
240 if ((Handle == Handles[Index]) && (EndTicker != 0)) {
241 Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
242 }
243 }
244
245 Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
246
247 if (Duration > 0) {
248
249 GetNameFromHandle (Handles[Index], GaugeString);
250
251 AsciiStrCpy (mPerfData.Token, GaugeString);
252 mPerfData.Duration = Duration;
253
254 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
255 Ptr += sizeof (PERF_DATA);
256
257 mPerfHeader.Count++;
258 if (mPerfHeader.Count == LimitCount) {
259 goto Done;
260 }
261 }
262 }
263
264 FreePool (Handles);
265
266 //
267 // Get inserted performance data
268 //
269 LogEntryKey = 0;
270 while ((LogEntryKey = GetPerformanceMeasurement (
271 LogEntryKey,
272 &Handle,
273 &Token,
274 &Module,
275 &StartTicker,
276 &EndTicker)) != 0) {
277 if (Handle == NULL && EndTicker != 0) {
278
279 ZeroMem (&mPerfData, sizeof (PERF_DATA));
280
281 AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);
282 Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
283
284 mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
285
286 CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
287 Ptr += sizeof (PERF_DATA);
288
289 mPerfHeader.Count++;
290 if (mPerfHeader.Count == LimitCount) {
291 goto Done;
292 }
293 }
294 }
295
296 Done:
297
298 mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
299
300 //
301 // Put performance data to memory
302 //
303 CopyMem (
304 (UINTN *) (UINTN) AcpiLowMemoryBase,
305 &mPerfHeader,
306 sizeof (PERF_HEADER)
307 );
308
309 gRT->SetVariable (
310 L"PerfDataMemAddr",
311 &gEfiGenericPlatformVariableGuid,
312 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
313 sizeof (EFI_PHYSICAL_ADDRESS),
314 &AcpiLowMemoryBase
315 );
316
317 return ;
318 }