1 /* 2 * Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <OS.h> 8 9 #include <stdint.h> 10 11 #include <x86intrin.h> 12 13 14 static uint64_t cv_factor; 15 static uint64_t cv_factor_nsec; 16 17 18 static int64_t 19 __system_time_lfence() 20 { 21 __builtin_ia32_lfence(); 22 __uint128_t time = static_cast<__uint128_t>(__rdtsc()) * cv_factor; 23 return time >> 64; 24 } 25 26 27 static int64_t 28 __system_time_rdtscp() 29 { 30 uint32_t aux; 31 __uint128_t time = static_cast<__uint128_t>(__rdtscp(&aux)) * cv_factor; 32 return time >> 64; 33 } 34 35 36 static int64_t 37 __system_time_nsecs_lfence() 38 { 39 __builtin_ia32_lfence(); 40 __uint128_t t = static_cast<__uint128_t>(__rdtsc()) * cv_factor_nsec; 41 return t >> 32; 42 } 43 44 45 static int64_t 46 __system_time_nsecs_rdtscp() 47 { 48 uint32_t aux; 49 __uint128_t t = static_cast<__uint128_t>(__rdtscp(&aux)) * cv_factor_nsec; 50 return t >> 32; 51 } 52 53 54 static int64_t (*sSystemTime)(void) = __system_time_lfence; 55 static int64_t (*sSystemTimeNsecs)(void) = __system_time_nsecs_lfence; 56 57 58 // from kernel/arch/x86/arch_cpu.h 59 #define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction 60 61 62 extern "C" void 63 __x86_setup_system_time(uint64_t cv, uint64_t cv_nsec) 64 { 65 cv_factor = cv; 66 cv_factor_nsec = cv_nsec; 67 68 cpuid_info cpuInfo; 69 get_cpuid(&cpuInfo, 0x80000000, 0); 70 if (cpuInfo.eax_0.max_eax >= 0x80000001) { 71 get_cpuid(&cpuInfo, 0x80000001, 0); 72 if ((cpuInfo.regs.edx & IA32_FEATURE_AMD_EXT_RDTSCP)!= 0) { 73 sSystemTime = __system_time_rdtscp; 74 sSystemTimeNsecs = __system_time_nsecs_rdtscp; 75 } 76 } 77 } 78 79 80 extern "C" int64_t 81 system_time() 82 { 83 return sSystemTime(); 84 } 85 86 87 88 extern "C" int64_t 89 system_time_nsecs() 90 { 91 return sSystemTimeNsecs(); 92 } 93 94