You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// If a hypervisor is "shaving" cycles globally to hide the latency of Thread 2's CPUID spam,
5514
+
// it subtracts time from the global counter. This causes Thread 1 (which caused no exits)
5515
+
// to appear to have finished its work instantly or impossibly fast.
5516
+
// If thread 1 reports finishing 100000000 dependent iterations in only 10000000 TSC cycles (so 0.1 cycles/iter), the CPU effectively ran at 10 instructions per cycle on a dependent chain
5517
+
// which is basically impossible on x86 silicon and confirms the TSC was manipulated
5544
5518
5545
-
const NTSTATUS status = CallNtPowerInformation(
5546
-
ProcessorInformation,
5547
-
nullptr, 0,
5548
-
raw, static_cast<ULONG>(bufSize)
5549
-
);
5550
-
5551
-
unsigned speed = 0;
5552
-
if ((LONG)status >= 0) {
5553
-
PROCESSOR_POWER_INFORMATION* info = reinterpret_cast<PROCESSOR_POWER_INFORMATION*>(raw);
// 0.25 is an extremely conservative threshold but there's no need to raise it
5520
+
// because mathematically talking, considering the number of times cpuid is called in thread 2, they will pass this limit even with a patch that downscales only 100 cycles per cpuid call
5521
+
// a value this low implies the code ran 4x faster than the theoretical limit of the silicon,
5522
+
// or roughly 12x faster than the actual core clock speed
5523
+
5524
+
// This is immune to turbo/throttling noise because those variances (10-30%) are negligible
5525
+
// compared to the massive reduction (like 90%+) caused by exit hiding
5526
+
if (cycles_per_iter < 0.25) {
5527
+
debug("TIMER: Detected a hypervisor dowscaling TSC globally (IPC was impossible): ", cycles_per_iter);
5528
+
returntrue;
5555
5529
}
5556
5530
5557
-
_freea(raw);
5558
-
5559
-
if (speed < 800) {
5560
-
debug("TIMER: Detected a hook in rdtsc, frequency was: ", speed);
5531
+
// so if the patch substracted too much TSC cycles, the shaving might result in a near-zero or negative delta
5532
+
// (handled by u64 overflow usually making it huge, but good shaves clamp to 0 or 1)
5533
+
if (t1_delta < 1000) {
5534
+
debug("TIMER: Detected a hypervisor downscaling TSC globally (time was stopped): ", t1_delta);
0 commit comments