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=53658&r1=53657&r2=53658&view=diff
==============================================================================
--- 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?rev=53658&r1=53657&r2=53658&view=diff
==============================================================================
--- 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=53658&r1=53657&r2=53658&view=diff
==============================================================================
--- 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);


Reply via email to