- 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:
Timo Kreuzer 2011-09-09 15:42:59 +00:00
parent da83700379
commit 4c5b0d11ab
3 changed files with 57 additions and 13 deletions

View file

@ -113,6 +113,11 @@ KIRQL
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 @@ ApicSetCurrentIrql(KIRQL Irql)
{
/* Convert IRQL and write the TPR */
ApicWrite(APIC_TPR, IrqlToTpr(Irql));
/* HACK: Keep PCR field in sync, s.a. */
KeGetPcr()->Irql = Irql;
}
UCHAR

View file

@ -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
@ -42,6 +43,10 @@ RtcSetClockRate(UCHAR ClockRate)
EFlags = __readeflags();
_disable();
/* Update the global values */
HalpCurrentRate = ClockRate;
HalpCurrentTimeIncrement = RtcClockRateToIncrement(ClockRate);
/* Acquire CMOS lock */
HalpAcquireCmosSpinLock();
@ -83,8 +88,13 @@ HalpInitializeClock(VOID)
/* 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 @@ HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
/* 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 @@ HalSetTimeIncrement(IN ULONG Increment)
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;

View file

@ -17,11 +17,40 @@
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
HalpInitializeTsc()
@ -45,9 +74,9 @@ HalpInitializeTsc()
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 @@ HalpInitializeTsc()
/* 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 @@ KeStallExecutionProcessor(ULONG MicroSeconds)
StartTime = __rdtsc();
/* Calculate the ending time */
EndTime = StartTime + HalpCpuClockFrequency.QuadPart * MicroSeconds;
EndTime = StartTime + KeGetPcr()->StallScaleFactor * MicroSeconds;
/* Loop until time is elapsed */
while (__rdtsc() < EndTime);