Cc: Liming Gao <liming.gao@intel.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Feng Tian <feng.tian@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
		
			
				
	
	
		
			318 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			318 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  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.
 | 
						|
 | 
						|
Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
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.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "InternalBm.h"
 | 
						|
 | 
						|
PERF_HEADER               mBmPerfHeader;
 | 
						|
PERF_DATA                 mBmPerfData;
 | 
						|
EFI_PHYSICAL_ADDRESS      mBmAcpiLowMemoryBase = 0x0FFFFFFFFULL;
 | 
						|
 | 
						|
/**
 | 
						|
  Get the short verion of PDB file name to be
 | 
						|
  used in performance data logging.
 | 
						|
 | 
						|
  @param PdbFileName     The long PDB file name.
 | 
						|
  @param GaugeString     The output string to be logged by performance logger.
 | 
						|
  @param StringSize      The buffer size of GaugeString in bytes.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
BmGetShortPdbFileName (
 | 
						|
  IN  CONST CHAR8  *PdbFileName,
 | 
						|
  OUT       CHAR8  *GaugeString,
 | 
						|
  IN        UINTN   StringSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Index;
 | 
						|
  UINTN Index1;
 | 
						|
  UINTN StartIndex;
 | 
						|
  UINTN EndIndex;
 | 
						|
 | 
						|
  if (PdbFileName == NULL) {
 | 
						|
    AsciiStrCpyS (GaugeString, StringSize, " ");
 | 
						|
  } else {
 | 
						|
    StartIndex = 0;
 | 
						|
    for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
 | 
						|
      ;
 | 
						|
 | 
						|
    for (Index = 0; PdbFileName[Index] != 0; Index++) {
 | 
						|
      if ((PdbFileName[Index] == '\\') || (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 == StringSize - 1) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    GaugeString[Index1] = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the name from the Driver handle, which can be a handle with
 | 
						|
  EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.
 | 
						|
  This name can be used in performance data logging.
 | 
						|
 | 
						|
  @param Handle          Driver handle.
 | 
						|
  @param GaugeString     The output string to be logged by performance logger.
 | 
						|
  @param StringSize      The buffer size of GaugeString in bytes.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
BmGetNameFromHandle (
 | 
						|
  IN  EFI_HANDLE     Handle,
 | 
						|
  OUT CHAR8          *GaugeString,
 | 
						|
  IN  UINTN          StringSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  EFI_LOADED_IMAGE_PROTOCOL   *Image;
 | 
						|
  CHAR8                       *PdbFileName;
 | 
						|
  EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
 | 
						|
 | 
						|
  AsciiStrCpyS (GaugeString, StringSize, " ");
 | 
						|
 | 
						|
  //
 | 
						|
  // 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) {
 | 
						|
    BmGetShortPdbFileName (PdbFileName, GaugeString, StringSize);
 | 
						|
  }
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Writes performance data of booting into the allocated memory.
 | 
						|
  OS can process these records.
 | 
						|
 | 
						|
  @param  Event                 The triggered event.
 | 
						|
  @param  Context               Context for this event.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
BmWriteBootToOsPerformanceData (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  UINT32                    LimitCount;
 | 
						|
  EFI_HANDLE                *Handles;
 | 
						|
  UINTN                     NoHandles;
 | 
						|
  CHAR8                     GaugeString[PERF_TOKEN_SIZE];
 | 
						|
  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;
 | 
						|
  UINTN                     VarSize;
 | 
						|
  BOOLEAN                   Found;
 | 
						|
 | 
						|
  //
 | 
						|
  // Record the performance data for End of BDS
 | 
						|
  //
 | 
						|
  PERF_END(NULL, "BDS", NULL, 0);
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrieve time stamp count as early as possible
 | 
						|
  //
 | 
						|
  Ticker  = GetPerformanceCounter ();
 | 
						|
 | 
						|
  Freq    = GetPerformanceCounterProperties (&StartValue, &EndValue);
 | 
						|
  
 | 
						|
  Freq    = DivU64x32 (Freq, 1000);
 | 
						|
 | 
						|
  mBmPerfHeader.CpuFreq = Freq;
 | 
						|
 | 
						|
  //
 | 
						|
  // Record BDS raw performance data
 | 
						|
  //
 | 
						|
  if (EndValue >= StartValue) {
 | 
						|
    mBmPerfHeader.BDSRaw = Ticker - StartValue;
 | 
						|
    CountUp            = TRUE;
 | 
						|
  } else {
 | 
						|
    mBmPerfHeader.BDSRaw = StartValue - Ticker;
 | 
						|
    CountUp            = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Reset the entry count
 | 
						|
  //
 | 
						|
  mBmPerfHeader.Count = 0;
 | 
						|
 | 
						|
  if (mBmAcpiLowMemoryBase == 0x0FFFFFFFF) {
 | 
						|
    VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
 | 
						|
    Status = gRT->GetVariable (
 | 
						|
                    L"PerfDataMemAddr",
 | 
						|
                    &gPerformanceProtocolGuid,
 | 
						|
                    NULL,
 | 
						|
                    &VarSize,
 | 
						|
                    &mBmAcpiLowMemoryBase
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Fail to get the variable, return.
 | 
						|
      //
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Put Detailed performance data into memory
 | 
						|
  //
 | 
						|
  Handles = NULL;
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  AllHandles,
 | 
						|
                  NULL,
 | 
						|
                  NULL,
 | 
						|
                  &NoHandles,
 | 
						|
                  &Handles
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  Ptr        = (UINT8 *) ((UINT32) mBmAcpiLowMemoryBase + sizeof (PERF_HEADER));
 | 
						|
  LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
 | 
						|
 | 
						|
  //
 | 
						|
  // Get performance data
 | 
						|
  //
 | 
						|
  LogEntryKey = 0;
 | 
						|
  while ((LogEntryKey = GetPerformanceMeasurement (
 | 
						|
                          LogEntryKey,
 | 
						|
                          &Handle,
 | 
						|
                          &Token,
 | 
						|
                          &Module,
 | 
						|
                          &StartTicker,
 | 
						|
                          &EndTicker)) != 0) {
 | 
						|
    if (EndTicker != 0) {
 | 
						|
      if (StartTicker == 1) {
 | 
						|
        StartTicker = StartValue;
 | 
						|
      }
 | 
						|
      if (EndTicker == 1) {
 | 
						|
        EndTicker = StartValue;
 | 
						|
      }
 | 
						|
      Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
 | 
						|
 | 
						|
      Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
 | 
						|
      if (Duration == 0) {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      ZeroMem (&mBmPerfData, sizeof (PERF_DATA));
 | 
						|
 | 
						|
      mBmPerfData.Duration = Duration;
 | 
						|
 | 
						|
      //
 | 
						|
      // See if the Handle is in the handle buffer
 | 
						|
      //
 | 
						|
      Found = FALSE;
 | 
						|
      for (Index = 0; Index < NoHandles; Index++) {
 | 
						|
        if (Handle == Handles[Index]) {
 | 
						|
          BmGetNameFromHandle (Handles[Index], GaugeString, PERF_TOKEN_SIZE);
 | 
						|
          AsciiStrCpyS (mBmPerfData.Token, PERF_TOKEN_SIZE, GaugeString);
 | 
						|
          Found = TRUE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (!Found) {
 | 
						|
        AsciiStrnCpyS (mBmPerfData.Token, PERF_TOKEN_SIZE, Token, PERF_TOKEN_LENGTH);
 | 
						|
      }
 | 
						|
 | 
						|
      CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
 | 
						|
      Ptr += sizeof (PERF_DATA);
 | 
						|
 | 
						|
      mBmPerfHeader.Count++;
 | 
						|
      if (mBmPerfHeader.Count == LimitCount) {
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
Done:
 | 
						|
 | 
						|
  FreePool (Handles);
 | 
						|
 | 
						|
  mBmPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Put performance data to Reserved memory
 | 
						|
  //
 | 
						|
  CopyMem (
 | 
						|
    (UINTN *) (UINTN) mBmAcpiLowMemoryBase,
 | 
						|
    &mBmPerfHeader,
 | 
						|
    sizeof (PERF_HEADER)
 | 
						|
    );
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 |