| /** @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 ((DEBUG_INFO, "Debug Timer: FSB Clock = %d\n", PcdGet32 (PcdFSBClock))); | |
| DEBUG ((DEBUG_INFO, "Debug Timer: Divisor = %d\n", ApicTimerDivisor)); | |
| DEBUG ((DEBUG_INFO, "Debug Timer: Frequency = %d\n", ApicTimerFrequency)); | |
| DEBUG ((DEBUG_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); | |
| } |