| /** @file |
| |
| Copyright (c) 2004 - 2007, Intel Corporation |
| All rights reserved. This program and the accompanying materials |
| are licensed and made available under the terms and conditions of the BSD License |
| which accompanies this distribution. The full text of the license may be found at |
| http://opensource.org/licenses/bsd-license.php |
| |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. |
| |
| Module Name: |
| |
| Performance.c |
| |
| Abstract: |
| |
| This file include the file which can help to get the system |
| performance, all the function will only include if the performance |
| switch is set. |
| |
| |
| **/ |
| |
| #include "InternalBdsLib.h" |
| |
| STATIC PERF_HEADER mPerfHeader; |
| STATIC PERF_DATA mPerfData; |
| |
| STATIC |
| VOID |
| GetShortPdbFileName ( |
| CHAR8 *PdbFileName, |
| CHAR8 *GaugeString |
| ) |
| /*++ |
| |
| Routine Description: |
| |
| Arguments: |
| |
| Returns: |
| |
| --*/ |
| { |
| UINTN Index; |
| UINTN Index1; |
| UINTN StartIndex; |
| UINTN EndIndex; |
| |
| if (PdbFileName == NULL) { |
| AsciiStrCpy (GaugeString, " "); |
| } else { |
| StartIndex = 0; |
| for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++) |
| ; |
| |
| for (Index = 0; PdbFileName[Index] != 0; Index++) { |
| if (PdbFileName[Index] == '\\') { |
| StartIndex = Index + 1; |
| } |
| |
| if (PdbFileName[Index] == '.') { |
| EndIndex = Index; |
| } |
| } |
| |
| Index1 = 0; |
| for (Index = StartIndex; Index < EndIndex; Index++) { |
| GaugeString[Index1] = PdbFileName[Index]; |
| Index1++; |
| if (Index1 == PERF_TOKEN_LENGTH - 1) { |
| break; |
| } |
| } |
| |
| GaugeString[Index1] = 0; |
| } |
| |
| return ; |
| } |
| |
| STATIC |
| VOID |
| GetNameFromHandle ( |
| IN EFI_HANDLE Handle, |
| OUT CHAR8 *GaugeString |
| ) |
| { |
| EFI_STATUS Status; |
| EFI_LOADED_IMAGE_PROTOCOL *Image; |
| CHAR8 *PdbFileName; |
| EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; |
| |
| AsciiStrCpy (GaugeString, " "); |
| |
| // |
| // Get handle name from image protocol |
| // |
| Status = gBS->HandleProtocol ( |
| Handle, |
| &gEfiLoadedImageProtocolGuid, |
| (VOID **) &Image |
| ); |
| |
| if (EFI_ERROR (Status)) { |
| Status = gBS->OpenProtocol ( |
| Handle, |
| &gEfiDriverBindingProtocolGuid, |
| (VOID **) &DriverBinding, |
| NULL, |
| NULL, |
| EFI_OPEN_PROTOCOL_GET_PROTOCOL |
| ); |
| if (EFI_ERROR (Status)) { |
| return ; |
| } |
| // |
| // Get handle name from image protocol |
| // |
| Status = gBS->HandleProtocol ( |
| DriverBinding->ImageHandle, |
| &gEfiLoadedImageProtocolGuid, |
| (VOID **) &Image |
| ); |
| } |
| |
| PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase); |
| |
| if (PdbFileName != NULL) { |
| GetShortPdbFileName (PdbFileName, GaugeString); |
| } |
| |
| return ; |
| } |
| |
| VOID |
| WriteBootToOsPerformanceData ( |
| VOID |
| ) |
| /*++ |
| |
| Routine Description: |
| |
| Allocates a block of memory and writes performance data of booting to OS into it. |
| |
| Arguments: |
| |
| None |
| |
| Returns: |
| |
| None |
| |
| --*/ |
| { |
| EFI_STATUS Status; |
| EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase; |
| UINT32 AcpiLowMemoryLength; |
| UINT32 LimitCount; |
| EFI_HANDLE *Handles; |
| UINTN NoHandles; |
| CHAR8 GaugeString[PERF_TOKEN_LENGTH]; |
| UINT8 *Ptr; |
| UINT32 Index; |
| UINT64 Ticker; |
| UINT64 Freq; |
| UINT32 Duration; |
| UINTN LogEntryKey; |
| CONST VOID *Handle; |
| CONST CHAR8 *Token; |
| CONST CHAR8 *Module; |
| UINT64 StartTicker; |
| UINT64 EndTicker; |
| UINT64 StartValue; |
| UINT64 EndValue; |
| BOOLEAN CountUp; |
| |
| // |
| // Retrive time stamp count as early as possilbe |
| // |
| Ticker = GetPerformanceCounter (); |
| |
| Freq = GetPerformanceCounterProperties (&StartValue, &EndValue); |
| |
| Freq = DivU64x32 (Freq, 1000); |
| |
| mPerfHeader.CpuFreq = Freq; |
| |
| // |
| // Record BDS raw performance data |
| // |
| if (EndValue >= StartValue) { |
| mPerfHeader.BDSRaw = Ticker - StartValue; |
| CountUp = TRUE; |
| } else { |
| mPerfHeader.BDSRaw = StartValue - Ticker; |
| CountUp = FALSE; |
| } |
| |
| AcpiLowMemoryLength = 0x2000; |
| |
| // |
| // Allocate a block of memory that contain performance data to OS |
| // |
| Status = gBS->AllocatePages ( |
| AllocateAnyPages, |
| EfiACPIReclaimMemory, |
| EFI_SIZE_TO_PAGES (AcpiLowMemoryLength), |
| &AcpiLowMemoryBase |
| ); |
| if (EFI_ERROR (Status)) { |
| return ; |
| } |
| |
| |
| Ptr = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER)); |
| LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA); |
| |
| // |
| // Put Detailed performance data into memory |
| // |
| Handles = NULL; |
| Status = gBS->LocateHandleBuffer ( |
| AllHandles, |
| NULL, |
| NULL, |
| &NoHandles, |
| &Handles |
| ); |
| if (EFI_ERROR (Status)) { |
| gBS->FreePages (AcpiLowMemoryBase, 1); |
| return ; |
| } |
| // |
| // Get DXE drivers performance |
| // |
| for (Index = 0; Index < NoHandles; Index++) { |
| Ticker = 0; |
| LogEntryKey = 0; |
| while ((LogEntryKey = GetPerformanceMeasurement ( |
| LogEntryKey, |
| &Handle, |
| &Token, |
| &Module, |
| &StartTicker, |
| &EndTicker)) != 0) { |
| if ((Handle == Handles[Index]) && (EndTicker != 0)) { |
| Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker); |
| } |
| } |
| |
| Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq); |
| |
| if (Duration > 0) { |
| |
| GetNameFromHandle (Handles[Index], GaugeString); |
| |
| AsciiStrCpy (mPerfData.Token, GaugeString); |
| mPerfData.Duration = Duration; |
| |
| CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA)); |
| Ptr += sizeof (PERF_DATA); |
| |
| mPerfHeader.Count++; |
| if (mPerfHeader.Count == LimitCount) { |
| goto Done; |
| } |
| } |
| } |
| |
| FreePool (Handles); |
| |
| // |
| // Get inserted performance data |
| // |
| LogEntryKey = 0; |
| while ((LogEntryKey = GetPerformanceMeasurement ( |
| LogEntryKey, |
| &Handle, |
| &Token, |
| &Module, |
| &StartTicker, |
| &EndTicker)) != 0) { |
| if (Handle == NULL && EndTicker != 0) { |
| |
| ZeroMem (&mPerfData, sizeof (PERF_DATA)); |
| |
| AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH); |
| Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker); |
| |
| mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq); |
| |
| CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA)); |
| Ptr += sizeof (PERF_DATA); |
| |
| mPerfHeader.Count++; |
| if (mPerfHeader.Count == LimitCount) { |
| goto Done; |
| } |
| } |
| } |
| |
| Done: |
| |
| mPerfHeader.Signiture = PERFORMANCE_SIGNATURE; |
| |
| // |
| // Put performance data to memory |
| // |
| CopyMem ( |
| (UINTN *) (UINTN) AcpiLowMemoryBase, |
| &mPerfHeader, |
| sizeof (PERF_HEADER) |
| ); |
| |
| gRT->SetVariable ( |
| L"PerfDataMemAddr", |
| &gEfiGenericPlatformVariableGuid, |
| EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, |
| sizeof (EFI_PHYSICAL_ADDRESS), |
| &AcpiLowMemoryBase |
| ); |
| |
| return ; |
| } |