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=…
==============================================================================
--- 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);