Example #1
0
/*
================
Sys_DoubleTime
================
*/
double Sys_DoubleTime( void )
{
	static longtime_t g_PerformanceFrequency;
	static longtime_t g_ClockStart;
	longtime_t CurrentTime;
#ifdef XASH_SDL
	if( !g_PerformanceFrequency )
	{
		g_PerformanceFrequency = SDL_GetPerformanceFrequency();
		g_ClockStart = SDL_GetPerformanceCounter();
	}
	CurrentTime = SDL_GetPerformanceCounter();
	return (double)( CurrentTime - g_ClockStart ) / (double)( g_PerformanceFrequency );
#elif _WIN32
	if( !g_PerformanceFrequency )
	{
		g_PerformanceFrequency = GetPerformanceFrequency();
		g_ClockStart = GetPerformanceCounter();
	}
	CurrentTime = GetPerformanceCounter();
	return (double)( CurrentTime - g_ClockStart ) / (double)( g_PerformanceFrequency );

#else
	struct timespec ts;
	if( !g_PerformanceFrequency )
	{
		struct timespec res;
		if( !clock_getres(CLOCK_MONOTONIC, &res) )
			g_PerformanceFrequency = 1000000000LL/res.tv_nsec;
	}
	clock_gettime(CLOCK_MONOTONIC, &ts);
	return (double) ts.tv_sec + (double) ts.tv_nsec/1000000000.0;
#endif
}
Example #2
0
EFIAPI
AcquireSpinLock (
  IN OUT  SPIN_LOCK                 *SpinLock
  )
{
  UINT64                            Tick;
  UINT64                            Start, End;
  UINT64                            Timeout;

  Tick = 0;
  Start = 0;
  End = 0;
  if (PcdGet32 (PcdSpinLockTimeout) > 0) {
    Tick = GetPerformanceCounter ();
    Timeout = DivU64x32 (
                MultU64x32 (
                  GetPerformanceCounterProperties (&Start, &End),
                  PcdGet32 (PcdSpinLockTimeout)
                  ),
                1000000
                );
    if (Start < End) {
      Tick += Timeout;
    } else {
      Tick -= Timeout;
    }
  }

  while (!AcquireSpinLockOrFail (SpinLock)) {
    CpuPause ();
    ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ()));
  }
  return SpinLock;
}
Example #3
0
/**
  Fills in the end time of a performance measurement.

  Looks up the record that matches Handle, Token, Module and Identifier.
  If the record can not be found then return RETURN_NOT_FOUND.
  If the record is found and TimeStamp is not zero,
  then TimeStamp is added to the record as the end time.
  If the record is found and TimeStamp is zero, then this function reads
  the current time stamp and adds that time stamp value to the record as the end time.

  @param  Handle                  Pointer to environment specific context used
                                  to identify the component being measured.
  @param  Token                   Pointer to a Null-terminated ASCII string
                                  that identifies the component being measured.
  @param  Module                  Pointer to a Null-terminated ASCII string
                                  that identifies the module being measured.
  @param  TimeStamp               64-bit time stamp.
  @param  Identifier              32-bit identifier. If the value is 0, the found record
                                  is same as the one found by EndPerformanceMeasurement.

  @retval RETURN_SUCCESS          The end of  the measurement was recorded.
  @retval RETURN_NOT_FOUND        The specified measurement record could not be found.

**/
RETURN_STATUS
EFIAPI
EndPerformanceMeasurementEx (
  IN CONST VOID   *Handle,  OPTIONAL
  IN CONST CHAR8  *Token,   OPTIONAL
  IN CONST CHAR8  *Module,  OPTIONAL
  IN UINT64       TimeStamp,
  IN UINT32       Identifier
  )
{
  PEI_PERFORMANCE_LOG_HEADER  *PeiPerformanceLog;
  UINT32                      *PeiPerformanceIdArray;
  PEI_PERFORMANCE_LOG_ENTRY   *LogEntryArray;
  UINT32                      Index;

  if (TimeStamp == 0) {
    TimeStamp = GetPerformanceCounter ();
  }

  InternalGetPerformanceHobLog (&PeiPerformanceLog, &PeiPerformanceIdArray);
  Index             = InternalSearchForLogEntry (PeiPerformanceLog, PeiPerformanceIdArray, Handle, Token, Module, Identifier);
  if (Index >= PeiPerformanceLog->NumberOfEntries) {
    return RETURN_NOT_FOUND;
  }
  LogEntryArray     = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1);
  LogEntryArray[Index].EndTimeStamp = TimeStamp;

  return RETURN_SUCCESS;
}
Example #4
0
void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void*)&nCounter, sizeof(nCounter));
}
Example #5
0
    HRESULT MyClock::GetAudioClockTime(REFERENCE_TIME* pAudioTime, REFERENCE_TIME* pCounterTime)
    {
        CheckPointer(pAudioTime, E_POINTER);

        CAutoLock lock(this);

        if (m_audioClock)
        {
            uint64_t audioFrequency, audioPosition, audioTime;
            if (SUCCEEDED(m_audioClock->GetFrequency(&audioFrequency)) &&
                SUCCEEDED(m_audioClock->GetPosition(&audioPosition, &audioTime)))
            {
                int64_t counterTime = llMulDiv(GetPerformanceCounter(), OneSecond, m_performanceFrequency, 0);
                int64_t clockTime = llMulDiv(audioPosition, OneSecond, audioFrequency, 0) +
                                    m_audioStart + (audioPosition > 0 ? m_audioOffset + counterTime - audioTime : 0);

                *pAudioTime = clockTime;

                if (pCounterTime)
                    *pCounterTime = counterTime;

                return S_OK;
            }
        }

        return E_FAIL;
    }
