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 14static uint64_t cv_factor; 15static uint64_t cv_factor_nsec; 16 17 18static 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 27static 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 36static 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 45static 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 54static int64_t (*sSystemTime)(void) = __system_time_lfence; 55static 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 62extern "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 80extern "C" int64_t 81system_time() 82{ 83 return sSystemTime(); 84} 85 86 87 88extern "C" int64_t 89system_time_nsecs() 90{ 91 return sSystemTimeNsecs(); 92} 93 94