From a6e9176bc547afeca88a9b5e4784f99d18b5ae66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Fri, 23 Sep 2022 18:55:15 +0200 Subject: [PATCH] x86_64: prefix rdtsc with lfence, or use rdtscp if available a strong monotonicity is a property of system_time(). Performance should be a bit impacted (around 10%). removed omit-frame-pointer hints as the compiler generates the same without. Change-Id: I920145d616604f32b38d9e134ce83f3e0e848bc7 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5690 Reviewed-by: Adrien Destugues Tested-by: Commit checker robot --- .../libroot/os/arch/x86_64/system_time.cpp | 79 ++++++++++++++++--- 1 file changed, 67 insertions(+), 12 deletions(-) diff --git a/src/system/libroot/os/arch/x86_64/system_time.cpp b/src/system/libroot/os/arch/x86_64/system_time.cpp index 5678d31323..aa02d85a98 100644 --- a/src/system/libroot/os/arch/x86_64/system_time.cpp +++ b/src/system/libroot/os/arch/x86_64/system_time.cpp @@ -4,6 +4,8 @@ */ +#include + #include #include @@ -13,26 +15,79 @@ static uint64_t cv_factor; static uint64_t cv_factor_nsec; -extern "C" void -__x86_setup_system_time(uint64_t cv, uint64_t cv_nsec) -{ - cv_factor = cv; - cv_factor_nsec = cv_nsec; -} - - -extern "C" [[gnu::optimize("omit-frame-pointer")]] int64_t -system_time() +static int64_t +__system_time_lfence() { + __builtin_ia32_lfence(); __uint128_t time = static_cast<__uint128_t>(__rdtsc()) * cv_factor; return time >> 64; } -extern "C" [[gnu::optimize("omit-frame-pointer")]] int64_t -system_time_nsecs() +static int64_t +__system_time_rdtscp() { + uint32_t aux; + __uint128_t time = static_cast<__uint128_t>(__rdtscp(&aux)) * cv_factor; + return time >> 64; +} + + +static int64_t +__system_time_nsecs_lfence() +{ + __builtin_ia32_lfence(); __uint128_t t = static_cast<__uint128_t>(__rdtsc()) * cv_factor_nsec; return t >> 32; } + +static int64_t +__system_time_nsecs_rdtscp() +{ + uint32_t aux; + __uint128_t t = static_cast<__uint128_t>(__rdtscp(&aux)) * cv_factor_nsec; + return t >> 32; +} + + +static int64_t (*sSystemTime)(void) = __system_time_lfence; +static int64_t (*sSystemTimeNsecs)(void) = __system_time_nsecs_lfence; + + +// from kernel/arch/x86/arch_cpu.h +#define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction + + +extern "C" void +__x86_setup_system_time(uint64_t cv, uint64_t cv_nsec) +{ + cv_factor = cv; + cv_factor_nsec = cv_nsec; + + cpuid_info cpuInfo; + get_cpuid(&cpuInfo, 0x80000000, 0); + if (cpuInfo.eax_0.max_eax >= 0x80000001) { + get_cpuid(&cpuInfo, 0x80000001, 0); + if ((cpuInfo.regs.edx & IA32_FEATURE_AMD_EXT_RDTSCP)!= 0) { + sSystemTime = __system_time_rdtscp; + sSystemTimeNsecs = __system_time_nsecs_rdtscp; + } + } +} + + +extern "C" int64_t +system_time() +{ + return sSystemTime(); +} + + + +extern "C" int64_t +system_time_nsecs() +{ + return sSystemTimeNsecs(); +} +