Example #6
0
/**
  Searches the performance measurement log from the beginning of the log
  for the first matching record that contains a zero end time and fills in a valid end time.

  Searches the performance measurement log from the beginning of the log
  for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
  If the record can not be found then return EFI_NOT_FOUND.
  If the record is found and TimeStamp is not zero,
  then the end time in the record is filled in with the value specified by TimeStamp.
  If the record is found and TimeStamp is zero, then the end time in the matching record
  is filled in with the current time stamp value.

  @param  Handle                  Pointer to environment specific context used
                                  to identify the component being measured.
  @param  Token                   Pointer to a Null-terminated ASCII string
                                  that identifies the component being measured.
  @param  Module                  Pointer to a Null-terminated ASCII string
                                  that identifies the module being measured.
  @param  TimeStamp               64-bit time stamp.
  @param  Identifier              32-bit identifier. If the value is 0, the found record
                                  is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.

  @retval EFI_SUCCESS             The end of  the measurement was recorded.
  @retval EFI_NOT_FOUND           The specified measurement record could not be found.

**/
EFI_STATUS
EFIAPI
EndGaugeEx (
  IN CONST VOID   *Handle,  OPTIONAL
  IN CONST CHAR8  *Token,   OPTIONAL
  IN CONST CHAR8  *Module,  OPTIONAL
  IN UINT64       TimeStamp,
  IN UINT32       Identifier
  )
{
  GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
  UINT32              Index;

  if (TimeStamp == 0) {
    TimeStamp = GetPerformanceCounter ();
  }

  Index = InternalSearchForGaugeEntry (Handle, Token, Module, Identifier);
  if (Index >= mGaugeData->NumberOfEntries) {
    return EFI_NOT_FOUND;
  }
  GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
  GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;

  return EFI_SUCCESS;
}
Example #7
0
VOID
CEntryPoint (
  IN  UINTN                     MpId,
  IN  UINTN                     UefiMemoryBase,
  IN  UINTN                     StacksBase
  )
{
  UINT64   StartTimeStamp;

  // Initialize the platform specific controllers
  ArmPlatformInitialize (MpId);

  if (PerformanceMeasurementEnabled ()) {
    // Initialize the Timer Library to setup the Timer HW controller
    TimerConstructor ();
    // We cannot call yet the PerformanceLib because the HOB List has not been initialized
    StartTimeStamp = GetPerformanceCounter ();
  } else {
    StartTimeStamp = 0;
  }

  // Data Cache enabled on Primary core when MMU is enabled.
  ArmDisableDataCache ();
  // Invalidate instruction cache
  ArmInvalidateInstructionCache ();
  // Enable Instruction Caches on all cores.
  ArmEnableInstructionCache ();

  PrePiMain (UefiMemoryBase, StacksBase, StartTimeStamp);

  // DXE Core should always load and never return
  ASSERT (FALSE);
}
Example #8
0
void RandAddSeed()
{
    // Seed with CPU performance counter
    int64 nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memset(&nCounter, 0, sizeof(nCounter));
}
Example #9
0
/**
  Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record
  performance data for ExitBootServicesEntry in FPDT.

  @param[in]  Event   The Event that is being processed.
  @param[in]  Context The Event Context.

**/
VOID
EFIAPI
FpdtExitBootServicesEventNotify (
  IN EFI_EVENT        Event,
  IN VOID             *Context
  )
{
  if (mAcpiBootPerformanceTable == NULL) {
    //
    // Firmware Performance Data Table not installed, do nothing.
    //
    return ;
  }

  //
  // Update Firmware Basic Boot Performance Record for UEFI boot.
  //
  mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry = GetTimeInNanoSecond (GetPerformanceCounter ());

  //
  // Dump FPDT Boot Performance record.
  //
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ResetEnd                = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart  = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry   = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry));
  //
  // ExitBootServicesExit will be updated later, so don't dump it here.
  //
}
UINT64
InternalGetPerformanceCounterFrequency (
  VOID
  ) 
{
  BOOLEAN  InterruptState;
  UINT64   Count;

  if (mPerformanceCounterFrequency == 0) {
    InterruptState = SaveAndDisableInterrupts ();
    Count = GetPerformanceCounter ();
    MicroSecondDelay (100);
    mPerformanceCounterFrequency = MultU64x32 (GetPerformanceCounter () - Count, 10000);
    SetInterruptState (InterruptState);
  }
  return  mPerformanceCounterFrequency;
}
Example #11
0
/**
  Start Timer for SMM AP Sync.

**/
UINT64
EFIAPI
StartSyncTimer (
  VOID
  )
{
  return GetPerformanceCounter ();
}
Example #12
0
VOID
CEntryPoint (
  IN  UINTN                     MpId,
  IN  UINTN                     UefiMemoryBase,
  IN  UINTN                     StacksBase,
  IN  UINTN                     GlobalVariableBase
  )
{
  UINT64   StartTimeStamp;
 
  ASSERT(!ArmIsMpCore() || (PcdGet32 (PcdCoreCount) > 1));

  // Initialize the platform specific controllers
  ArmPlatformInitialize (MpId);

  if (ArmPlatformIsPrimaryCore (MpId) && PerformanceMeasurementEnabled ()) {
    // Initialize the Timer Library to setup the Timer HW controller
    TimerConstructor ();
    // We cannot call yet the PerformanceLib because the HOB List has not been initialized
    StartTimeStamp = GetPerformanceCounter ();
  } else {
    StartTimeStamp = 0;
  }

  // Data Cache enabled on Primary core when MMU is enabled.
  ArmDisableDataCache ();
  // Invalidate Data cache
  ArmInvalidateDataCache ();
  // Invalidate instruction cache
  ArmInvalidateInstructionCache ();
  // Enable Instruction Caches on all cores.
  ArmEnableInstructionCache ();

  // Define the Global Variable region when we are not running in XIP
  if (!IS_XIP()) {
    if (ArmPlatformIsPrimaryCore (MpId)) {
      mGlobalVariableBase = GlobalVariableBase;
      if (ArmIsMpCore()) {
        // Signal the Global Variable Region is defined (event: ARM_CPU_EVENT_DEFAULT)
        ArmCallSEV ();
      }
    } else {
      // Wait the Primay core has defined the address of the Global Variable region (event: ARM_CPU_EVENT_DEFAULT)
      ArmCallWFE ();
    }
  }
  
  // If not primary Jump to Secondary Main
  if (ArmPlatformIsPrimaryCore (MpId)) {
    // Goto primary Main.
    PrimaryMain (UefiMemoryBase, StacksBase, GlobalVariableBase, StartTimeStamp);
  } else {
    SecondaryMain (MpId);
  }

  // DXE Core should always load and never return
  ASSERT (FALSE);
}
Example #13
0
bool PerfCounterItem::SetCounterValue(int newValue) {
	bool ret = false;

	if (mPerfCounterId!=-1 ) {
		ret = GetPerformanceCounter()->SetPerformanceCounter(mPerfCounterId,newValue);
	}

	return ret;
}
Example #14
0
bool PerfCounterItem::SetName(const char* name) {
	bool ret = false;

	mPerfCounterId = GetPerformanceCounter()->AddPerformanceCounter(name);
	if (mPerfCounterId!=-1) {
		ret = true;
	}
	return ret;
}
Example #15
0
bool PerfCounterItem::Increment(int incrementvalue) {
	bool ret = false;

	if (mPerfCounterId!=-1 ) {
		ret = GetPerformanceCounter()->IncrementPerformanceCounter(mPerfCounterId,incrementvalue);
	}

	return ret;
}
Example #16
0
/********************************************************************
 *
 *  TimerHandler
 *
 *  Handles both coalesced and non-coalesced timers, and keeps
 *  the record of the effective elapsed time.
 *  Switches the coalesced modes periodically for comparison.
 *
 *********************************************************************/
