Add HPET and TSC stall execution backends
All checks were successful
All checks were successful
This commit is contained in:
@@ -37,7 +37,7 @@ HL::Timer::CalibrateApicTimer()
|
|||||||
HL::Pic::WriteApicRegister(APIC_TICR, InitialCount);
|
HL::Pic::WriteApicRegister(APIC_TICR, InitialCount);
|
||||||
|
|
||||||
/* Stall CPU execution for exactly 10 milliseconds */
|
/* Stall CPU execution for exactly 10 milliseconds */
|
||||||
StallExecutionPit(10000);
|
StallExecution(10000);
|
||||||
|
|
||||||
/* Read current tick count from APIC timer and clear APIC timer */
|
/* Read current tick count from APIC timer and clear APIC timer */
|
||||||
CurrentCount = HL::Pic::ReadApicRegister(APIC_TCCR);
|
CurrentCount = HL::Pic::ReadApicRegister(APIC_TCCR);
|
||||||
@@ -87,7 +87,7 @@ HL::Timer::CalibrateTscCounter(VOID)
|
|||||||
InitialTickCount = AR::CpuFunc::ReadTimeStampCounterProcessor(&TscAux);
|
InitialTickCount = AR::CpuFunc::ReadTimeStampCounterProcessor(&TscAux);
|
||||||
|
|
||||||
/* Stall CPU execution for exactly 10 milliseconds */
|
/* Stall CPU execution for exactly 10 milliseconds */
|
||||||
StallExecutionPit(10000);
|
StallExecution(10000);
|
||||||
|
|
||||||
/* Read current tick count from TSC */
|
/* Read current tick count from TSC */
|
||||||
FinalTickCount = AR::CpuFunc::ReadTimeStampCounterProcessor(&TscAux);
|
FinalTickCount = AR::CpuFunc::ReadTimeStampCounterProcessor(&TscAux);
|
||||||
@@ -683,12 +683,12 @@ HL::Timer::ProbeTimerType(VOID)
|
|||||||
/* Determine if the ACPI PM Timer port is physically provisioned */
|
/* Determine if the ACPI PM Timer port is physically provisioned */
|
||||||
if(AcpiTimerInfo->TimerPort != 0)
|
if(AcpiTimerInfo->TimerPort != 0)
|
||||||
{
|
{
|
||||||
/* Route execution stalls through the active ACPI PM hardware */
|
/* Temporarily route execution stalls through the active ACPI PM hardware */
|
||||||
TimerRoutines.StallExecution = StallExecutionAcpiPm;
|
TimerRoutines.StallExecution = StallExecutionAcpiPm;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Route execution stalls through the legacy PIT hardware */
|
/* Temporarily route execution stalls through the legacy PIT hardware */
|
||||||
TimerRoutines.StallExecution = StallExecutionPit;
|
TimerRoutines.StallExecution = StallExecutionPit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -720,27 +720,31 @@ HL::Timer::ProbeTimerType(VOID)
|
|||||||
{
|
{
|
||||||
case TimerTsc:
|
case TimerTsc:
|
||||||
/* Register the TSC */
|
/* Register the TSC */
|
||||||
TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterTsc;
|
|
||||||
PerformanceFrequency = CalibrateTscCounter();
|
PerformanceFrequency = CalibrateTscCounter();
|
||||||
|
TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterTsc;
|
||||||
|
TimerRoutines.StallExecution = StallExecutionTsc;
|
||||||
DebugPrint(L"Performance Counter: Invariant TSC @ %lluHz\n", PerformanceFrequency);
|
DebugPrint(L"Performance Counter: Invariant TSC @ %lluHz\n", PerformanceFrequency);
|
||||||
break;
|
break;
|
||||||
case TimerHpet:
|
case TimerHpet:
|
||||||
/* Register the HPET */
|
/* Register the HPET */
|
||||||
TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterHpet;
|
|
||||||
PerformanceFrequency = HpetFrequency;
|
PerformanceFrequency = HpetFrequency;
|
||||||
|
TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterHpet;
|
||||||
|
TimerRoutines.StallExecution = StallExecutionHpet;
|
||||||
DebugPrint(L"Performance Counter: HPET @ %lluHz\n", PerformanceFrequency);
|
DebugPrint(L"Performance Counter: HPET @ %lluHz\n", PerformanceFrequency);
|
||||||
break;
|
break;
|
||||||
case TimerAcpiPm:
|
case TimerAcpiPm:
|
||||||
/* Register the ACPI PM */
|
/* Register the ACPI PM */
|
||||||
TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterAcpiPm;
|
|
||||||
PerformanceFrequency = 3579545;
|
PerformanceFrequency = 3579545;
|
||||||
|
TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterAcpiPm;
|
||||||
|
TimerRoutines.StallExecution = StallExecutionAcpiPm;
|
||||||
KeInitializeSpinLock(&PerformanceCounterLock);
|
KeInitializeSpinLock(&PerformanceCounterLock);
|
||||||
DebugPrint(L"Performance Counter: ACPI PM Timer\n");
|
DebugPrint(L"Performance Counter: ACPI PM Timer\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Register the legacy PIT */
|
/* Register the legacy PIT */
|
||||||
TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterPit;
|
|
||||||
PerformanceFrequency = 1193182;
|
PerformanceFrequency = 1193182;
|
||||||
|
TimerRoutines.QueryPerformanceCounter = QueryPerformanceCounterPit;
|
||||||
|
TimerRoutines.StallExecution = StallExecutionPit;
|
||||||
KeInitializeSpinLock(&PerformanceCounterLock);
|
KeInitializeSpinLock(&PerformanceCounterLock);
|
||||||
DebugPrint(L"Performance Counter: Legacy PIT\n");
|
DebugPrint(L"Performance Counter: Legacy PIT\n");
|
||||||
break;
|
break;
|
||||||
@@ -1264,6 +1268,50 @@ HL::Timer::StallExecutionAcpiPm(IN ULONG MicroSeconds)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stalls the CPU execution for a specified duration (maximum 3 seconds) using the High Precision Event Timer (HPET).
|
||||||
|
*
|
||||||
|
* @param MicroSeconds
|
||||||
|
* Supplies the number of microseconds to stall execution.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
VOID
|
||||||
|
HL::Timer::StallExecutionHpet(IN ULONG MicroSeconds)
|
||||||
|
{
|
||||||
|
PHPET_REGISTERS Hpet;
|
||||||
|
ULONGLONG StartTick, TargetTicks;
|
||||||
|
|
||||||
|
/* Validate input parameter */
|
||||||
|
if(MicroSeconds == 0)
|
||||||
|
{
|
||||||
|
/* Nothing to do */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(MicroSeconds > 3000000)
|
||||||
|
{
|
||||||
|
/* Cap execution stall to 3 seconds */
|
||||||
|
MicroSeconds = 3000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cast the mapped virtual address to the HPET hardware register */
|
||||||
|
Hpet = (PHPET_REGISTERS)HpetAddress;
|
||||||
|
|
||||||
|
/* Calculate target ticks based on HPET frequency */
|
||||||
|
TargetTicks = ((ULONGLONG)MicroSeconds * PerformanceFrequency) / 1000000ULL;
|
||||||
|
StartTick = Hpet->MainCounterValue;
|
||||||
|
|
||||||
|
/* Spin until the elapsed ticks reach the target */
|
||||||
|
while((Hpet->MainCounterValue - StartTick) < TargetTicks)
|
||||||
|
{
|
||||||
|
/* Issue a PAUSE instruction to relieve memory bus contention */
|
||||||
|
AR::CpuFunc::YieldProcessor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stalls the CPU execution for a specified duration (maximum 3 seconds) using the legacy PIT timer.
|
* Stalls the CPU execution for a specified duration (maximum 3 seconds) using the legacy PIT timer.
|
||||||
*
|
*
|
||||||
@@ -1335,6 +1383,46 @@ HL::Timer::StallExecutionPit(IN ULONG MicroSeconds)
|
|||||||
HL::IoPort::WritePort8(0x61, Port61State);
|
HL::IoPort::WritePort8(0x61, Port61State);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stalls the CPU execution for a specified duration (maximum 3 seconds) using the Time Stamp Counter (TSC).
|
||||||
|
*
|
||||||
|
* @param MicroSeconds
|
||||||
|
* Supplies the number of microseconds to stall execution.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
VOID
|
||||||
|
HL::Timer::StallExecutionTsc(IN ULONG MicroSeconds)
|
||||||
|
{
|
||||||
|
ULONGLONG StartTick, TargetTicks;
|
||||||
|
|
||||||
|
/* Validate input parameter */
|
||||||
|
if(MicroSeconds == 0)
|
||||||
|
{
|
||||||
|
/* Nothing to do */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(MicroSeconds > 3000000)
|
||||||
|
{
|
||||||
|
/* Cap execution stall to 3 seconds */
|
||||||
|
MicroSeconds = 3000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate target ticks based on calibrated TSC frequency */
|
||||||
|
TargetTicks = ((ULONGLONG)MicroSeconds * PerformanceFrequency) / 1000000ULL;
|
||||||
|
StartTick = AR::CpuFunc::ReadTimeStampCounter();
|
||||||
|
|
||||||
|
/* Spin until the elapsed ticks reach the target */
|
||||||
|
while((AR::CpuFunc::ReadTimeStampCounter() - StartTick) < TargetTicks)
|
||||||
|
{
|
||||||
|
/* Issue a PAUSE instruction to relieve memory bus contention */
|
||||||
|
AR::CpuFunc::YieldProcessor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables the profile interrupt for the specified profile source.
|
* Enables the profile interrupt for the specified profile source.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -65,7 +65,9 @@ namespace HL
|
|||||||
STATIC XTAPI VOID QueryTimerCapabilities(VOID);
|
STATIC XTAPI VOID QueryTimerCapabilities(VOID);
|
||||||
STATIC XTAPI ULONG SetClockRateApic(ULONG TargetIncrement);
|
STATIC XTAPI ULONG SetClockRateApic(ULONG TargetIncrement);
|
||||||
STATIC XTAPI VOID StallExecutionAcpiPm(IN ULONG MicroSeconds);
|
STATIC XTAPI VOID StallExecutionAcpiPm(IN ULONG MicroSeconds);
|
||||||
|
STATIC XTAPI VOID StallExecutionHpet(IN ULONG MicroSeconds);
|
||||||
STATIC XTAPI VOID StallExecutionPit(IN ULONG MicroSeconds);
|
STATIC XTAPI VOID StallExecutionPit(IN ULONG MicroSeconds);
|
||||||
|
STATIC XTAPI VOID StallExecutionTsc(IN ULONG MicroSeconds);
|
||||||
STATIC XTAPI BOOLEAN ValidateTimerSupport(IN TIMER_TYPE TimerType,
|
STATIC XTAPI BOOLEAN ValidateTimerSupport(IN TIMER_TYPE TimerType,
|
||||||
IN BOOLEAN IsClock);
|
IN BOOLEAN IsClock);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user