143 lines
4.0 KiB
C#
143 lines
4.0 KiB
C#
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: HalMpClock.cs
|
|
//
|
|
// Note:
|
|
//
|
|
// This file is an implementation of Interfaces/Hal/HalClock.csi
|
|
//
|
|
// For now we just read the time from the HPET or PMTimer. Both of these
|
|
// use a spinlock to protect the relevant state. The PMTimer is incredibly
|
|
// expensive.
|
|
|
|
|
|
#if !SINGULARITY_MP
|
|
#error "This file is only for MP builds."
|
|
#endif
|
|
|
|
namespace Microsoft.Singularity.Hal
|
|
{
|
|
using Microsoft.Singularity.Hal.Acpi;
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Threading;
|
|
|
|
public class HalClockApic : HalClock
|
|
{
|
|
Apic apic;
|
|
PMClock pmClock;
|
|
RTClockApic rtClock;
|
|
HpetClock hpetClock;
|
|
SpinLock spinLock;
|
|
|
|
internal HalClockApic(Apic apic, RTClockApic rtClock, PMClock pmClock)
|
|
{
|
|
this.apic = apic;
|
|
this.rtClock = rtClock;
|
|
this.pmClock = pmClock;
|
|
this.hpetClock = null;
|
|
this.spinLock = new SpinLock(SpinLock.Types.MpHalClock);
|
|
}
|
|
|
|
[Conditional("SINGULARITY_MP")]
|
|
[NoHeapAllocation]
|
|
private void AcquireLock()
|
|
{
|
|
this.spinLock.Acquire();
|
|
}
|
|
|
|
[Conditional("SINGULARITY_MP")]
|
|
[NoHeapAllocation]
|
|
private void ReleaseLock()
|
|
{
|
|
this.spinLock.Release();
|
|
}
|
|
|
|
[NoHeapAllocation][HalLock]
|
|
public override long GetKernelTicks()
|
|
{
|
|
bool en = Processor.DisableInterrupts();
|
|
this.AcquireLock();
|
|
try {
|
|
if (this.hpetClock == null) {
|
|
return (long) pmClock.GetKernelTicks();
|
|
}
|
|
else {
|
|
return (long) hpetClock.GetKernelTicks();
|
|
}
|
|
}
|
|
finally {
|
|
this.ReleaseLock();
|
|
Processor.RestoreInterrupts(en);
|
|
}
|
|
}
|
|
|
|
internal byte Interrupt
|
|
{
|
|
[NoHeapAllocation]
|
|
get { return rtClock.Interrupt; }
|
|
}
|
|
|
|
[NoHeapAllocation][HalLock]
|
|
public override void ClearInterrupt()
|
|
{
|
|
bool en = Processor.DisableInterrupts();
|
|
this.AcquireLock();
|
|
try {
|
|
Microsoft.Singularity.Hal.Platform p = Microsoft.Singularity.Hal.Platform.ThePlatform;
|
|
if (hpetClock == null) {
|
|
pmClock.Update();
|
|
}
|
|
else {
|
|
hpetClock.Update();
|
|
}
|
|
rtClock.ClearInterrupt();
|
|
}
|
|
finally {
|
|
this.ReleaseLock();
|
|
Processor.RestoreInterrupts(en);
|
|
}
|
|
}
|
|
|
|
[HalLock]
|
|
internal void SwitchToHpetClock(HpetClock hc)
|
|
{
|
|
// Change rt clock interrupt frequency to appropriate
|
|
// rate for HPET main clock.
|
|
bool en = Processor.DisableInterrupts();
|
|
this.AcquireLock();
|
|
try {
|
|
rtClock.SetFrequency(HpetClock.UpdateFrequency(hc.Hpet));
|
|
hpetClock = hc;
|
|
}
|
|
finally {
|
|
this.ReleaseLock();
|
|
Processor.RestoreInterrupts(en);
|
|
}
|
|
DebugStub.Print("Hal switching to HpetClock.\n");
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public override void CpuResumeFromHaltEvent()
|
|
{
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public override long GetRtcTime()
|
|
{
|
|
return rtClock.GetBootTime() + GetKernelTicks();
|
|
}
|
|
|
|
public override void SetRtcTime(long newRtcTime)
|
|
{
|
|
rtClock.SetRtcTime(newRtcTime, GetKernelTicks());
|
|
}
|
|
}
|
|
}
|