void CALLBACK TimerHandler(_In_ HWND hwnd, _In_ UINT_PTR idEvent)
{
    if (idEvent >= ARRAYSIZE(gTimerRec)) {
        return;
    }

    TimerRec& t = gTimerRec[idEvent];

    LONGLONG lTime = GetPerformanceCounter();
    LONGLONG lElapsed = lTime - t.lLast;
    t.lElapsedMin = min(t.lElapsedMin, lElapsed);
    t.lElapsedMax = max(t.lElapsedMax, lElapsed);
    t.lLast = lTime;
    ++t.lCount;
    t.lSum += lElapsed;

    if (t.lCount % TIMER_CONTIGUOUS_RUN == 0) {
        // Now, let's switch the timer types.
        // First, kill the current timer.
        KillTimer(hwnd, idEvent);

        // Reverse the timer id.
        idEvent = !idEvent;

        /*
         * Setting new timer - switching the coalescing mode.
         *
         * Note that the coalesced timers may be fired
         * together with other timers that are readied during the
         * coalescing tolerance.  As such, in an environment
         * that has a lot of short timers may only see a small or no
         * increase in the average time.
         * If that's the case, try running this sample with
         * the minimum number of processes.
         */
        gTimerRec[idEvent].lLast = GetPerformanceCounter();
        SetCoalescableTimer(hwnd, idEvent, TIMER_ELAPSE, NULL,
                            idEvent == TIMERID_NOCOALSCING ? TIMERV_NO_COALESCING : TIMER_TOLERANCE);
    }
}
Example #17
0
    REFERENCE_TIME MyClock::GetPrivateTime()
    {
        CAutoLock lock(this);

        REFERENCE_TIME audioClockTime, audioClockCounterTime;
        if (SUCCEEDED(GetAudioClockTime(&audioClockTime, &audioClockCounterTime)))
        {
            m_counterOffset = audioClockTime - audioClockCounterTime;
            return audioClockTime;
        }

        return m_counterOffset + llMulDiv(GetPerformanceCounter(), OneSecond, m_performanceFrequency, 0);
    }
