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 (!QueryPerformanceFrequency(&freq)) // NtPowerInformation and NtQueryPerformanceCounter are avoided as some hypervisors downscale tsc only if we triggered a context switch from userspace
4452
4458
returnfalse;
4453
4459
4454
-
// calculates the invariant TSC base rate, not the dynamic core frequency, similar to what CallNtPowerInformation would give you
4460
+
// calculates the invariant TSC base rate (on modern CPUs), not the dynamic core frequency, similar to what CallNtPowerInformation would give you
4455
4461
LARGE_INTEGER t1q, t2q;
4456
4462
constu64 t1 = __rdtsc();
4457
4463
QueryPerformanceCounter(&t1q); // uses RDTSCP under the hood unless platformclock (a bcdedit setting) is set, which then would use HPET or ACPI PM via NtQueryPerformanceCounter
4458
4464
SleepEx(50, 0);
4459
4465
QueryPerformanceCounter(&t2q);
4460
-
constu64 t2 = __rdtsc();
4466
+
constu64 t2 = __rdtscp(&aux);
4461
4467
4462
4468
constdouble elapsedSec = double(t2q.QuadPart - t1q.QuadPart) / double(freq.QuadPart); // the performance counter frequency is always 10MHz when running under Hyper-V
4463
4469
constdouble tscHz = double(t2 - t1) / elapsedSec;
@@ -4478,16 +4484,13 @@ struct VM {
4478
4484
}
4479
4485
else {
4480
4486
debug("TIMER: Processor base speed -> ", static_cast<double>(baseMHz), " MHz");
4487
+
// this -650 delta accounts for older CPUs, it's better to use this rather than calling CPUID to know if the CPU supports invariant TSC, as it can be spoofed
4481
4488
if (tscMHz <= static_cast<double>(baseMHz) - 650.0) {
4482
4489
returntrue;
4483
4490
}
4484
4491
}
4485
4492
4486
4493
// Case C - Hypervisor with RDTSC patch + useplatformclock = false
staticthread_localvolatileunsignedlonglong g_sink = 0; // so that it doesnt need to be captured by the lambda
@@ -4509,7 +4512,7 @@ struct VM {
4509
4512
usingfn_t = unsignedlonglong (*)();
4510
4513
4511
4514
// make the pointer volatile so the compiler treats the call as opaque/indirect
4512
-
volatilefn_t rd_ptr = +rd_lambda; // +lambda forces conversion to function ptr, so it won't be inlined, we need this for the trick
4515
+
volatilefn_t rd_ptr = +rd_lambda; // +lambda forces conversion to function ptr, so it won't be inlined, we need this to prevent some optimizatons by the compiler
0 commit comments