diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c b/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c new file mode 100644 index 00000000..19c2afe9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugTimer.c @@ -0,0 +1,143 @@ +/** @file + Code for debug timer to support debug agent library implementation. + + Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DebugAgent.h" + +/** + Initialize CPU local APIC timer. + + @param[out] TimerFrequency Local APIC timer frequency returned. + @param[in] DumpFlag If TRUE, dump Local APIC timer's parameter. + + @return 32-bit Local APIC timer init count. +**/ +UINT32 +InitializeDebugTimer ( + OUT UINT32 *TimerFrequency, + IN BOOLEAN DumpFlag + ) +{ + UINTN ApicTimerDivisor; + UINT32 InitialCount; + UINT32 ApicTimerFrequency; + + InitializeLocalApicSoftwareEnable (TRUE); + GetApicTimerState (&ApicTimerDivisor, NULL, NULL); + ApicTimerFrequency = PcdGet32(PcdFSBClock) / (UINT32)ApicTimerDivisor; + // + // Cpu Local Apic timer interrupt frequency, it is set to 0.1s + // + InitialCount = (UINT32)DivU64x32 ( + MultU64x64 ( + ApicTimerFrequency, + DEBUG_TIMER_INTERVAL + ), + 1000000u + ); + + InitializeApicTimer (ApicTimerDivisor, InitialCount, TRUE, DEBUG_TIMER_VECTOR); + // + // Disable Debug Timer interrupt to avoid it is delivered before Debug Port + // is initialized + // + DisableApicTimerInterrupt (); + + if (DumpFlag) { + DEBUG ((EFI_D_INFO, "Debug Timer: FSB Clock = %d\n", PcdGet32(PcdFSBClock))); + DEBUG ((EFI_D_INFO, "Debug Timer: Divisor = %d\n", ApicTimerDivisor)); + DEBUG ((EFI_D_INFO, "Debug Timer: Frequency = %d\n", ApicTimerFrequency)); + DEBUG ((EFI_D_INFO, "Debug Timer: InitialCount = %d\n", InitialCount)); + } + if (TimerFrequency != NULL) { + *TimerFrequency = ApicTimerFrequency; + } + return InitialCount; +} + +/** + Enable/Disable the interrupt of debug timer and return the interrupt state + prior to the operation. + + If EnableStatus is TRUE, enable the interrupt of debug timer. + If EnableStatus is FALSE, disable the interrupt of debug timer. + + @param[in] EnableStatus Enable/Disable. + + @retval TRUE Debug timer interrupt were enabled on entry to this call. + @retval FALSE Debug timer interrupt were disabled on entry to this call. + +**/ +BOOLEAN +EFIAPI +SaveAndSetDebugTimerInterrupt ( + IN BOOLEAN EnableStatus + ) +{ + BOOLEAN OldDebugTimerInterruptState; + + OldDebugTimerInterruptState = GetApicTimerInterruptState (); + + if (OldDebugTimerInterruptState != EnableStatus) { + if (EnableStatus) { + EnableApicTimerInterrupt (); + } else { + DisableApicTimerInterrupt (); + } + // + // Validate the Debug Timer interrupt state + // This will make additional delay after Local Apic Timer interrupt state is changed. + // Thus, CPU could handle the potential pending interrupt of Local Apic timer. + // + while (GetApicTimerInterruptState () != EnableStatus) { + CpuPause (); + } + } + + return OldDebugTimerInterruptState; +} + +/** + Check if the timer is time out. + + @param[in] TimerCycle Timer initial count. + @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 +IsDebugTimerTimeout ( + IN UINT32 TimerCycle, + IN UINT32 Timer, + IN UINT32 TimeoutTicker + ) +{ + UINT64 CurrentTimer; + UINT64 Delta; + + CurrentTimer = GetApicTimerCurrentCount (); + + // + // This timer counter counts down. Check for roll over condition. + // If CurrentTimer is equal to Timer, it does not mean that roll over + // happened. + // + if (CurrentTimer <= Timer) { + Delta = Timer - CurrentTimer; + } else { + // + // Handle one roll-over. + // + Delta = TimerCycle - (CurrentTimer - Timer) + 1; + } + + return (BOOLEAN) (Delta >= TimeoutTicker); +} + |