Example #18
0
/******************************************************************
 *
 *  WndProc
 *
 ******************************************************************/
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) {
    case WM_CREATE:
        // Start with non-coalescable timer.
        // Later we switch to the coalescable timer.
        gTimerRec[TIMERID_NOCOALSCING].lLast = GetPerformanceCounter();
        if (!SetCoalescableTimer(hwnd, TIMERID_NOCOALSCING, TIMER_ELAPSE, NULL, TIMERV_NO_COALESCING)) {
            return -1;
        }

        // Let's update the screen periodically.
        SetTimer(hwnd, TIMERID_UPDATE_SCREEN, TIMER_AUTO_REFRESH_ELAPSE, NULL);
        return 0;

    case WM_TIMER:
        if (wParam < ARRAYSIZE(gTimerRec)) {

            TimerHandler(hwnd, (UINT_PTR)wParam);

        } else if (wParam == TIMERID_UPDATE_SCREEN) {
            // Periodically update the results.
    case WM_MOUSEMOVE:  // Tricky: also update the screen at every mouse move.
            InvalidateRect(hwnd, NULL, FALSE);
        }
        break;

    case WM_PAINT:
    case WM_DISPLAYCHANGE:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            OnPaint(hdc, &ps.rcPaint);
            EndPaint(hwnd, &ps);
        }
        return 0;

    case WM_KEYDOWN:
        if (wParam == VK_SPACE) {
            // Space key to power down the monitor.
            DefWindowProc(GetDesktopWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, 2);
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 1;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}
Example #19
0
/**
  Retrieves the current value of a 64-bit free running timestamp counter.

  The counter shall count up in proportion to the amount of time that has passed. The counter value
  will always roll over to zero. The properties of the counter can be retrieved from GetProperties().
  The caller should be prepared for the function to return the same value twice across successive calls.
  The counter value will not go backwards other than when wrapping, as defined by EndValue in GetProperties().
  The frequency of the returned timestamp counter value must remain constant. Power management operations that 
  affect clocking must not change the returned counter frequency. The quantization of counter value updates may 
  vary as long as the value reflecting time passed remains consistent.           

  @retval The current value of the free running timestamp counter.

**/
UINT64
EFIAPI
TimestampDriverGetTimestamp (
  VOID
  )
{
  //
  // The timestamp of Timestamp Protocol
  //
  UINT64  TimestampValue;
  TimestampValue = 0;
  
  //
  // Get the timestamp
  //
  if (mTimerLibStartValue > mTimerLibEndValue) {
    TimestampValue = mTimerLibStartValue - GetPerformanceCounter();
  } else {
    TimestampValue = GetPerformanceCounter() - mTimerLibStartValue;
  }
    
  return TimestampValue;
}
Example #20
0
/**
  Creates a record for the beginning of a performance measurement.

  Creates a record that contains the Handle, Token, Module and Identifier.
  If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
  If TimeStamp is zero, then this function reads the current time stamp
  and adds that time stamp value to the record as the start time.

  @param  Handle                  Pointer to environment specific context used
                                  to identify the component being measured.
  @param  Token                   Pointer to a Null-terminated ASCII string
                                  that identifies the component being measured.
  @param  Module                  Pointer to a Null-terminated ASCII string
                                  that identifies the module being measured.
  @param  TimeStamp               64-bit time stamp.
  @param  Identifier              32-bit identifier. If the value is 0, the created record
                                  is same as the one created by StartPerformanceMeasurement.

  @retval RETURN_SUCCESS          The start of the measurement was recorded.
  @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.

**/
RETURN_STATUS
EFIAPI
StartPerformanceMeasurementEx (
  IN CONST VOID   *Handle,  OPTIONAL
  IN CONST CHAR8  *Token,   OPTIONAL
  IN CONST CHAR8  *Module,  OPTIONAL
  IN UINT64       TimeStamp,
  IN UINT32       Identifier
  )
{
  PEI_PERFORMANCE_LOG_HEADER  *PeiPerformanceLog;
  UINT32                      *PeiPerformanceIdArray;
  PEI_PERFORMANCE_LOG_ENTRY   *LogEntryArray;
  UINT32                      Index;
  UINT16                      PeiPerformanceLogEntries;

  PeiPerformanceLogEntries = (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?
                                       PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :
                                       PcdGet8 (PcdMaxPeiPerformanceLogEntries));

  InternalGetPerformanceHobLog (&PeiPerformanceLog, &PeiPerformanceIdArray);

  if (PeiPerformanceLog->NumberOfEntries >= PeiPerformanceLogEntries) {
    DEBUG ((DEBUG_ERROR, "PEI performance log array out of resources\n"));
    return RETURN_OUT_OF_RESOURCES;
  }
  Index                       = PeiPerformanceLog->NumberOfEntries++;
  LogEntryArray               = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1);
  LogEntryArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;

  if (Token != NULL) {
    AsciiStrnCpyS (LogEntryArray[Index].Token, PEI_PERFORMANCE_STRING_SIZE, Token, PEI_PERFORMANCE_STRING_LENGTH);
  }
  if (Module != NULL) {
    AsciiStrnCpyS (LogEntryArray[Index].Module, PEI_PERFORMANCE_STRING_SIZE, Module, PEI_PERFORMANCE_STRING_LENGTH);
  }

  LogEntryArray[Index].EndTimeStamp = 0;
  PeiPerformanceIdArray[Index] = Identifier;

  if (TimeStamp == 0) {
    TimeStamp = GetPerformanceCounter ();
  }
  LogEntryArray[Index].StartTimeStamp = TimeStamp;

  return RETURN_SUCCESS;
}
Example #21
0
/**
  Check if the SMM AP Sync timer is timeout.

  @param Timer  The start timer from the begin.

**/
BOOLEAN
EFIAPI
IsSyncTimerTimeout (
  IN      UINT64                    Timer
  )
{
  UINT64  CurrentTimer;
  UINT64  Delta;

  CurrentTimer = GetPerformanceCounter ();
  //
  // We need to consider the case that CurrentTimer is equal to Timer
  // when some timer runs too slow and CPU runs fast. We think roll over
  // condition does not happen on this case.
  //
  if (mCountDown) {
    //
    // The performance counter counts down.  Check for roll over condition.
    //
    if (CurrentTimer <= Timer) {
      Delta = Timer - CurrentTimer;
    } else {
      //
      // Handle one roll-over.
      //
      Delta = mCycle - (CurrentTimer - Timer) + 1;
    }
  } else {
    //
    // The performance counter counts up.  Check for roll over condition.
    //
    if (CurrentTimer >= Timer) {
      Delta = CurrentTimer - Timer;
    } else {
      //
      // Handle one roll-over.
      //
      Delta = mCycle - (Timer - CurrentTimer) + 1;
    }
  }

  return (BOOLEAN) (Delta >= mTimeoutTicker);
}
Example #22
0
/**
  Check if the timer is timeout.
  
  @param[in] UsbDebugPortHandle  Pointer to USB Debug port handle
  @param[in] Timer               The start timer from the begin.
  @param[in] TimeoutTicker       Ticker number need time out.

  @return TRUE  Timer time out occurs.
  @retval FALSE Timer does not time out.

**/
BOOLEAN
IsTimerTimeout (
  IN USB_DEBUG_PORT_HANDLE   *UsbDebugPortHandle,
  IN UINT64                  Timer,
  IN UINT64                  TimeoutTicker
  )
{
  UINT64  CurrentTimer;
  UINT64  Delta;

  CurrentTimer = GetPerformanceCounter ();

  if (UsbDebugPortHandle->TimerCountDown) {
    //
    // The timer counter counts down.  Check for roll over condition.
    //
    if (CurrentTimer < Timer) {
      Delta = Timer - CurrentTimer;
    } else {
      //
      // Handle one roll-over. 
      //
      Delta = UsbDebugPortHandle->TimerCycle - (CurrentTimer - Timer);
    }
  } else {
    //
    // The timer counter counts up.  Check for roll over condition.
    //
    if (CurrentTimer > Timer) {
      Delta = CurrentTimer - Timer;
    } else {
      //
      // Handle one roll-over. 
      //
      Delta = UsbDebugPortHandle->TimerCycle - (Timer - CurrentTimer);
    }
  }
 
  return (BOOLEAN) (Delta >= TimeoutTicker);
}
/**
  Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record
  performance data for ExitBootServicesEntry in FPDT.

  @param[in]  Event   The Event that is being processed.
  @param[in]  Context The Event Context.

**/
VOID
EFIAPI
FpdtExitBootServicesEventNotify (
  IN EFI_EVENT        Event,
  IN VOID             *Context
  )
{
  if (!mDxeCoreReportStatusCodeEnable) {
    //
    // When DxeCore Report Status Code is disabled, 
    // Unregister boot time report status code listener at ExitBootService Event.
    //
    mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);
  }

  if (mAcpiBootPerformanceTable == NULL) {
    //
    // Firmware Performance Data Table not installed, do nothing.
    //
    return ;
  }

  //
  // Update Firmware Basic Boot Performance Record for UEFI boot.
  //
  mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry = GetTimeInNanoSecond (GetPerformanceCounter ());

  //
  // Dump FPDT Boot Performance record.
  //
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ResetEnd                = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart  = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry   = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry));
  //
  // ExitBootServicesExit will be updated later, so don't dump it here.
  //
}
Example #24
0
/**

  Allocates a block of memory and writes performance data of booting into it.
  OS can processing these record.

**/
VOID
WriteBootToOsPerformanceData (
    VOID
)
{
    EFI_STATUS                Status;
    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;
    UINTN                     EntryIndex;
    UINTN                     NumPerfEntries;
    //
    // List of flags indicating PerfEntry contains DXE handle
    //
    BOOLEAN                   *PerfEntriesAsDxeHandle;

    //
    // Retrieve time stamp count as early as possible
    //
    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;
    }

    //
    // Put Detailed performance data into memory
    //
    Handles = NULL;
    Status = gBS->LocateHandleBuffer (
                 AllHandles,
                 NULL,
                 NULL,
                 &NoHandles,
                 &Handles
             );
    if (EFI_ERROR (Status)) {
        return ;
    }


    AcpiLowMemoryLength = 0x4000;
    if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {
        //
        // Allocate a block of memory that contain performance data to OS
        //
        Status = gBS->AllocatePages (
                     AllocateMaxAddress,
                     EfiReservedMemoryType,
                     EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),
                     &mAcpiLowMemoryBase
                 );
        if (EFI_ERROR (Status)) {
            FreePool (Handles);
            return ;
        }
    }


    Ptr        = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));
    LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);

    NumPerfEntries = 0;
    LogEntryKey    = 0;
    while ((LogEntryKey = GetPerformanceMeasurement (
                              LogEntryKey,
                              &Handle,
                              &Token,
                              &Module,
                              &StartTicker,
                              &EndTicker)) != 0) {
        NumPerfEntries++;
    }
    PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
    ASSERT (PerfEntriesAsDxeHandle != NULL);

    //
    // Get DXE drivers performance
    //
    for (Index = 0; Index < NoHandles; Index++) {
        Ticker = 0;
        LogEntryKey = 0;
        EntryIndex  = 0;
        while ((LogEntryKey = GetPerformanceMeasurement (
                                  LogEntryKey,
                                  &Handle,
                                  &Token,
                                  &Module,
                                  &StartTicker,
                                  &EndTicker)) != 0) {
            if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
                PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
            }
            EntryIndex++;
            if ((Handle == Handles[Index]) && (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) {

            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;
            }
        }
    }

    //
    // Get inserted performance data
    //
    LogEntryKey = 0;
    EntryIndex  = 0;
    while ((LogEntryKey = GetPerformanceMeasurement (
                              LogEntryKey,
                              &Handle,
                              &Token,
                              &Module,
                              &StartTicker,
                              &EndTicker)) != 0) {
        if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {

            ZeroMem (&mPerfData, sizeof (PERF_DATA));

            AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);
            if (StartTicker == 1) {
                StartTicker = StartValue;
            }
            if (EndTicker == 1) {
                EndTicker = StartValue;
            }
            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;
            }
        }
        EntryIndex++;
    }

