mirror of
https://github.com/reactos/reactos.git
synced 2024-10-02 23:46:50 +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
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue