namespace XFESystem.NativeKernel;
// Single-BSP elapsed-time source. CPUID crystal/ratio is preferred; otherwise
// channel 2 of the legacy PIT measures TSC frequency without enabling an IRQ.
public static unsafe class MonotonicClock
{
public static ulong Frequency;
public static bool Ready, Invariant;
static ulong _origin;
public static bool Initialize()
{
Frequency = 0;
uint* result = stackalloc uint[4];
Native.CpuId(0x80000000, 0, result);
if (result[0] >= 0x80000007)
{
Native.CpuId(0x80000007, 0, result);
Invariant = (result[3] & (1u << 8)) != 0;
}
if (Cpu.MaximumLeaf >= 0x15)
{
Native.CpuId(0x15, 0, result);
if (result[0] != 0 && result[1] != 0 && result[2] != 0)
Frequency = (ulong)result[2] * result[1] / result[0];
}
if (Frequency == 0) Frequency = CalibratePit();
if (Frequency < 1000000 || Frequency > 10000000000) return false;
_origin = Native.ReadTsc();
Ready = true;
ulong before = Nanoseconds();
for (uint i = 0; i < 1000; i++) Native.Pause();
return Nanoseconds() >= before;
}
static ulong CalibratePit()
{
const ushort ticks = 11932;
byte original = Native.In8(0x61);
if (original == 0xff) return 0;
Native.Out8(0x61, (byte)(original & ~3));
Native.Out8(0x43, 0xb0); // channel 2, lo/hi, mode zero, binary
Native.Out8(0x42, (byte)(ticks & 255));
Native.Out8(0x42, (byte)(ticks >> 8));
ulong start = Native.ReadTsc();
Native.Out8(0x61, (byte)((original & ~2) | 1));
bool complete = false;
for (uint poll = 0; poll < 2000000; poll++)
{
if ((Native.In8(0x61) & 0x20) != 0) { complete = true; break; }
Native.Pause();
}
ulong elapsed = Native.ReadTsc() - start;
Native.Out8(0x61, original);
if (!complete || elapsed > 100000000000UL) return 0;
return elapsed * 1193182 / ticks;
}
public static ulong Nanoseconds()
{
if (!Ready) return 0;
ulong elapsed = Native.ReadTsc() - _origin;
return elapsed / Frequency * 1000000000 + elapsed % Frequency * 1000000000 / Frequency;
}
}
namespace XFESystem.NativeKernel;
// Single-BSP elapsed-time source. CPUID crystal/ratio is preferred; otherwise
// channel 2 of the legacy PIT measures TSC frequency without enabling an IRQ.
public static unsafe class MonotonicClock
{
public static ulong Frequency;
public static bool Ready, Invariant;
static ulong _origin;
public static bool Initialize()
{
Frequency = 0;
uint* result = stackalloc uint[4];
Native.CpuId(0x80000000, 0, result);
if (result[0] >= 0x80000007)
{
Native.CpuId(0x80000007, 0, result);
Invariant = (result[3] & (1u << 8)) != 0;
}
if (Cpu.MaximumLeaf >= 0x15)
{
Native.CpuId(0x15, 0, result);
if (result[0] != 0 && result[1] != 0 && result[2] != 0)
Frequency = (ulong)result[2] * result[1] / result[0];
}
if (Frequency == 0) Frequency = CalibratePit();
if (Frequency < 1000000 || Frequency > 10000000000) return false;
_origin = Native.ReadTsc();
Ready = true;
ulong before = Nanoseconds();
for (uint i = 0; i < 1000; i++) Native.Pause();
return Nanoseconds() >= before;
}
static ulong CalibratePit()
{
const ushort ticks = 11932;
byte original = Native.In8(0x61);
if (original == 0xff) return 0;
Native.Out8(0x61, (byte)(original & ~3));
Native.Out8(0x43, 0xb0); // channel 2, lo/hi, mode zero, binary
Native.Out8(0x42, (byte)(ticks & 255));
Native.Out8(0x42, (byte)(ticks >> 8));
ulong start = Native.ReadTsc();
Native.Out8(0x61, (byte)((original & ~2) | 1));
bool complete = false;
for (uint poll = 0; poll < 2000000; poll++)
{
if ((Native.In8(0x61) & 0x20) != 0) { complete = true; break; }
Native.Pause();
}
ulong elapsed = Native.ReadTsc() - start;
Native.Out8(0x61, original);
if (!complete || elapsed > 100000000000UL) return 0;
return elapsed * 1193182 / ticks;
}
public static ulong Nanoseconds()
{
if (!Ready) return 0;
ulong elapsed = Native.ReadTsc() - _origin;
return elapsed / Frequency * 1000000000 + elapsed % Frequency * 1000000000 / Frequency;
}
}