Done:

    FreePool (Handles);
    FreePool (PerfEntriesAsDxeHandle);

    mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;

    //
    // Put performance data to Reserved memory
    //
    CopyMem (
        (UINTN *) (UINTN) mAcpiLowMemoryBase,
        &mPerfHeader,
        sizeof (PERF_HEADER)
    );

    gRT->SetVariable (
        L"PerfDataMemAddr",
        &gPerformanceProtocolGuid,
        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
        sizeof (EFI_PHYSICAL_ADDRESS),
        &mAcpiLowMemoryBase
    );

    return ;
}
/**
  Report status code listener for SMM. This is used to record the performance
  data for S3 Suspend Start and S3 Suspend End in FPDT.

  @param[in]  CodeType            Indicates the type of status code being reported.
  @param[in]  Value               Describes the current status of a hardware or software entity.
                                  This included information about the class and subclass that is used to
                                  classify the entity as well as an operation.
  @param[in]  Instance            The enumeration of a hardware or software entity within
                                  the system. Valid instance numbers start with 1.
  @param[in]  CallerId            This optional parameter may be used to identify the caller.
                                  This parameter allows the status code driver to apply different rules to
                                  different callers.
  @param[in]  Data                This optional parameter may be used to pass additional data.

  @retval EFI_SUCCESS             Status code is what we expected.
  @retval EFI_UNSUPPORTED         Status code not supported.

**/
EFI_STATUS
EFIAPI
FpdtStatusCodeListenerSmm (
  IN EFI_STATUS_CODE_TYPE     CodeType,
  IN EFI_STATUS_CODE_VALUE    Value,
  IN UINT32                   Instance,
  IN EFI_GUID                 *CallerId,
  IN EFI_STATUS_CODE_DATA     *Data
  )
{
  EFI_STATUS                           Status;
  UINT64                               CurrentTime;
  EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD  S3SuspendRecord;
  UINT8                                *NewRecordBuffer;

  //
  // Check whether status code is what we are interested in.
  //
  if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) {
    return EFI_UNSUPPORTED;
  }
  
  //
  // Collect one or more Boot records in boot time
  //
  if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {
    AcquireSpinLock (&mSmmFpdtLock);
    
    if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
      //
      // Try to allocate big SMRAM data to store Boot record. 
      //
      if (mSmramIsOutOfResource) {
        ReleaseSpinLock (&mSmmFpdtLock);
        return EFI_OUT_OF_RESOURCES;
      }
      NewRecordBuffer = ReallocatePool (mBootRecordSize, mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE, mBootRecordBuffer); 
      if (NewRecordBuffer == NULL) {
        ReleaseSpinLock (&mSmmFpdtLock);
        mSmramIsOutOfResource = TRUE;
        return EFI_OUT_OF_RESOURCES;
      }
      mBootRecordBuffer  = NewRecordBuffer;
      mBootRecordMaxSize = mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE;
    }
    //
    // Save boot record into the temp memory space.
    //
    CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
    mBootRecordSize += Data->Size;
    
    ReleaseSpinLock (&mSmmFpdtLock);
    return EFI_SUCCESS;
  }

  if ((Value != PcdGet32 (PcdProgressCodeS3SuspendStart)) &&
      (Value != PcdGet32 (PcdProgressCodeS3SuspendEnd))) {
    return EFI_UNSUPPORTED;
  }

  //
  // Retrieve current time.
  //
  CurrentTime = GetTimeInNanoSecond (GetPerformanceCounter ());

  if (Value == PcdGet32 (PcdProgressCodeS3SuspendStart)) {
    //
    // S3 Suspend started, record the performance data and return.
    //
    mSuspendStartTime = CurrentTime;
    return EFI_SUCCESS;
  }

  //
  // We are going to S3 sleep, record S3 Suspend End performance data.
  //
  S3SuspendRecord.SuspendStart = mSuspendStartTime;
  S3SuspendRecord.SuspendEnd   = CurrentTime;

  //
  // Save S3 suspend performance data to lock box, it will be used by Firmware Performance PEIM.
  //
  if (!mS3SuspendLockBoxSaved) {
    Status = SaveLockBox (
               &gEfiFirmwarePerformanceGuid,
               &S3SuspendRecord,
               sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD)
               );
    ASSERT_EFI_ERROR (Status);

    mS3SuspendLockBoxSaved = TRUE;
  } else {
    Status = UpdateLockBox (
               &gEfiFirmwarePerformanceGuid,
               0,
               &S3SuspendRecord,
               sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD)
               );
    ASSERT_EFI_ERROR (Status);
  }

  return EFI_SUCCESS;
}
Example #26
0
 REFERENCE_TIME MyTestClock::GetPrivateTime()
 {
     return llMulDiv(GetPerformanceCounter(), OneSecond, m_performanceFrequency, 0);
 }
