mirror of
https://github.com/reactos/reactos.git
synced 2025-06-06 01:40:36 +00:00
[HAL]
- Add a hack to ApicGetCurrentIrql and ApicSetCurrentIrql to work around a VBox bug - call KeSetTimeIncrement after initializing the rtc clock - calculate TSC frequency from the samples - Fix a bug in KeStallExecutionProcessor svn path=/trunk/; revision=53658
This commit is contained in:
parent
da83700379
commit
4c5b0d11ab
3 changed files with 57 additions and 13 deletions
|
@ -113,6 +113,11 @@ KIRQL
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
ApicGetCurrentIrql(VOID)
|
ApicGetCurrentIrql(VOID)
|
||||||
{
|
{
|
||||||
|
// HACK: This won't work with amd64, where cr8 is modified directly, but
|
||||||
|
// VBox is broken and returns a wrong value when using a vmmcall after a
|
||||||
|
// page table modification.
|
||||||
|
return KeGetPcr()->Irql;
|
||||||
|
|
||||||
/* Read the TPR and convert it to an IRQL */
|
/* Read the TPR and convert it to an IRQL */
|
||||||
return TprToIrql(ApicRead(APIC_TPR));
|
return TprToIrql(ApicRead(APIC_TPR));
|
||||||
}
|
}
|
||||||
|
@ -123,6 +128,9 @@ ApicSetCurrentIrql(KIRQL Irql)
|
||||||
{
|
{
|
||||||
/* Convert IRQL and write the TPR */
|
/* Convert IRQL and write the TPR */
|
||||||
ApicWrite(APIC_TPR, IrqlToTpr(Irql));
|
ApicWrite(APIC_TPR, IrqlToTpr(Irql));
|
||||||
|
|
||||||
|
/* HACK: Keep PCR field in sync, s.a. */
|
||||||
|
KeGetPcr()->Irql = Irql;
|
||||||
}
|
}
|
||||||
|
|
||||||
UCHAR
|
UCHAR
|
||||||
|
|
|
@ -19,9 +19,10 @@
|
||||||
const UCHAR HalpClockVector = 0xD1;
|
const UCHAR HalpClockVector = 0xD1;
|
||||||
BOOLEAN HalpClockSetMSRate;
|
BOOLEAN HalpClockSetMSRate;
|
||||||
UCHAR HalpNextMSRate;
|
UCHAR HalpNextMSRate;
|
||||||
UCHAR HalpCurrentRate = 9;
|
UCHAR HalpCurrentRate = 9; /* Initial rate 9: 128 Hz / 7,8 ms */
|
||||||
ULONG HalpCurrentTimeIncrement;
|
ULONG HalpCurrentTimeIncrement;
|
||||||
static UCHAR RtcLargestClockRate = 10;
|
static UCHAR RtcMinimumClockRate = 6; /* Minimum rate 6: 16 Hz / 62,5 ms */
|
||||||
|
static UCHAR RtcMaximumClockRate = 10; /* Maximum rate 10: 256 Hz / 3,9 ms */
|
||||||
|
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
|
@ -42,6 +43,10 @@ RtcSetClockRate(UCHAR ClockRate)
|
||||||
EFlags = __readeflags();
|
EFlags = __readeflags();
|
||||||
_disable();
|
_disable();
|
||||||
|
|
||||||
|
/* Update the global values */
|
||||||
|
HalpCurrentRate = ClockRate;
|
||||||
|
HalpCurrentTimeIncrement = RtcClockRateToIncrement(ClockRate);
|
||||||
|
|
||||||
/* Acquire CMOS lock */
|
/* Acquire CMOS lock */
|
||||||
HalpAcquireCmosSpinLock();
|
HalpAcquireCmosSpinLock();
|
||||||
|
|
||||||
|
@ -83,8 +88,13 @@ HalpInitializeClock(VOID)
|
||||||
/* Release CMOS lock */
|
/* Release CMOS lock */
|
||||||
HalpReleaseCmosSpinLock();
|
HalpReleaseCmosSpinLock();
|
||||||
|
|
||||||
|
/* Set initial rate */
|
||||||
RtcSetClockRate(HalpCurrentRate);
|
RtcSetClockRate(HalpCurrentRate);
|
||||||
|
|
||||||
|
/* Notify the kernel about the maximum and minimum increment */
|
||||||
|
KeSetTimeIncrement(RtcClockRateToIncrement(RtcMaximumClockRate),
|
||||||
|
RtcClockRateToIncrement(RtcMinimumClockRate));
|
||||||
|
|
||||||
DPRINT1("Clock initialized\n");
|
DPRINT1("Clock initialized\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,10 +120,6 @@ HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
|
||||||
/* Check if someone changed the time rate */
|
/* Check if someone changed the time rate */
|
||||||
if (HalpClockSetMSRate)
|
if (HalpClockSetMSRate)
|
||||||
{
|
{
|
||||||
/* Update the global values */
|
|
||||||
HalpCurrentRate = HalpNextMSRate;
|
|
||||||
HalpCurrentTimeIncrement = RtcClockRateToIncrement(HalpCurrentRate);
|
|
||||||
|
|
||||||
/* Set new clock rate */
|
/* Set new clock rate */
|
||||||
RtcSetClockRate(HalpCurrentRate);
|
RtcSetClockRate(HalpCurrentRate);
|
||||||
|
|
||||||
|
@ -143,7 +149,7 @@ HalSetTimeIncrement(IN ULONG Increment)
|
||||||
UCHAR Rate;
|
UCHAR Rate;
|
||||||
|
|
||||||
/* Lookup largest value below given Increment */
|
/* Lookup largest value below given Increment */
|
||||||
for (Rate = 2; Rate < RtcLargestClockRate; Rate++)
|
for (Rate = RtcMinimumClockRate; Rate <= RtcMaximumClockRate; Rate++)
|
||||||
{
|
{
|
||||||
/* Check if this is the largest rate possible */
|
/* Check if this is the largest rate possible */
|
||||||
if (RtcClockRateToIncrement(Rate + 1) > Increment) break;
|
if (RtcClockRateToIncrement(Rate + 1) > Increment) break;
|
||||||
|
|
|
@ -17,11 +17,40 @@
|
||||||
LARGE_INTEGER HalpCpuClockFrequency = {INITIAL_STALL_COUNT * 1000000};
|
LARGE_INTEGER HalpCpuClockFrequency = {INITIAL_STALL_COUNT * 1000000};
|
||||||
|
|
||||||
UCHAR TscCalibrationPhase;
|
UCHAR TscCalibrationPhase;
|
||||||
LARGE_INTEGER TscCalibrationArray[NUM_SAMPLES];
|
ULONG64 TscCalibrationArray[NUM_SAMPLES];
|
||||||
UCHAR HalpRtcClockVector = 0xD1;
|
UCHAR HalpRtcClockVector = 0xD1;
|
||||||
|
|
||||||
|
#define RTC_MODE 6 /* Mode 6 is 1024 Hz */
|
||||||
|
#define SAMPLE_FREQENCY ((32768 << 1) >> RTC_MODE)
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
static
|
||||||
|
ULONG64
|
||||||
|
DoLinearRegression(
|
||||||
|
ULONG XMax,
|
||||||
|
ULONG64 *ArrayY)
|
||||||
|
{
|
||||||
|
ULONG X, SumXX;
|
||||||
|
ULONG64 SumXY;
|
||||||
|
|
||||||
|
/* Calculate the sum of the squares of X */
|
||||||
|
SumXX = (XMax * (XMax + 1) * (2*XMax + 1)) / 6;
|
||||||
|
|
||||||
|
/* Calculate the sum of the differences to the first value
|
||||||
|
weighted by x */
|
||||||
|
for (SumXY = 0, X = 1; X <= XMax; X++)
|
||||||
|
{
|
||||||
|
SumXY += X * (ArrayY[X] - ArrayY[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Account for sample frequency */
|
||||||
|
SumXY *= SAMPLE_FREQENCY;
|
||||||
|
|
||||||
|
/* Return the quotient of the sums */
|
||||||
|
return (SumXY + (SumXX/2)) / SumXX;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
HalpInitializeTsc()
|
HalpInitializeTsc()
|
||||||
|
@ -45,9 +74,9 @@ HalpInitializeTsc()
|
||||||
RegisterB = HalpReadCmos(RTC_REGISTER_B);
|
RegisterB = HalpReadCmos(RTC_REGISTER_B);
|
||||||
HalpWriteCmos(RTC_REGISTER_B, RegisterB | RTC_REG_B_PI);
|
HalpWriteCmos(RTC_REGISTER_B, RegisterB | RTC_REG_B_PI);
|
||||||
|
|
||||||
/* Modify register A to get 4096 Hz */
|
/* Modify register A to RTC_MODE to get SAMPLE_FREQENCY */
|
||||||
RegisterA = HalpReadCmos(RTC_REGISTER_A);
|
RegisterA = HalpReadCmos(RTC_REGISTER_A);
|
||||||
RegisterA = (RegisterA & 0xF0) | 9;
|
RegisterA = (RegisterA & 0xF0) | RTC_MODE;
|
||||||
HalpWriteCmos(RTC_REGISTER_A, RegisterA);
|
HalpWriteCmos(RTC_REGISTER_A, RegisterA);
|
||||||
|
|
||||||
/* Save old IDT entry */
|
/* Save old IDT entry */
|
||||||
|
@ -80,8 +109,9 @@ HalpInitializeTsc()
|
||||||
/* Restore old IDT entry */
|
/* Restore old IDT entry */
|
||||||
*IdtPointer = OldIdtEntry;
|
*IdtPointer = OldIdtEntry;
|
||||||
|
|
||||||
// do linear regression
|
/* Calculate an average, using simplified linear regression */
|
||||||
|
HalpCpuClockFrequency.QuadPart = DoLinearRegression(NUM_SAMPLES - 1,
|
||||||
|
TscCalibrationArray);
|
||||||
|
|
||||||
/* Restore flags */
|
/* Restore flags */
|
||||||
__writeeflags(Flags);
|
__writeeflags(Flags);
|
||||||
|
@ -133,7 +163,7 @@ KeStallExecutionProcessor(ULONG MicroSeconds)
|
||||||
StartTime = __rdtsc();
|
StartTime = __rdtsc();
|
||||||
|
|
||||||
/* Calculate the ending time */
|
/* Calculate the ending time */
|
||||||
EndTime = StartTime + HalpCpuClockFrequency.QuadPart * MicroSeconds;
|
EndTime = StartTime + KeGetPcr()->StallScaleFactor * MicroSeconds;
|
||||||
|
|
||||||
/* Loop until time is elapsed */
|
/* Loop until time is elapsed */
|
||||||
while (__rdtsc() < EndTime);
|
while (__rdtsc() < EndTime);
|
||||||
|
|
Loading…
Reference in a new issue