15fecf5d8SWill Auld #include "libcflat.h" 25fecf5d8SWill Auld #include "processor.h" 35fecf5d8SWill Auld 45fecf5d8SWill Auld #define IA32_TSC_ADJUST 0x3b 55fecf5d8SWill Auld 65fecf5d8SWill Auld int main() 75fecf5d8SWill Auld { 85fecf5d8SWill Auld u64 t1, t2, t3, t4, t5; 95fecf5d8SWill Auld u64 est_delta_time; 105fecf5d8SWill Auld 115fecf5d8SWill Auld if (cpuid(7).b & (1 << 1)) { // IA32_TSC_ADJUST Feature is enabled? 12*1ce2224dSAndrew Jones report("IA32_TSC_ADJUST msr initialization", 13*1ce2224dSAndrew Jones rdmsr(IA32_TSC_ADJUST) == 0x0); 145fecf5d8SWill Auld t3 = 100000000000ull; 155fecf5d8SWill Auld t1 = rdtsc(); 165fecf5d8SWill Auld wrmsr(IA32_TSC_ADJUST, t3); 175fecf5d8SWill Auld t2 = rdtsc(); 18*1ce2224dSAndrew Jones report("IA32_TSC_ADJUST msr read / write", 19*1ce2224dSAndrew Jones rdmsr(IA32_TSC_ADJUST) == t3); 20*1ce2224dSAndrew Jones report("TSC adjustment for IA32_TSC_ADJUST value", 21*1ce2224dSAndrew Jones (t2 - t1) >= t3); 225fecf5d8SWill Auld t3 = 0x0; 235fecf5d8SWill Auld wrmsr(IA32_TSC_ADJUST, t3); 24*1ce2224dSAndrew Jones report("IA32_TSC_ADJUST msr read / write", 25*1ce2224dSAndrew Jones rdmsr(IA32_TSC_ADJUST) == t3); 265fecf5d8SWill Auld t4 = 100000000000ull; 275fecf5d8SWill Auld t1 = rdtsc(); 285fecf5d8SWill Auld wrtsc(t4); 295fecf5d8SWill Auld t2 = rdtsc(); 305fecf5d8SWill Auld t5 = rdmsr(IA32_TSC_ADJUST); 315fecf5d8SWill Auld // est of time between reading tsc and writing tsc, 325fecf5d8SWill Auld // (based on IA32_TSC_ADJUST msr value) should be small 335fecf5d8SWill Auld est_delta_time = t4 - t5 - t1; 345fecf5d8SWill Auld // arbitray 2x latency (wrtsc->rdtsc) threshold 35*1ce2224dSAndrew Jones report("IA32_TSC_ADJUST msr adjustment on tsc write", 36*1ce2224dSAndrew Jones est_delta_time <= (2 * (t2 - t4))); 375fecf5d8SWill Auld } 385fecf5d8SWill Auld else { 39*1ce2224dSAndrew Jones report("IA32_TSC_ADJUST feature not enabled", true); 405fecf5d8SWill Auld } 41*1ce2224dSAndrew Jones return report_summary(); 425fecf5d8SWill Auld } 43