Example #27
0
/**

  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
WriteBootToOsPerformanceData (
  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                     EntryIndex;
  UINTN                     NumPerfEntries;
  //
  // List of flags indicating PerfEntry contains DXE handle
  //
  BOOLEAN                   *PerfEntriesAsDxeHandle;
  UINTN                     VarSize;

  //
  // 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);

  mPerfHeader.CpuFreq = Freq;

  //
  // Record BDS raw performance data
  //
  if (EndValue >= StartValue) {
    mPerfHeader.BDSRaw = Ticker - StartValue;
    CountUp            = TRUE;
  } else {
    mPerfHeader.BDSRaw = StartValue - Ticker;
    CountUp            = FALSE;
  }

  if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {
    VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
    Status = gRT->GetVariable (
                    L"PerfDataMemAddr",
                    &gPerformanceProtocolGuid,
                    NULL,
                    &VarSize,
                    &mAcpiLowMemoryBase
                    );
    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) mAcpiLowMemoryBase + sizeof (PERF_HEADER));
  LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);

  NumPerfEntries = 0;
  LogEntryKey    = 0;
  while ((LogEntryKey = GetPerformanceMeasurement (
                          LogEntryKey,
                          &Handle,
                          &Token,
                          &Module,
                          &StartTicker,
                          &EndTicker)) != 0) {
    NumPerfEntries++;
  }
  PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
  ASSERT (PerfEntriesAsDxeHandle != NULL);
  
  //
  // Get DXE drivers performance
  //
  for (Index = 0; Index < NoHandles; Index++) {
    Ticker = 0;
    LogEntryKey = 0;
    EntryIndex  = 0;
    while ((LogEntryKey = GetPerformanceMeasurement (
                            LogEntryKey,
                            &Handle,
                            &Token,
                            &Module,
                            &StartTicker,
                            &EndTicker)) != 0) {
      if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
        PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
      }
      EntryIndex++;
      if ((Handle == Handles[Index]) && (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) {

      GetNameFromHandle (Handles[Index], GaugeString);

      AsciiStrCpyS (mPerfData.Token, PERF_TOKEN_SIZE, GaugeString);
      mPerfData.Duration = Duration;

      CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
      Ptr += sizeof (PERF_DATA);

      mPerfHeader.Count++;
      if (mPerfHeader.Count == LimitCount) {
        goto Done;
      }
    }
  }

  //
  // Get inserted performance data
  //
  LogEntryKey = 0;
  EntryIndex  = 0;
  while ((LogEntryKey = GetPerformanceMeasurement (
                          LogEntryKey,
                          &Handle,
                          &Token,
                          &Module,
                          &StartTicker,
                          &EndTicker)) != 0) {
    if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {

      ZeroMem (&mPerfData, sizeof (PERF_DATA));

      AsciiStrnCpyS (mPerfData.Token, PERF_TOKEN_SIZE, Token, PERF_TOKEN_LENGTH);
      if (StartTicker == 1) {
        StartTicker = StartValue;
      }
      if (EndTicker == 1) {
        EndTicker = StartValue;
      }
      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;
      }
    }
    EntryIndex++;
  }

Done:

  FreePool (Handles);
  FreePool (PerfEntriesAsDxeHandle);

  mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;

  //
  // Put performance data to Reserved memory
  //
  CopyMem (
    (UINTN *) (UINTN) mAcpiLowMemoryBase,
    &mPerfHeader,
    sizeof (PERF_HEADER)
    );

  return ;
}
EFIAPI
AcquireSpinLock (
  IN OUT  SPIN_LOCK                 *SpinLock
  )
{
  UINT64  Current;
  UINT64  Previous;
  UINT64  Total;
  UINT64  Start;
  UINT64  End;
  UINT64  Timeout;
  INT64   Cycle;
  INT64   Delta;

  if (PcdGet32 (PcdSpinLockTimeout) > 0) {
    //
    // Get the current timer value
    //
    Current = GetPerformanceCounter();

    //
    // Initialize local variables
    //
    Start = 0;
    End   = 0;
    Total = 0;

    //
    // Retrieve the performance counter properties and compute the number of performance
    // counter ticks required to reach the timeout
    //
    Timeout = DivU64x32 (
                MultU64x32 (
                  GetPerformanceCounterProperties (&Start, &End),
                  PcdGet32 (PcdSpinLockTimeout)
                  ),
                1000000
                );
    Cycle = End - Start;
    if (Cycle < 0) {
      Cycle = -Cycle;
    }
    Cycle++;

    while (!AcquireSpinLockOrFail (SpinLock)) {
      CpuPause ();
      Previous = Current;
      Current  = GetPerformanceCounter();
      Delta = (INT64) (Current - Previous);
      if (Start > End) {
        Delta = -Delta;
      }
      if (Delta < 0) {
        Delta += Cycle;
      }
      Total += Delta;
      ASSERT (Total < Timeout);
    }
  } else {
    while (!AcquireSpinLockOrFail (SpinLock)) {
      CpuPause ();
    }
  }
  return SpinLock;
}
Example #29
0
/**
  Adds a record at the end of the performance measurement log
  that records the start time of a performance measurement.

  Adds a record to the end of the performance measurement log
  that contains the Handle, Token, Module and Identifier.
  The end time of the new record must be set to zero.
  If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
  If TimeStamp is zero, the start time in the record is filled in with the value
  read from the current time stamp.

  @param  Handle                  Pointer to environment specific context used
                                  to identify the component being measured.
  @param  Token                   Pointer to a Null-terminated ASCII string
                                  that identifies the component being measured.
  @param  Module                  Pointer to a Null-terminated ASCII string
                                  that identifies the module being measured.
  @param  TimeStamp               64-bit time stamp.
  @param  Identifier              32-bit identifier. If the value is 0, the created record
                                  is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.

  @retval EFI_SUCCESS             The data was read correctly from the device.
  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.

**/
EFI_STATUS
EFIAPI
StartGaugeEx (
  IN CONST VOID   *Handle,  OPTIONAL
  IN CONST CHAR8  *Token,   OPTIONAL
  IN CONST CHAR8  *Module,  OPTIONAL
  IN UINT64       TimeStamp,
  IN UINT32       Identifier
  )
{
  GAUGE_DATA_ENTRY_EX       *GaugeEntryExArray;
  UINTN                     GaugeDataSize;
  GAUGE_DATA_HEADER         *NewGaugeData;
  UINTN                     OldGaugeDataSize;
  GAUGE_DATA_HEADER         *OldGaugeData;
  UINT32                    Index;

  Index = mGaugeData->NumberOfEntries;
  if (Index >= mMaxGaugeRecords) {
    //
    // Try to enlarge the scale of gauge array.
    //
    OldGaugeData      = mGaugeData;
    OldGaugeDataSize  = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords;

    GaugeDataSize     = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2;

    NewGaugeData = AllocateZeroPool (GaugeDataSize);
    if (NewGaugeData == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    mGaugeData = NewGaugeData;
    mMaxGaugeRecords *= 2;

    //
    // Initialize new data array and migrate old data one.
    //
    mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize);

    FreePool (OldGaugeData);
  }

  GaugeEntryExArray               = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
  GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;

  if (Token != NULL) {
    AsciiStrCpyS (GaugeEntryExArray[Index].Token, DXE_PERFORMANCE_STRING_SIZE, Token);
  }
  if (Module != NULL) {
    AsciiStrCpyS (GaugeEntryExArray[Index].Module, DXE_PERFORMANCE_STRING_SIZE, Module);
  }

  GaugeEntryExArray[Index].EndTimeStamp = 0;
  GaugeEntryExArray[Index].Identifier = Identifier;

  if (TimeStamp == 0) {
    TimeStamp = GetPerformanceCounter ();
  }
  GaugeEntryExArray[Index].StartTimeStamp = TimeStamp;

  mGaugeData->NumberOfEntries++;

  return EFI_SUCCESS;
}
Example #30
0
/**
  Report status code listener of FPDT. This is used to collect performance data
  for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT.

  @param[in]  CodeType            Indicates the type of status code being reported.
  @param[in]  Value               Describes the current status of a hardware or software entity.
                                  This included information about the class and subclass that is used to
                                  classify the entity as well as an operation.
  @param[in]  Instance            The enumeration of a hardware or software entity within
                                  the system. Valid instance numbers start with 1.
  @param[in]  CallerId            This optional parameter may be used to identify the caller.
                                  This parameter allows the status code driver to apply different rules to
                                  different callers.
  @param[in]  Data                This optional parameter may be used to pass additional data.

  @retval EFI_SUCCESS             Status code is what we expected.
  @retval EFI_UNSUPPORTED         Status code not supported.

**/
EFI_STATUS
EFIAPI
FpdtStatusCodeListenerDxe (
  IN EFI_STATUS_CODE_TYPE     CodeType,
  IN EFI_STATUS_CODE_VALUE    Value,
  IN UINT32                   Instance,
  IN EFI_GUID                 *CallerId,
  IN EFI_STATUS_CODE_DATA     *Data
  )
{
  EFI_STATUS  Status;

  //
  // Check whether status code is what we are interested in.
  //
  if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) {
    return EFI_UNSUPPORTED;
  }

  Status = EFI_SUCCESS;
  if (Value == PcdGet32 (PcdProgressCodeOsLoaderLoad)) {
    //
    // Progress code for OS Loader LoadImage.
    //
    if (mAcpiBootPerformanceTable == NULL) {
      return Status;
    }

    //
    // Update OS Loader LoadImage Start for UEFI boot.
    //
    mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());
  } else if (Value == PcdGet32 (PcdProgressCodeOsLoaderStart)) {
    //
    // Progress code for OS Loader StartImage.
    //
    if (mAcpiBootPerformanceTable == NULL) {
      return Status;
    }

    //
    // Update OS Loader StartImage Start for UEFI boot.
    //
    mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());
  } else if (Value == (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)) {
    //
    // Progress code for ExitBootServices.
    //
    if (mAcpiBootPerformanceTable == NULL) {
      return Status;
    }

    //
    // Update ExitBootServicesExit for UEFI boot.
    //
    mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesExit = GetTimeInNanoSecond (GetPerformanceCounter ());

    //
    // Unregister boot time report status code listener.
    //
    mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);
  } else if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {
    //
    // Append one or more Boot records
    //
    if (mAcpiBootPerformanceTable == NULL) {
      //
      // Append Boot records before FPDT ACPI table is installed. 
      //
      if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
        mBootRecordBuffer = ReallocatePool (mBootRecordSize, mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE, mBootRecordBuffer);
        ASSERT (mBootRecordBuffer != NULL);
        mBootRecordMaxSize = mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE;
      }
      //
      // Save boot record into the temp memory space.
      //
      CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
      mBootRecordSize += Data->Size;
    } else {
      //
      // Append Boot records after FPDT ACPI table is installed. 
      //
      if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
        //
        // No enough space to save boot record.
        //
        Status = EFI_OUT_OF_RESOURCES;
      } else {
        //
        // Save boot record into BootPerformance table
        //
        CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
        mBootRecordSize += Data->Size;
        mAcpiBootPerformanceTable->Header.Length = mBootRecordSize;
      }
    }
  } else {
    //
    // Ignore else progress code.
    //
    Status = EFI_UNSUPPORTED;
  }

  return Status;
}