From: Jeffrey W. <nol...@gm...> - 2014-02-10 23:36:05
|
I've got some code that determines CPU capabilities for x86 processors. I'm interested in RDRAND and AESNI, and I use three functions to determine the capabilities: HasIntel(), HasAESNI() and HasRDRAND(). Debug configurations compiled with GCC and Clang work fine. Release configuration compiled with GCC and Clang work fine. However, I get *one* incorrect result when running under Valgrind. The incorrect result is from HasRDRAND(). Under Valgrind, the result is 0, which means RDRAND is not available. I think its related to "Valgrind shows different results for ubuntu and debian x86 cpuid implementations", http://sourceforge.net/mailarchive/message.php?msg_id=31873412. Can anyone confirm this is related to VEX virtual machine? I want to ensure I'm not seeing success in Debug and Release by dumb-luck (and possibly have an unforeseen problem to fix). Thanks in advance. ********** # Debian 7.3, x64, fully patched $ uname -a Linux debian-q500 3.2.0-4-amd64 #1 SMP Debian 3.2.51-1 x86_64 GNU/Linux # Built from sources a couple of weeks ago $ valgrind --version valgrind-3.9.0 ********** static void get_cpuid_info(CPUIDinfo *info, const unsigned int func, const unsigned int subfunc) { LogDebug("get_cpuid_info"); UNUSED(info); UNUSED(func); UNUSED(subfunc); __asm__ __volatile__ ( "cpuid" : "=a"(info->EAX), "=b"(info->EBX), "=c"(info->ECX), "=d"(info->EDX) : "a"(func), "c"(subfunc) ); } int HasIntel() { static int intel_cpu = 0; static once_flag flag; call_once(flag, []() { CPUIDinfo info; get_cpuid_info(&info,0,0); if(memcmp((char *)(&info.EBX), "Genu", 4) == 0 && memcmp((char *)(&info.EDX), "ineI", 4) == 0 && memcmp((char *)(&info.ECX), "ntel", 4) == 0) { intel_cpu = 1; } }); return intel_cpu; } int HasRDRAND() { static volatile int has_rdrand = 0; static once_flag flag; call_once(flag, []() { if(HasIntel()) { CPUIDinfo info; static const unsigned int RDRAND_CAP_BIT = (1 << 30); AC_ASSERT(0x40000000 == RDRAND_CAP_BIT); get_cpuid_info(&info,1,0); if ((info.ECX & RDRAND_CAP_BIT)==RDRAND_CAP_BIT) has_rdrand = 1; } }); return has_rdrand; } int HasAESNI() { static volatile int has_aesni = 0; static once_flag flag; call_once(flag, []() { if(HasIntel()) { CPUIDinfo info; static const unsigned int AESNI_CAP_BIT = (1 << 25); AC_ASSERT(0x2000000 == AESNI_CAP_BIT); get_cpuid_info(&info,1,0); if ((info.ECX & AESNI_CAP_BIT)==AESNI_CAP_BIT) has_aesni = 1; } }); return has_aesni; } |