87 lines
2.7 KiB
C#
87 lines
2.7 KiB
C#
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: Calibration.cs
|
||
|
//
|
||
|
//
|
||
|
// Note:
|
||
|
//
|
||
|
|
||
|
namespace Microsoft.Singularity.Hal
|
||
|
{
|
||
|
using Microsoft.Singularity.Hal.Acpi;
|
||
|
|
||
|
internal class Calibrate
|
||
|
{
|
||
|
private static uint PmDelta(uint newValue, uint oldValue)
|
||
|
{
|
||
|
// PmTimer may be 24 or 32 bits depending on system.
|
||
|
// Simplest to treat as 24 bits.
|
||
|
return (newValue - oldValue) & 0x00ffffff;
|
||
|
}
|
||
|
|
||
|
internal static void CpuCycleCounter(PMTimer pmTimer)
|
||
|
{
|
||
|
uint pmLast = pmTimer.Value;
|
||
|
ulong tscLast = Processor.CycleCount;
|
||
|
|
||
|
uint pmLimit = PMTimer.FrequencyHz / 15;
|
||
|
uint pmAccum = 0;
|
||
|
ulong tscNow = 0;
|
||
|
|
||
|
// Initial measurements
|
||
|
tscLast = Processor.CycleCount;
|
||
|
pmLast = pmTimer.Value;
|
||
|
|
||
|
// Measurement loop
|
||
|
do
|
||
|
{
|
||
|
tscNow = Processor.CycleCount;
|
||
|
uint pmNow = pmTimer.Value;
|
||
|
pmAccum += PmDelta(pmNow, pmLast);
|
||
|
pmLast = pmNow;
|
||
|
} while (pmAccum < pmLimit);
|
||
|
|
||
|
ulong tscHz = PMTimer.FrequencyHz * (tscNow - tscLast) / pmAccum;
|
||
|
DebugStub.Print("Cpu{0}: TSC frequency {1} Hz\n",
|
||
|
__arglist(Processor.CurrentProcessor.Id, tscHz));
|
||
|
Processor.CyclesPerSecond = tscHz;
|
||
|
}
|
||
|
|
||
|
internal static void ApicTimer(PMTimer pmTimer, ApicTimer apicTimer)
|
||
|
{
|
||
|
apicTimer.SetDivisor(1);
|
||
|
apicTimer.SetOneShot();
|
||
|
apicTimer.SetInterruptEnabled(false);
|
||
|
apicTimer.SetInitialCount(~0u);
|
||
|
|
||
|
uint apicLast = apicTimer.Value;
|
||
|
uint pmLast = pmTimer.Value;
|
||
|
|
||
|
uint pmLimit = PMTimer.FrequencyHz / 15;
|
||
|
uint pmAccum = 0;
|
||
|
uint apicNow = 0;
|
||
|
|
||
|
// Initial measurements
|
||
|
apicLast = apicTimer.Value;
|
||
|
pmLast = pmTimer.Value;
|
||
|
do
|
||
|
{
|
||
|
apicNow = apicTimer.Value;
|
||
|
uint pmNow = pmTimer.Value | 0xff000000;
|
||
|
pmAccum += PmDelta(pmNow, pmLast);
|
||
|
pmLast = pmNow;
|
||
|
} while (pmAccum < pmLimit);
|
||
|
|
||
|
ulong apicHz = PMTimer.FrequencyHz * (ulong)(apicLast - apicNow) / pmAccum;
|
||
|
DebugStub.Print("Cpu{0}: APIC timer frequency {1} Hz\n",
|
||
|
__arglist(Processor.CurrentProcessor.Id, apicHz));
|
||
|
|
||
|
apicTimer.SetBusFrequency((uint)apicHz);
|
||
|
}
|
||
|
}
|
||
|
}
|