Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Correctly check for AVX support in x64CPUDetect
It's not enough to check for the CPUID bit to know if AVX is supported since
AVX requires OS support (new set of registers == more registers to be saved
when context switching). If the OS does not support, the cpuid bit will still
be set but using YMM registers will cause an illegal exception fault.
  • Loading branch information
delroth committed Aug 19, 2013
1 parent 77a5af3 commit 377202b
Showing 1 changed file with 18 additions and 1 deletion.
19 changes: 18 additions & 1 deletion Source/Core/Common/Src/x64CPUDetect.cpp
Expand Up @@ -72,6 +72,14 @@ static void __cpuid(int info[4], int x)
#endif
}

#define _XCR_XFEATURE_ENABLED_MASK 0
static unsigned long long _xgetbv(unsigned int index)
{
unsigned int eax, edx;
__asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
return ((unsigned long long)edx << 32) | eax;
}

#endif

#include "Common.h"
Expand Down Expand Up @@ -149,8 +157,17 @@ void CPUInfo::Detect()
if ((cpu_id[2] >> 9) & 1) bSSSE3 = true;
if ((cpu_id[2] >> 19) & 1) bSSE4_1 = true;
if ((cpu_id[2] >> 20) & 1) bSSE4_2 = true;
if ((cpu_id[2] >> 28) & 1) bAVX = true;
if ((cpu_id[2] >> 25) & 1) bAES = true;

// AVX support requires 3 separate checks:
// - Is the AVX bit set in CPUID?
// - Is the XSAVE bit set in CPUID?
// - XGETBV result has the XCR bit set.
if (((cpu_id[2] >> 28) & 1) && ((cpu_id[2] >> 27) & 1))
{
if (_xgetbv(_XCR_XFEATURE_ENABLED_MASK) & 0x6)
bAVX = true;
}
}
if (max_ex_fn >= 0x80000004) {
// Extract brand string
Expand Down

0 comments on commit 377202b

Please sign in to comment.