Fix AMD RDRAND detection. Add VIA Padlock extension detection

pull/174/head
Jeffrey Walton 2016-05-19 08:32:51 -04:00
parent 2a163e0b14
commit c3d61ef78a
3 changed files with 98 additions and 14 deletions

55
cpu.cpp
View File

@ -174,6 +174,7 @@ static bool TrySSE2()
bool g_x86DetectionDone = false;
bool g_hasMMX = false, g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasSSE4 = false, g_hasAESNI = false, g_hasCLMUL = false, g_isP4 = false, g_hasRDRAND = false, g_hasRDSEED = false;
bool g_hasPadlockRNG = false, g_hasPadlockACE = false, g_hasPadlockACE2 = false, g_hasPadlockPHE = false, g_hasPadlockPMM = false;
word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
static inline bool IsIntel(const word32 output[4])
@ -186,10 +187,18 @@ static inline bool IsIntel(const word32 output[4])
static inline bool IsAMD(const word32 output[4])
{
// This is the "AuthenticAMD" string
// This is the "AuthenticAMD" string. Some early K5's can return "AMDisbetter!"
return (output[1] /*EBX*/ == 0x68747541) &&
(output[2] /*ECX*/ == 0x69746E65) &&
(output[3] /*EDX*/ == 0x444D4163);
(output[2] /*ECX*/ == 0x444D4163) &&
(output[3] /*EDX*/ == 0x69746E65);
}
static inline bool IsVIA(const word32 output[4])
{
// This is the "CentaurHauls" string. Some non-PadLock can return "VIA VIA VIA ".
return (output[1] /*EBX*/ == 0x746e6543) &&
(output[2] /*ECX*/ == 0x736c7561) &&
(output[3] /*EDX*/ == 0x48727561);
}
#if HAVE_GCC_CONSTRUCTOR1
@ -227,10 +236,11 @@ void DetectX86Features()
}
}
static const unsigned int RDRAND_FLAG = (1 << 30);
static const unsigned int RDSEED_FLAG = (1 << 18);
if (IsIntel(cpuid))
{
static const unsigned int RDRAND_FLAG = (1 << 30);
static const unsigned int RDSEED_FLAG = (1 << 18);
g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
g_hasRDRAND = !!(cpuid1[2] /*ECX*/ & RDRAND_FLAG);
@ -244,9 +254,42 @@ void DetectX86Features()
}
else if (IsAMD(cpuid))
{
static const unsigned int RDRAND_FLAG = (1 << 30);
CpuId(0x01, cpuid);
g_hasRDRAND = !!(cpuid[2] /*ECX*/ & RDRAND_FLAG);
CpuId(0x80000005, cpuid);
g_cacheLineSize = GETBYTE(cpuid[2], 0);
g_hasRDRAND = !!(cpuid[2] /*ECX*/ & RDRAND_FLAG);
}
else if (IsVIA(cpuid))
{
static const unsigned int RNG_FLAGS = (0x3 << 2);
static const unsigned int ACE_FLAGS = (0x3 << 6);
static const unsigned int ACE2_FLAGS = (0x3 << 8);
static const unsigned int PHE_FLAGS = (0x3 << 10);
static const unsigned int PMM_FLAGS = (0x3 << 12);
CpuId(0xC0000000, cpuid);
if (cpuid[0] < 0xC0000001)
{
// No extended features
g_hasPadlockRNG = false;
g_hasPadlockACE = false;
g_hasPadlockACE2 = false;
g_hasPadlockPHE = false;
g_hasPadlockPMM = false;
}
else
{
// Extended features available
CpuId(0xC0000001, cpuid);
g_hasPadlockRNG = !!(cpuid[3] /*EDX*/ & RNG_FLAGS);
g_hasPadlockACE = !!(cpuid[3] /*EDX*/ & ACE_FLAGS);
g_hasPadlockACE2 = !!(cpuid[3] /*EDX*/ & ACE2_FLAGS);
g_hasPadlockPHE = !!(cpuid[3] /*EDX*/ & PHE_FLAGS);
g_hasPadlockPMM = !!(cpuid[3] /*EDX*/ & PMM_FLAGS);
}
}
if (!g_cacheLineSize)

40
cpu.h
View File

@ -143,6 +143,11 @@ extern CRYPTOPP_DLL bool g_hasCLMUL;
extern CRYPTOPP_DLL bool g_isP4;
extern CRYPTOPP_DLL bool g_hasRDRAND;
extern CRYPTOPP_DLL bool g_hasRDSEED;
extern CRYPTOPP_DLL bool g_hasPadlockRNG;
extern CRYPTOPP_DLL bool g_hasPadlockACE;
extern CRYPTOPP_DLL bool g_hasPadlockACE2;
extern CRYPTOPP_DLL bool g_hasPadlockPHE;
extern CRYPTOPP_DLL bool g_hasPadlockPMM;
extern CRYPTOPP_DLL word32 g_cacheLineSize;
CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features();
@ -230,6 +235,41 @@ inline bool HasRDSEED()
return g_hasRDSEED;
}
inline bool HasPadlockRNG()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasPadlockRNG;
}
inline bool HasPadlockACE()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasPadlockACE;
}
inline bool HasPadlockACE2()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasPadlockACE2;
}
inline bool HasPadlockPHE()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasPadlockPHE;
}
inline bool HasPadlockPMM()
{
if (!g_x86DetectionDone)
DetectX86Features();
return g_hasPadlockPMM;
}
inline int GetCacheLineSize()
{
if (!g_x86DetectionDone)

View File

@ -299,6 +299,7 @@ bool TestSettings()
bool hasSSSE3 = HasSSSE3();
bool hasSSE4 = HasSSE4();
bool isP4 = IsP4();
bool hasPadlockRNG = HasPadlockRNG();
int cacheLineSize = GetCacheLineSize();
if ((isP4 && (!hasMMX || !hasSSE2)) || (hasSSE2 && !hasMMX) || (cacheLineSize < 16 || cacheLineSize > 256 || !IsPowerOf2(cacheLineSize)))
@ -309,7 +310,7 @@ bool TestSettings()
else
cout << "passed: ";
cout << "hasMMX == " << hasMMX << ", hasISSE == " << hasISSE << ", hasSSE2 == " << hasSSE2 << ", hasSSSE3 == " << hasSSE4 << ", hasSSE4 == " << hasSSSE3 << ", hasAESNI == " << HasAESNI() << ", hasRDRAND == " << HasRDRAND() << ", hasRDSEED == " << HasRDSEED() << ", hasCLMUL == " << HasCLMUL() << ", isP4 == " << isP4 << ", cacheLineSize == " << cacheLineSize;
cout << "hasMMX == " << hasMMX << ", hasISSE == " << hasISSE << ", hasSSE2 == " << hasSSE2 << ", hasSSSE3 == " << hasSSE4 << ", hasSSE4 == " << hasSSSE3 << ", hasAESNI == " << HasAESNI() << ", hasRDRAND == " << HasRDRAND() << ", hasRDSEED == " << HasRDSEED() << ", hasCLMUL == " << HasCLMUL() << ", isP4 == " << isP4 << ", hasPadlockRNG == " << hasPadlockRNG << ", cacheLineSize == " << cacheLineSize;
cout << ", AESNI_INTRINSICS == " << CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE << endl;
#elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64)