Author: tkreuzer Date: Fri Sep 9 15:42:59 2011 New Revision: 53658
URL: http://svn.reactos.org/svn/reactos?rev=53658&view=rev Log: [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
Modified: trunk/reactos/hal/halx86/apic/apic.c trunk/reactos/hal/halx86/apic/rtctimer.c trunk/reactos/hal/halx86/apic/tsc.c
Modified: trunk/reactos/hal/halx86/apic/apic.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/apic.c?rev=... ============================================================================== --- trunk/reactos/hal/halx86/apic/apic.c [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/apic/apic.c [iso-8859-1] Fri Sep 9 15:42:59 2011 @@ -113,6 +113,11 @@ FORCEINLINE 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 */ return TprToIrql(ApicRead(APIC_TPR)); } @@ -123,6 +128,9 @@ { /* Convert IRQL and write the TPR */ ApicWrite(APIC_TPR, IrqlToTpr(Irql)); + + /* HACK: Keep PCR field in sync, s.a. */ + KeGetPcr()->Irql = Irql; }
UCHAR
Modified: trunk/reactos/hal/halx86/apic/rtctimer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/rtctimer.c?... ============================================================================== --- trunk/reactos/hal/halx86/apic/rtctimer.c [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/apic/rtctimer.c [iso-8859-1] Fri Sep 9 15:42:59 2011 @@ -19,9 +19,10 @@ const UCHAR HalpClockVector = 0xD1; BOOLEAN HalpClockSetMSRate; UCHAR HalpNextMSRate; -UCHAR HalpCurrentRate = 9; +UCHAR HalpCurrentRate = 9; /* Initial rate 9: 128 Hz / 7,8 ms */ 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 @@ -41,6 +42,10 @@ /* Disable interrupts */ EFlags = __readeflags(); _disable(); + + /* Update the global values */ + HalpCurrentRate = ClockRate; + HalpCurrentTimeIncrement = RtcClockRateToIncrement(ClockRate);
/* Acquire CMOS lock */ HalpAcquireCmosSpinLock(); @@ -83,7 +88,12 @@ /* Release CMOS lock */ HalpReleaseCmosSpinLock();
+ /* Set initial rate */ RtcSetClockRate(HalpCurrentRate); + + /* Notify the kernel about the maximum and minimum increment */ + KeSetTimeIncrement(RtcClockRateToIncrement(RtcMaximumClockRate), + RtcClockRateToIncrement(RtcMinimumClockRate));
DPRINT1("Clock initialized\n"); } @@ -110,10 +120,6 @@ /* Check if someone changed the time rate */ if (HalpClockSetMSRate) { - /* Update the global values */ - HalpCurrentRate = HalpNextMSRate; - HalpCurrentTimeIncrement = RtcClockRateToIncrement(HalpCurrentRate); - /* Set new clock rate */ RtcSetClockRate(HalpCurrentRate);
@@ -143,7 +149,7 @@ UCHAR Rate;
/* 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 */ if (RtcClockRateToIncrement(Rate + 1) > Increment) break;
Modified: trunk/reactos/hal/halx86/apic/tsc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/apic/tsc.c?rev=5... ============================================================================== --- trunk/reactos/hal/halx86/apic/tsc.c [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/apic/tsc.c [iso-8859-1] Fri Sep 9 15:42:59 2011 @@ -17,10 +17,39 @@ LARGE_INTEGER HalpCpuClockFrequency = {INITIAL_STALL_COUNT * 1000000};
UCHAR TscCalibrationPhase; -LARGE_INTEGER TscCalibrationArray[NUM_SAMPLES]; +ULONG64 TscCalibrationArray[NUM_SAMPLES]; UCHAR HalpRtcClockVector = 0xD1;
+#define RTC_MODE 6 /* Mode 6 is 1024 Hz */ +#define SAMPLE_FREQENCY ((32768 << 1) >> RTC_MODE) + /* 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 NTAPI @@ -45,9 +74,9 @@ RegisterB = HalpReadCmos(RTC_REGISTER_B); 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 = (RegisterA & 0xF0) | 9; + RegisterA = (RegisterA & 0xF0) | RTC_MODE; HalpWriteCmos(RTC_REGISTER_A, RegisterA);
/* Save old IDT entry */ @@ -80,8 +109,9 @@ /* Restore old IDT entry */ *IdtPointer = OldIdtEntry;
- // do linear regression - + /* Calculate an average, using simplified linear regression */ + HalpCpuClockFrequency.QuadPart = DoLinearRegression(NUM_SAMPLES - 1, + TscCalibrationArray);
/* Restore flags */ __writeeflags(Flags); @@ -133,7 +163,7 @@ StartTime = __rdtsc();
/* Calculate the ending time */ - EndTime = StartTime + HalpCpuClockFrequency.QuadPart * MicroSeconds; + EndTime = StartTime + KeGetPcr()->StallScaleFactor * MicroSeconds;
/* Loop until time is elapsed */ while (__rdtsc() < EndTime);