From 8033e9314810ae2e7544bd35fa30451f0a8b7d16 Mon Sep 17 00:00:00 2001 From: tgingold Date: Mon, 12 Feb 2007 23:39:38 +0000 Subject: EdkGenericBdsLib added git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2367 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Library/EdkGenericBdsLib/Performance.c | 399 +++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 EdkModulePkg/Library/EdkGenericBdsLib/Performance.c (limited to 'EdkModulePkg/Library/EdkGenericBdsLib/Performance.c') diff --git a/EdkModulePkg/Library/EdkGenericBdsLib/Performance.c b/EdkModulePkg/Library/EdkGenericBdsLib/Performance.c new file mode 100644 index 0000000000..1d92a4d5f6 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericBdsLib/Performance.c @@ -0,0 +1,399 @@ +/*++ + +Copyright (c) 2006, 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 "Performance.h" + +VOID +ClearDebugRegisters ( + VOID + ) +{ + // + // BugBug: We should not need to do this. We need to root cause this bug!!!! + // + AsmWriteDr0 (0); + AsmWriteDr1 (0); +} + +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 +CHAR8 * +GetPdbPath ( + VOID *ImageBase + ) +/*++ + +Routine Description: + + Located PDB path name in PE image + +Arguments: + + ImageBase - base of PE to search + +Returns: + + Pointer into image at offset of PDB file name if PDB file name is found, + Otherwise a pointer to an empty string. + +--*/ +{ + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = ImageBase; + ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; + + PeCoffLoaderGetImageInfo (&ImageContext); + + return ImageContext.PdbPointer; +} + + +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 = GetPdbPath (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_CPU_ARCH_PROTOCOL *Cpu; + EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase; + UINT32 mAcpiLowMemoryLength; + UINT32 LimitCount; + PERF_HEADER mPerfHeader; + PERF_DATA mPerfData; + EFI_HANDLE *Handles; + UINTN NoHandles; + CHAR8 GaugeString[PERF_TOKEN_LENGTH]; + UINT8 *Ptr; + UINT32 mIndex; + UINT64 Ticker; + UINT64 Freq; + UINT32 Duration; + UINT64 CurrentTicker; + UINT64 TimerPeriod; + UINTN LogEntryKey; + CONST VOID *Handle; + CONST CHAR8 *Token; + CONST CHAR8 *Module; + UINT64 StartTicker; + UINT64 EndTicker; + + // + // Retrive time stamp count as early as possilbe + // + Ticker = AsmReadTsc (); + + // + // Allocate a block of memory that contain performance data to OS + // + mAcpiLowMemoryBase = 0xFFFFFFFF; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + 4, + &mAcpiLowMemoryBase + ); + if (EFI_ERROR (Status)) { + return ; + } + + mAcpiLowMemoryLength = EFI_PAGES_TO_SIZE(4); + + Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER)); + LimitCount = (mAcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA); + + // + // Initialize performance data structure + // + ZeroMem (&mPerfHeader, sizeof (PERF_HEADER)); + + // + // Get CPU frequency + // + Status = gBS->LocateProtocol ( + &gEfiCpuArchProtocolGuid, + NULL, + (VOID **)&Cpu + ); + if (EFI_ERROR (Status)) { + gBS->FreePages (mAcpiLowMemoryBase, 4); + return ; + } + // + // Get Cpu Frequency + // + Status = Cpu->GetTimerValue (Cpu, 0, &(CurrentTicker), &TimerPeriod); + if (EFI_ERROR (Status)) { + gBS->FreePages (mAcpiLowMemoryBase, 4); + return ; + } + + Freq = DivU64x32 (1000000000000ULL, (UINTN) TimerPeriod); + + mPerfHeader.CpuFreq = Freq; + + // + // Record BDS raw performance data + // + mPerfHeader.BDSRaw = Ticker; + + // + // Put Detailed performance data into memory + // + Handles = NULL; + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + gBS->FreePages (mAcpiLowMemoryBase, 4); + return ; + } + // + // Get DXE drivers performance + // + for (mIndex = 0; mIndex < NoHandles; mIndex++) { + Ticker = 0; + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Handle, + &Token, + &Module, + &StartTicker, + &EndTicker)) != 0) { + if ((Handle == Handles[mIndex]) && (StartTicker < EndTicker)) { + Ticker += (EndTicker - StartTicker); + } + } + + Duration = (UINT32) DivU64x32 ( + Ticker, + (UINT32) Freq + ); + + if (Duration > 0) { + ZeroMem (&mPerfData, sizeof (PERF_DATA)); + + GetNameFromHandle (Handles[mIndex], 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; + } + } + } + + gBS->FreePool (Handles); + + // + // Get inserted performance data + // + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Handle, + &Token, + &Module, + &StartTicker, + &EndTicker)) != 0) { + if ((Handle == NULL) && (StartTicker <= EndTicker)) { + + ZeroMem (&mPerfData, sizeof (PERF_DATA)); + + AsciiStrnCpy (mPerfData.Token, Token, DXE_PERFORMANCE_STRING_SIZE); + mPerfData.Duration = (UINT32) DivU64x32 ( + EndTicker - StartTicker, + (UINT32) Freq + ); + + CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA)); + Ptr += sizeof (PERF_DATA); + + mPerfHeader.Count++; + if (mPerfHeader.Count == LimitCount) { + goto Done; + } + } + } + +Done: + + ClearDebugRegisters (); + + mPerfHeader.Signiture = 0x66726550; + + // + // Put performance data to memory + // + CopyMem ( + (UINT32 *) (UINT32) mAcpiLowMemoryBase, + &mPerfHeader, + sizeof (PERF_HEADER) + ); + + gRT->SetVariable ( + L"PerfDataMemAddr", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (UINT32), + (VOID *) &mAcpiLowMemoryBase + ); + + return ; +} -- cgit v1.2.3