2017-01-27 12:05:45 +00:00
|
|
|
// cpu.cpp - originally written and placed in the public domain by Wei Dai
|
2015-11-05 06:59:46 +00:00
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#ifndef EXCEPTION_EXECUTE_HANDLER
|
|
|
|
# define EXCEPTION_EXECUTE_HANDLER 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef CRYPTOPP_IMPORTS
|
|
|
|
|
|
|
|
#include "cpu.h"
|
|
|
|
#include "misc.h"
|
2017-08-17 06:15:42 +00:00
|
|
|
#include "stdcpp.h"
|
|
|
|
|
2017-09-11 07:05:04 +00:00
|
|
|
#ifdef _AIX
|
|
|
|
# include <sys/systemcfg.h>
|
|
|
|
#endif
|
|
|
|
|
2017-09-17 06:39:41 +00:00
|
|
|
#ifdef __linux__
|
|
|
|
# include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2017-10-13 00:14:21 +00:00
|
|
|
// Capability queries, requires Glibc 2.16, http://lwn.net/Articles/519085/
|
2017-09-17 04:41:48 +00:00
|
|
|
// CRYPTOPP_GLIBC_VERSION not used because config.h is missing <feature.h>
|
|
|
|
#if (((__GLIBC__ * 100) + __GLIBC_MINOR__) >= 216)
|
|
|
|
# define CRYPTOPP_GETAUXV_AVAILABLE 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if CRYPTOPP_GETAUXV_AVAILABLE
|
2017-09-13 11:16:41 +00:00
|
|
|
# include <sys/auxv.h>
|
2017-09-17 04:41:48 +00:00
|
|
|
#else
|
2018-03-04 14:17:03 +00:00
|
|
|
#ifndef AT_HWCAP
|
2018-03-21 20:19:43 +00:00
|
|
|
# define AT_HWCAP 16
|
2018-03-04 14:17:03 +00:00
|
|
|
#endif
|
|
|
|
#ifndef AT_HWCAP2
|
2018-03-21 20:19:43 +00:00
|
|
|
# define AT_HWCAP2 26
|
2018-03-04 14:17:03 +00:00
|
|
|
#endif
|
2017-09-17 04:41:48 +00:00
|
|
|
unsigned long int getauxval(unsigned long int) { return 0; }
|
2017-09-13 11:16:41 +00:00
|
|
|
#endif
|
|
|
|
|
2018-07-14 12:20:16 +00:00
|
|
|
#if defined(__APPLE__)
|
2017-09-13 11:16:41 +00:00
|
|
|
# include <sys/utsname.h>
|
2015-11-05 06:59:46 +00:00
|
|
|
#endif
|
|
|
|
|
2018-07-14 12:20:16 +00:00
|
|
|
// The cpu-features header and source file are located in
|
|
|
|
// "$ANDROID_NDK_ROOT/sources/android/cpufeatures".
|
|
|
|
// setenv-android.sh will copy the header and source file
|
|
|
|
// into PWD and the makefile will build it in place.
|
2017-09-08 19:43:06 +00:00
|
|
|
#if defined(__ANDROID__)
|
2017-09-13 11:16:41 +00:00
|
|
|
# include "cpu-features.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
|
|
|
|
# include <signal.h>
|
|
|
|
# include <setjmp.h>
|
2017-09-08 19:43:06 +00:00
|
|
|
#endif
|
|
|
|
|
2018-08-19 14:19:29 +00:00
|
|
|
// Visual Studio 2008 and below is missing _xgetbv. See x64dll.asm for the body.
|
2018-12-22 00:54:24 +00:00
|
|
|
#if defined(_MSC_VER) && _MSC_VER <= 1500 && defined(_M_X64)
|
2019-05-21 23:44:48 +00:00
|
|
|
extern "C" unsigned long long __fastcall XGETBV64(unsigned int);
|
2018-08-19 14:19:29 +00:00
|
|
|
#endif
|
|
|
|
|
2018-07-14 12:20:16 +00:00
|
|
|
ANONYMOUS_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
#if defined(__APPLE__)
|
|
|
|
enum {PowerMac=1, Mac, iPhone, iPod, iPad, AppleTV, AppleWatch};
|
|
|
|
void GetAppleMachineInfo(unsigned int& device, unsigned int& version)
|
|
|
|
{
|
|
|
|
device = version = 0;
|
|
|
|
|
|
|
|
struct utsname systemInfo;
|
|
|
|
systemInfo.machine[0] = '\0';
|
|
|
|
uname(&systemInfo);
|
|
|
|
|
|
|
|
std::string machine(systemInfo.machine);
|
2018-07-14 12:40:06 +00:00
|
|
|
if (machine.find("PowerMac") != std::string::npos ||
|
|
|
|
machine.find("Power Macintosh") != std::string::npos)
|
2018-07-14 12:20:16 +00:00
|
|
|
device = PowerMac;
|
2018-07-14 12:40:06 +00:00
|
|
|
else if (machine.find("Mac") != std::string::npos ||
|
|
|
|
machine.find("Macintosh") != std::string::npos)
|
2018-07-14 12:20:16 +00:00
|
|
|
device = Mac;
|
2018-07-14 12:40:06 +00:00
|
|
|
else if (machine.find("iPhone") != std::string::npos)
|
2018-07-14 12:20:16 +00:00
|
|
|
device = iPhone;
|
2018-07-14 12:40:06 +00:00
|
|
|
else if (machine.find("iPod") != std::string::npos)
|
2018-07-14 12:20:16 +00:00
|
|
|
device = iPod;
|
2018-07-14 12:40:06 +00:00
|
|
|
else if (machine.find("iPad") != std::string::npos)
|
2018-07-14 12:20:16 +00:00
|
|
|
device = iPad;
|
2018-07-14 12:40:06 +00:00
|
|
|
else if (machine.find("AppleTV") != std::string::npos)
|
2018-07-14 12:20:16 +00:00
|
|
|
device = AppleTV;
|
2018-07-14 12:40:06 +00:00
|
|
|
else if (machine.find("AppleWatch") != std::string::npos)
|
2018-07-14 12:20:16 +00:00
|
|
|
device = AppleWatch;
|
|
|
|
|
|
|
|
std::string::size_type pos = machine.find_first_of("0123456789");
|
|
|
|
if (pos != std::string::npos)
|
|
|
|
version = std::atoi(machine.substr(pos).c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
|
|
|
|
bool IsAppleMachineARMv8(unsigned int device, unsigned int version)
|
|
|
|
{
|
|
|
|
if ((device == iPhone && version >= 6) ||
|
|
|
|
(device == iPad && version >= 4))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsAppleMachineARMv84(unsigned int device, unsigned int version)
|
|
|
|
{
|
2019-05-17 19:18:17 +00:00
|
|
|
CRYPTOPP_UNUSED(device);
|
|
|
|
CRYPTOPP_UNUSED(version);
|
2018-07-14 12:20:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif // __APPLE__
|
|
|
|
|
|
|
|
ANONYMOUS_NAMESPACE_END
|
|
|
|
|
2015-11-05 06:59:46 +00:00
|
|
|
NAMESPACE_BEGIN(CryptoPP)
|
|
|
|
|
2016-05-16 22:47:43 +00:00
|
|
|
#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
|
|
|
|
extern "C" {
|
|
|
|
typedef void (*SigHandler)(int);
|
2018-03-31 17:10:11 +00:00
|
|
|
}
|
2017-11-17 00:37:29 +00:00
|
|
|
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
static jmp_buf s_jmpNoCPUID;
|
2018-01-25 01:04:16 +00:00
|
|
|
static void SigIllHandlerCPUID(int unused)
|
2017-11-17 00:37:29 +00:00
|
|
|
{
|
2018-01-25 01:04:16 +00:00
|
|
|
CRYPTOPP_UNUSED(unused);
|
2017-11-17 00:37:29 +00:00
|
|
|
longjmp(s_jmpNoCPUID, 1);
|
|
|
|
}
|
|
|
|
}
|
2016-05-16 22:47:43 +00:00
|
|
|
#endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
|
|
|
|
|
2017-08-18 07:03:42 +00:00
|
|
|
// *************************** IA-32 CPUs ***************************
|
2017-08-17 16:33:43 +00:00
|
|
|
|
2017-11-16 20:11:51 +00:00
|
|
|
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
|
|
|
|
|
|
|
extern bool CPU_ProbeSSE2();
|
2015-11-05 06:59:46 +00:00
|
|
|
|
2018-03-28 00:38:26 +00:00
|
|
|
#if _MSC_VER >= 1600
|
2015-11-05 06:59:46 +00:00
|
|
|
|
2017-08-17 16:33:43 +00:00
|
|
|
inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
|
2015-11-05 06:59:46 +00:00
|
|
|
{
|
2017-08-17 16:33:43 +00:00
|
|
|
__cpuidex((int *)output, func, subfunc);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
|
|
|
|
|
|
|
|
inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
|
|
|
|
{
|
|
|
|
if (subfunc != 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
__cpuid((int *)output, func);
|
2015-11-05 06:59:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2017-09-16 22:03:24 +00:00
|
|
|
// Borland/Embarcadero and Issue 498
|
2017-09-15 16:42:50 +00:00
|
|
|
// cpu.cpp (131): E2211 Inline assembly not allowed in inline and template functions
|
|
|
|
bool CpuId(word32 func, word32 subfunc, word32 output[4])
|
2015-11-05 06:59:46 +00:00
|
|
|
{
|
2017-10-13 00:14:21 +00:00
|
|
|
#if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) || defined(__BORLANDC__)
|
2015-11-05 06:59:46 +00:00
|
|
|
__try
|
|
|
|
{
|
2017-09-16 22:03:24 +00:00
|
|
|
// Borland/Embarcadero and Issue 500
|
|
|
|
// Local variables for cpuid output
|
|
|
|
word32 a, b, c, d;
|
2015-11-05 06:59:46 +00:00
|
|
|
__asm
|
|
|
|
{
|
2017-08-17 16:33:43 +00:00
|
|
|
mov eax, func
|
|
|
|
mov ecx, subfunc
|
2015-11-05 06:59:46 +00:00
|
|
|
cpuid
|
2017-09-16 22:03:24 +00:00
|
|
|
mov [a], eax
|
|
|
|
mov [b], ebx
|
|
|
|
mov [c], ecx
|
|
|
|
mov [d], edx
|
2015-11-05 06:59:46 +00:00
|
|
|
}
|
2017-09-16 22:03:24 +00:00
|
|
|
output[0] = a;
|
|
|
|
output[1] = b;
|
|
|
|
output[2] = c;
|
|
|
|
output[3] = d;
|
2015-11-05 06:59:46 +00:00
|
|
|
}
|
|
|
|
// GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION
|
|
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-12 16:55:57 +00:00
|
|
|
// func = 0 returns the highest basic function understood in EAX. If the CPU does
|
|
|
|
// not return non-0, then it is mostly useless. The code below converts basic
|
|
|
|
// function value to a true/false return value.
|
2017-09-16 04:19:14 +00:00
|
|
|
if(func == 0)
|
2018-01-25 01:04:16 +00:00
|
|
|
return output[0] != 0;
|
2015-11-05 06:59:46 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
#else
|
2015-11-18 20:32:28 +00:00
|
|
|
// longjmp and clobber warnings. Volatile is required.
|
2016-05-19 08:45:35 +00:00
|
|
|
// http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
|
2015-11-18 20:32:28 +00:00
|
|
|
volatile bool result = true;
|
|
|
|
|
2016-05-30 07:08:53 +00:00
|
|
|
volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
|
2015-11-05 06:59:46 +00:00
|
|
|
if (oldHandler == SIG_ERR)
|
2016-06-01 05:27:53 +00:00
|
|
|
return false;
|
2015-11-05 06:59:46 +00:00
|
|
|
|
2016-08-01 19:56:43 +00:00
|
|
|
# ifndef __MINGW32__
|
2016-05-30 07:08:53 +00:00
|
|
|
volatile sigset_t oldMask;
|
2018-01-25 01:04:16 +00:00
|
|
|
if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask) != 0)
|
2016-06-01 05:27:53 +00:00
|
|
|
return false;
|
2016-08-01 19:56:43 +00:00
|
|
|
# endif
|
2016-05-30 07:08:53 +00:00
|
|
|
|
2015-11-05 06:59:46 +00:00
|
|
|
if (setjmp(s_jmpNoCPUID))
|
|
|
|
result = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
asm volatile
|
|
|
|
(
|
|
|
|
// save ebx in case -fPIC is being used
|
|
|
|
// TODO: this might need an early clobber on EDI.
|
|
|
|
# if CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
|
|
|
|
"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
|
|
|
|
# else
|
|
|
|
"push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
|
|
|
|
# endif
|
|
|
|
: "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
|
2017-08-17 16:33:43 +00:00
|
|
|
: "a" (func), "c" (subfunc)
|
2016-11-13 16:14:03 +00:00
|
|
|
: "cc"
|
2015-11-05 06:59:46 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-08-01 19:56:43 +00:00
|
|
|
# ifndef __MINGW32__
|
2017-03-01 11:10:06 +00:00
|
|
|
sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
|
2016-08-01 19:56:43 +00:00
|
|
|
# endif
|
|
|
|
|
2015-11-05 06:59:46 +00:00
|
|
|
signal(SIGILL, oldHandler);
|
|
|
|
return result;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2016-07-13 03:05:00 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_x86DetectionDone = false;
|
2018-03-28 03:19:26 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSSE2 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSSSE3 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSSE41 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSSE42 = false;
|
2018-06-18 22:33:17 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasAVX = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasAVX2 = false;
|
2018-03-28 03:19:26 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasAESNI = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasCLMUL = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasADX = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSHA = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasRDRAND = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasRDSEED = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_isP4 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasPadlockRNG = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasPadlockACE = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasPadlockACE2 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasPadlockPHE = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasPadlockPMM = false;
|
2016-07-13 03:05:00 +00:00
|
|
|
word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
|
2015-11-05 06:59:46 +00:00
|
|
|
|
2015-11-18 20:32:28 +00:00
|
|
|
static inline bool IsIntel(const word32 output[4])
|
|
|
|
{
|
|
|
|
// This is the "GenuineIntel" string
|
|
|
|
return (output[1] /*EBX*/ == 0x756e6547) &&
|
|
|
|
(output[2] /*ECX*/ == 0x6c65746e) &&
|
|
|
|
(output[3] /*EDX*/ == 0x49656e69);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool IsAMD(const word32 output[4])
|
|
|
|
{
|
2019-05-08 22:51:12 +00:00
|
|
|
// This is the "AuthenticAMD" string.
|
|
|
|
return ((output[1] /*EBX*/ == 0x68747541) &&
|
2016-05-19 12:32:51 +00:00
|
|
|
(output[2] /*ECX*/ == 0x444D4163) &&
|
2019-05-08 22:51:12 +00:00
|
|
|
(output[3] /*EDX*/ == 0x69746E65)) ||
|
|
|
|
// Some early K5's can return "AMDisbetter!"
|
|
|
|
((output[1] /*EBX*/ == 0x69444d41) &&
|
|
|
|
(output[2] /*ECX*/ == 0x74656273) &&
|
|
|
|
(output[3] /*EDX*/ == 0x21726574));
|
2016-05-19 12:32:51 +00:00
|
|
|
}
|
|
|
|
|
2018-12-20 22:33:16 +00:00
|
|
|
static inline bool IsHygon(const word32 output[4])
|
|
|
|
{
|
|
|
|
// This is the "HygonGenuine" string.
|
|
|
|
return (output[1] /*EBX*/ == 0x6f677948) &&
|
|
|
|
(output[2] /*ECX*/ == 0x656e6975) &&
|
|
|
|
(output[3] /*EDX*/ == 0x6e65476e);
|
|
|
|
}
|
|
|
|
|
2016-05-19 12:32:51 +00:00
|
|
|
static inline bool IsVIA(const word32 output[4])
|
|
|
|
{
|
2019-05-08 22:29:33 +00:00
|
|
|
// This is the "CentaurHauls" string.
|
|
|
|
return ((output[1] /*EBX*/ == 0x746e6543) &&
|
2016-05-19 12:32:51 +00:00
|
|
|
(output[2] /*ECX*/ == 0x736c7561) &&
|
2019-05-08 22:29:33 +00:00
|
|
|
(output[3] /*EDX*/ == 0x48727561)) ||
|
|
|
|
// Some non-PadLock's return "VIA VIA VIA "
|
|
|
|
((output[1] /*EBX*/ == 0x32414956) &&
|
|
|
|
(output[2] /*ECX*/ == 0x32414956) &&
|
|
|
|
(output[3] /*EDX*/ == 0x32414956));
|
2015-11-18 20:32:28 +00:00
|
|
|
}
|
|
|
|
|
2015-11-05 06:59:46 +00:00
|
|
|
void DetectX86Features()
|
|
|
|
{
|
2017-03-18 01:29:15 +00:00
|
|
|
// Coverity finding CID 171239...
|
2017-08-11 21:13:15 +00:00
|
|
|
word32 cpuid0[4]={0}, cpuid1[4]={0}, cpuid2[4]={0};
|
2017-08-17 16:33:43 +00:00
|
|
|
if (!CpuId(0, 0, cpuid0))
|
2015-11-05 06:59:46 +00:00
|
|
|
return;
|
2017-08-17 16:33:43 +00:00
|
|
|
if (!CpuId(1, 0, cpuid1))
|
2015-11-05 06:59:46 +00:00
|
|
|
return;
|
|
|
|
|
2017-10-13 00:14:21 +00:00
|
|
|
// cpuid1[2] & (1 << 27) is XSAVE/XRESTORE and signals OS support for SSE; use it to avoid probes.
|
|
|
|
// See http://github.com/weidai11/cryptopp/issues/511 and http://stackoverflow.com/a/22521619/608639
|
2017-08-11 21:13:15 +00:00
|
|
|
if ((cpuid1[3] & (1 << 26)) != 0)
|
2018-01-25 01:04:16 +00:00
|
|
|
g_hasSSE2 = ((cpuid1[2] & (1 << 27)) != 0) || CPU_ProbeSSE2();
|
2017-10-13 00:14:21 +00:00
|
|
|
|
2018-01-25 01:04:16 +00:00
|
|
|
g_hasSSSE3 = g_hasSSE2 && ((cpuid1[2] & (1<< 9)) != 0);
|
|
|
|
g_hasSSE41 = g_hasSSE2 && ((cpuid1[2] & (1<<19)) != 0);
|
|
|
|
g_hasSSE42 = g_hasSSE2 && ((cpuid1[2] & (1<<20)) != 0);
|
|
|
|
g_hasAESNI = g_hasSSE2 && ((cpuid1[2] & (1<<25)) != 0);
|
|
|
|
g_hasCLMUL = g_hasSSE2 && ((cpuid1[2] & (1<< 1)) != 0);
|
2015-11-05 06:59:46 +00:00
|
|
|
|
2018-06-18 22:33:17 +00:00
|
|
|
// AVX is similar to SSE, but check both bits 27 (SSE) and 28 (AVX).
|
|
|
|
// https://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
|
|
|
|
CRYPTOPP_CONSTANT(YMM_FLAG = (3 << 1))
|
|
|
|
CRYPTOPP_CONSTANT(AVX_FLAG = (3 << 27))
|
|
|
|
if ((cpuid1[2] & AVX_FLAG) == AVX_FLAG)
|
|
|
|
{
|
2018-12-28 17:19:13 +00:00
|
|
|
|
|
|
|
// Unable to perform the necessary tests
|
|
|
|
#if defined(CRYPTOPP_DISABLE_ASM)
|
|
|
|
g_hasAVX = false;
|
|
|
|
|
2018-08-19 14:19:29 +00:00
|
|
|
// GCC 4.1/Binutils 2.17 cannot consume xgetbv
|
2018-12-28 17:19:13 +00:00
|
|
|
#elif defined(__GNUC__) || (__SUNPRO_CC >= 0x5100) || defined(__BORLANDC__)
|
2018-06-18 22:33:17 +00:00
|
|
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71659 and
|
|
|
|
// http://www.agner.org/optimize/vectorclass/read.php?i=65
|
|
|
|
word32 a=0, d=0;
|
|
|
|
__asm __volatile
|
|
|
|
(
|
|
|
|
// "xgetbv" : "=a"(a), "=d"(d) : "c"(0) :
|
|
|
|
".byte 0x0f, 0x01, 0xd0" "\n\t"
|
2018-12-29 05:09:59 +00:00
|
|
|
: "=a"(a), "=d"(d) : "c"(0) : "cc"
|
2018-06-18 22:33:17 +00:00
|
|
|
);
|
|
|
|
word64 xcr0 = a | static_cast<word64>(d) << 32;
|
|
|
|
g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
|
2018-08-19 14:19:29 +00:00
|
|
|
|
2019-04-28 21:27:09 +00:00
|
|
|
// Visual Studio 2010 and below lack xgetbv
|
|
|
|
#elif defined(_MSC_VER) && _MSC_VER <= 1600 && defined(_M_IX86)
|
2018-08-19 14:19:29 +00:00
|
|
|
word32 a=0, d=0;
|
|
|
|
__asm {
|
|
|
|
push eax
|
|
|
|
push edx
|
|
|
|
push ecx
|
|
|
|
mov ecx, 0
|
|
|
|
_emit 0x0f
|
|
|
|
_emit 0x01
|
|
|
|
_emit 0xd0
|
|
|
|
mov a, eax
|
|
|
|
mov d, edx
|
|
|
|
pop ecx
|
|
|
|
pop edx
|
|
|
|
pop eax
|
|
|
|
}
|
|
|
|
word64 xcr0 = a | static_cast<word64>(d) << 32;
|
|
|
|
g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
|
|
|
|
|
|
|
|
// Visual Studio 2008 and below lack xgetbv
|
2018-12-22 00:54:24 +00:00
|
|
|
#elif defined(_MSC_VER) && _MSC_VER <= 1500 && defined(_M_X64)
|
2019-05-21 23:44:48 +00:00
|
|
|
word64 xcr0 = XGETBV64(0);
|
2018-08-19 14:19:29 +00:00
|
|
|
g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
|
2018-12-28 17:19:13 +00:00
|
|
|
|
|
|
|
// Downlevel SunCC
|
|
|
|
#elif defined(__SUNPRO_CC)
|
2018-11-08 20:08:30 +00:00
|
|
|
g_hasAVX = false;
|
2018-12-28 17:19:13 +00:00
|
|
|
|
|
|
|
// _xgetbv is available
|
2018-06-18 22:33:17 +00:00
|
|
|
#else
|
|
|
|
word64 xcr0 = _xgetbv(0);
|
|
|
|
g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-08-11 21:13:15 +00:00
|
|
|
if (IsIntel(cpuid0))
|
2015-11-05 06:59:46 +00:00
|
|
|
{
|
2017-09-16 05:21:14 +00:00
|
|
|
CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30))
|
|
|
|
CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18))
|
2017-11-16 07:38:53 +00:00
|
|
|
CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19))
|
2017-09-16 05:21:14 +00:00
|
|
|
CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29))
|
2018-06-18 22:33:17 +00:00
|
|
|
CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5))
|
2016-05-19 12:32:51 +00:00
|
|
|
|
2017-08-11 21:13:15 +00:00
|
|
|
g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
|
|
|
|
g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
|
2018-01-25 01:04:16 +00:00
|
|
|
g_hasRDRAND = (cpuid1[2] /*ECX*/ & RDRAND_FLAG) != 0;
|
2015-11-18 20:32:28 +00:00
|
|
|
|
2018-01-11 22:59:24 +00:00
|
|
|
if (cpuid0[0] /*EAX*/ >= 7)
|
2015-11-18 20:32:28 +00:00
|
|
|
{
|
2017-08-17 16:33:43 +00:00
|
|
|
if (CpuId(7, 0, cpuid2))
|
2016-10-27 02:35:24 +00:00
|
|
|
{
|
2018-01-25 01:04:16 +00:00
|
|
|
g_hasRDSEED = (cpuid2[1] /*EBX*/ & RDSEED_FLAG) != 0;
|
|
|
|
g_hasADX = (cpuid2[1] /*EBX*/ & ADX_FLAG) != 0;
|
|
|
|
g_hasSHA = (cpuid2[1] /*EBX*/ & SHA_FLAG) != 0;
|
2018-06-18 22:33:17 +00:00
|
|
|
g_hasAVX2 = (cpuid2[1] /*EBX*/ & AVX2_FLAG) != 0;
|
2016-10-27 02:35:24 +00:00
|
|
|
}
|
2015-11-18 20:32:28 +00:00
|
|
|
}
|
2015-11-05 06:59:46 +00:00
|
|
|
}
|
2018-12-20 22:33:16 +00:00
|
|
|
else if (IsAMD(cpuid0) || IsHygon(cpuid0))
|
2015-11-05 06:59:46 +00:00
|
|
|
{
|
2017-09-16 05:21:14 +00:00
|
|
|
CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30))
|
|
|
|
CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18))
|
2017-11-16 07:38:53 +00:00
|
|
|
CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19))
|
2017-09-16 05:21:14 +00:00
|
|
|
CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29))
|
2018-06-18 22:33:17 +00:00
|
|
|
CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5))
|
2016-05-19 12:32:51 +00:00
|
|
|
|
2017-08-17 16:33:43 +00:00
|
|
|
CpuId(0x80000005, 0, cpuid2);
|
2017-08-11 21:13:15 +00:00
|
|
|
g_cacheLineSize = GETBYTE(cpuid2[2], 0);
|
2018-01-25 01:04:16 +00:00
|
|
|
g_hasRDRAND = (cpuid1[2] /*ECX*/ & RDRAND_FLAG) != 0;
|
2016-05-19 12:32:51 +00:00
|
|
|
|
2018-01-11 22:59:24 +00:00
|
|
|
if (cpuid0[0] /*EAX*/ >= 7)
|
2017-05-21 15:38:56 +00:00
|
|
|
{
|
2017-08-17 16:33:43 +00:00
|
|
|
if (CpuId(7, 0, cpuid2))
|
2017-05-21 15:38:56 +00:00
|
|
|
{
|
2018-01-25 01:04:16 +00:00
|
|
|
g_hasRDSEED = (cpuid2[1] /*EBX*/ & RDSEED_FLAG) != 0;
|
|
|
|
g_hasADX = (cpuid2[1] /*EBX*/ & ADX_FLAG) != 0;
|
|
|
|
g_hasSHA = (cpuid2[1] /*EBX*/ & SHA_FLAG) != 0;
|
2018-06-18 22:33:17 +00:00
|
|
|
g_hasAVX2 = (cpuid2[1] /*EBX*/ & AVX2_FLAG) != 0;
|
2017-05-21 15:38:56 +00:00
|
|
|
}
|
|
|
|
}
|
2016-05-19 12:32:51 +00:00
|
|
|
}
|
2017-08-11 21:13:15 +00:00
|
|
|
else if (IsVIA(cpuid0))
|
2016-05-19 12:32:51 +00:00
|
|
|
{
|
2019-05-08 22:29:33 +00:00
|
|
|
// Two bits: available and enabled
|
2017-09-16 05:21:14 +00:00
|
|
|
CRYPTOPP_CONSTANT( RNG_FLAGS = (0x3 << 2))
|
|
|
|
CRYPTOPP_CONSTANT( ACE_FLAGS = (0x3 << 6))
|
|
|
|
CRYPTOPP_CONSTANT(ACE2_FLAGS = (0x3 << 8))
|
|
|
|
CRYPTOPP_CONSTANT( PHE_FLAGS = (0x3 << 10))
|
|
|
|
CRYPTOPP_CONSTANT( PMM_FLAGS = (0x3 << 12))
|
2017-08-11 21:13:15 +00:00
|
|
|
|
2017-08-17 16:33:43 +00:00
|
|
|
CpuId(0xC0000000, 0, cpuid2);
|
2019-05-08 22:29:33 +00:00
|
|
|
word32 extendedFeatures = cpuid2[0];
|
|
|
|
|
|
|
|
if (extendedFeatures >= 0xC0000001)
|
2016-05-19 12:32:51 +00:00
|
|
|
{
|
2017-08-17 16:33:43 +00:00
|
|
|
CpuId(0xC0000001, 0, cpuid2);
|
2018-06-18 22:33:17 +00:00
|
|
|
g_hasPadlockRNG = (cpuid2[3] /*EDX*/ & RNG_FLAGS) == RNG_FLAGS;
|
|
|
|
g_hasPadlockACE = (cpuid2[3] /*EDX*/ & ACE_FLAGS) == ACE_FLAGS;
|
|
|
|
g_hasPadlockACE2 = (cpuid2[3] /*EDX*/ & ACE2_FLAGS) == ACE2_FLAGS;
|
|
|
|
g_hasPadlockPHE = (cpuid2[3] /*EDX*/ & PHE_FLAGS) == PHE_FLAGS;
|
|
|
|
g_hasPadlockPMM = (cpuid2[3] /*EDX*/ & PMM_FLAGS) == PMM_FLAGS;
|
2016-05-19 12:32:51 +00:00
|
|
|
}
|
2019-05-08 22:29:33 +00:00
|
|
|
|
|
|
|
if (extendedFeatures >= 0xC0000005)
|
|
|
|
{
|
|
|
|
CpuId(0xC0000005, 0, cpuid2);
|
|
|
|
g_cacheLineSize = GETBYTE(cpuid2[2] /*ECX*/, 0);
|
|
|
|
}
|
2019-05-08 23:54:05 +00:00
|
|
|
}
|
|
|
|
|
2019-05-08 23:46:23 +00:00
|
|
|
#if defined(_SC_LEVEL1_DCACHE_LINESIZE)
|
2019-05-08 23:54:05 +00:00
|
|
|
// Glibc does not implement on some platforms. The runtime returns 0 instead of error.
|
|
|
|
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
|
|
|
|
int cacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
|
2019-05-09 01:20:49 +00:00
|
|
|
if (g_cacheLineSize == 0 && cacheLineSize > 0)
|
2019-05-08 23:54:05 +00:00
|
|
|
g_cacheLineSize = cacheLineSize;
|
2019-05-08 23:46:23 +00:00
|
|
|
#endif
|
2015-11-05 06:59:46 +00:00
|
|
|
|
2018-03-21 20:19:43 +00:00
|
|
|
if (g_cacheLineSize == 0)
|
2015-11-05 06:59:46 +00:00
|
|
|
g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
|
|
|
|
|
2017-11-17 00:37:29 +00:00
|
|
|
*const_cast<volatile bool*>(&g_x86DetectionDone) = true;
|
2015-11-05 06:59:46 +00:00
|
|
|
}
|
|
|
|
|
2017-09-11 07:05:04 +00:00
|
|
|
// *************************** ARM-32, Aarch32 and Aarch64 ***************************
|
2017-08-17 16:33:43 +00:00
|
|
|
|
2018-12-09 15:24:55 +00:00
|
|
|
#elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8)
|
2016-05-15 06:30:08 +00:00
|
|
|
|
2016-07-13 03:05:00 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_ArmDetectionDone = false;
|
2018-07-08 06:49:21 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasARMv7 = false;
|
2018-03-28 03:19:26 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasNEON = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasCRC32 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasAES = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSHA1 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSHA2 = false;
|
2018-07-14 12:20:16 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSHA3 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSM3 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSM4 = false;
|
2016-07-13 03:05:00 +00:00
|
|
|
word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
|
2016-05-15 06:30:08 +00:00
|
|
|
|
2017-08-17 16:33:43 +00:00
|
|
|
// ARM does not have an unprivliged equivalent to CPUID on IA-32. We have to jump through some
|
|
|
|
// hoops to detect features on a wide array of platforms. Our strategy is two part. First,
|
|
|
|
// attempt to *Query* the OS for a feature, like using getauxval on Linux. If that fails,
|
|
|
|
// then *Probe* the cpu executing an instruction and an observe a SIGILL if unsupported.
|
|
|
|
// The probes are in source files where compilation options like -march=armv8-a+crc make
|
|
|
|
// intrinsics available. They are expensive when compared to a standard OS feature query.
|
2019-05-08 22:33:55 +00:00
|
|
|
// Always perform the feature query first. For Linux see
|
2017-08-17 16:33:43 +00:00
|
|
|
// http://sourceware.org/ml/libc-help/2017-08/msg00012.html
|
|
|
|
// Avoid probes on Apple platforms because Apple's signal handling for SIGILLs appears broken.
|
|
|
|
// We are trying to figure out a way to feature test without probes. Also see
|
|
|
|
// http://stackoverflow.com/a/11197770/608639 and
|
|
|
|
// http://gist.github.com/erkanyildiz/390a480f27e86f8cd6ba
|
|
|
|
|
2018-07-08 06:49:21 +00:00
|
|
|
extern bool CPU_ProbeARMv7();
|
2017-08-17 16:33:43 +00:00
|
|
|
extern bool CPU_ProbeNEON();
|
|
|
|
extern bool CPU_ProbeCRC32();
|
|
|
|
extern bool CPU_ProbeAES();
|
|
|
|
extern bool CPU_ProbeSHA1();
|
2019-05-08 23:31:31 +00:00
|
|
|
extern bool CPU_ProbeSHA256();
|
2018-07-14 12:20:16 +00:00
|
|
|
extern bool CPU_ProbeSHA512();
|
|
|
|
extern bool CPU_ProbeSHA3();
|
|
|
|
extern bool CPU_ProbeSM3();
|
|
|
|
extern bool CPU_ProbeSM4();
|
2017-08-17 16:33:43 +00:00
|
|
|
extern bool CPU_ProbePMULL();
|
|
|
|
|
2019-05-21 03:02:36 +00:00
|
|
|
// https://github.com/torvalds/linux/blob/master/arch/arm/include/uapi/asm/hwcap.h
|
Add ARMv8.4 cpu feature detection support (GH #685) (#687)
This PR adds ARMv8.4 cpu feature detection support. Previously we only needed ARMv8.1 and things were much easier. For example, ARMv8.1 `__ARM_FEATURE_CRYPTO` meant PMULL, AES, SHA-1 and SHA-256 were available. ARMv8.4 `__ARM_FEATURE_CRYPTO` means PMULL, AES, SHA-1, SHA-256, SHA-512, SHA-3, SM3 and SM4 are available.
We still use the same pattern as before. We make something available based on compiler version and/or preprocessor macros. But this time around we had to tighten things up a bit to ensure ARMv8.4 did not cross-pollinate down into ARMv8.1.
ARMv8.4 is largely untested at the moment. There is no hardware in the field and CI lacks QEMU with the relevant patches/support. We will probably have to revisit some of this stuff in the future.
Since this update applies to ARM gadgets we took the time to expand Android and iOS testing on Travis. Travis now tests more platforms, and includes Autotools and CMake builds, too.
2018-07-15 12:35:14 +00:00
|
|
|
// https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
|
2018-07-08 06:49:21 +00:00
|
|
|
#ifndef HWCAP_ARMv7
|
|
|
|
# define HWCAP_ARMv7 (1 << 29)
|
|
|
|
#endif
|
2017-09-17 04:41:48 +00:00
|
|
|
#ifndef HWCAP_ASIMD
|
|
|
|
# define HWCAP_ASIMD (1 << 1)
|
|
|
|
#endif
|
2019-05-21 03:02:36 +00:00
|
|
|
#ifndef HWCAP_NEON
|
|
|
|
# define HWCAP_NEON (1 << 12)
|
2017-09-17 04:41:48 +00:00
|
|
|
#endif
|
|
|
|
#ifndef HWCAP_CRC32
|
|
|
|
# define HWCAP_CRC32 (1 << 7)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP2_CRC32
|
|
|
|
# define HWCAP2_CRC32 (1 << 4)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP_PMULL
|
|
|
|
# define HWCAP_PMULL (1 << 4)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP2_PMULL
|
|
|
|
# define HWCAP2_PMULL (1 << 1)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP_AES
|
|
|
|
# define HWCAP_AES (1 << 3)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP2_AES
|
|
|
|
# define HWCAP2_AES (1 << 0)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP_SHA1
|
|
|
|
# define HWCAP_SHA1 (1 << 5)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP_SHA2
|
|
|
|
# define HWCAP_SHA2 (1 << 6)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP2_SHA1
|
|
|
|
# define HWCAP2_SHA1 (1 << 2)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP2_SHA2
|
|
|
|
# define HWCAP2_SHA2 (1 << 3)
|
|
|
|
#endif
|
2018-07-14 12:20:16 +00:00
|
|
|
#ifndef HWCAP_SHA3
|
|
|
|
# define HWCAP_SHA3 (1 << 17)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP_SM3
|
|
|
|
# define HWCAP_SM3 (1 << 18)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP_SM4
|
|
|
|
# define HWCAP_SM4 (1 << 19)
|
|
|
|
#endif
|
|
|
|
#ifndef HWCAP_SHA512
|
|
|
|
# define HWCAP_SHA512 (1 << 21)
|
|
|
|
#endif
|
|
|
|
|
2018-07-08 06:49:21 +00:00
|
|
|
inline bool CPU_QueryARMv7()
|
|
|
|
{
|
2019-05-21 03:09:57 +00:00
|
|
|
#if defined(__ANDROID__) && defined(__arm__)
|
2018-07-08 06:49:21 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0))
|
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__arm__)
|
2019-05-21 03:02:36 +00:00
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_ARMv7) != 0 ||
|
|
|
|
(getauxval(AT_HWCAP) & HWCAP_NEON) != 0)
|
2018-07-08 06:49:21 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__APPLE__) && defined(__arm__)
|
|
|
|
// Apple hardware is ARMv7 or above.
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-17 16:33:43 +00:00
|
|
|
inline bool CPU_QueryNEON()
|
2016-05-15 06:30:08 +00:00
|
|
|
{
|
2017-09-13 11:16:41 +00:00
|
|
|
#if defined(__ANDROID__) && defined(__aarch64__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_ASIMD) != 0))
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__ANDROID__) && defined(__arm__)
|
2018-07-08 06:49:21 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
2018-03-21 20:19:43 +00:00
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0))
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch64__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_ASIMD) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch32__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP2) & HWCAP2_ASIMD) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__arm__)
|
2019-05-21 03:02:36 +00:00
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_NEON) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
2017-08-18 07:03:42 +00:00
|
|
|
#elif defined(__APPLE__) && defined(__aarch64__)
|
|
|
|
// Core feature set for Aarch32 and Aarch64.
|
|
|
|
return true;
|
2017-08-17 16:33:43 +00:00
|
|
|
#endif
|
2016-05-16 22:47:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-17 16:33:43 +00:00
|
|
|
inline bool CPU_QueryCRC32()
|
2016-07-24 13:48:28 +00:00
|
|
|
{
|
2017-09-13 11:16:41 +00:00
|
|
|
#if defined(__ANDROID__) && defined(__aarch64__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_CRC32) != 0))
|
2017-09-13 11:16:41 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__ANDROID__) && defined(__aarch32__)
|
2018-07-08 06:49:21 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
2018-03-21 20:19:43 +00:00
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_CRC32) != 0))
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch64__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_CRC32) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch32__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
2017-08-18 07:03:42 +00:00
|
|
|
#elif defined(__APPLE__) && defined(__aarch64__)
|
|
|
|
// No compiler support. CRC intrinsics result in a failed compiled.
|
|
|
|
return false;
|
2017-08-17 16:33:43 +00:00
|
|
|
#endif
|
2016-07-24 13:48:28 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-17 16:33:43 +00:00
|
|
|
inline bool CPU_QueryPMULL()
|
2016-05-16 22:47:43 +00:00
|
|
|
{
|
2017-09-13 11:16:41 +00:00
|
|
|
#if defined(__ANDROID__) && defined(__aarch64__)
|
2018-07-08 06:49:21 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
|
2018-03-21 20:19:43 +00:00
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_PMULL) != 0))
|
2017-09-13 11:16:41 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__ANDROID__) && defined(__aarch32__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_PMULL) != 0))
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch64__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_PMULL) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch32__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP2) & HWCAP2_PMULL) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
2017-08-18 07:03:42 +00:00
|
|
|
#elif defined(__APPLE__) && defined(__aarch64__)
|
|
|
|
// No compiler support. PMULL intrinsics result in a failed compiled.
|
|
|
|
return false;
|
2017-08-17 16:33:43 +00:00
|
|
|
#endif
|
2016-05-16 22:47:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-17 16:33:43 +00:00
|
|
|
inline bool CPU_QueryAES()
|
2016-05-16 22:47:43 +00:00
|
|
|
{
|
2017-09-13 11:16:41 +00:00
|
|
|
#if defined(__ANDROID__) && defined(__aarch64__)
|
2018-07-08 06:49:21 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
|
2018-03-21 20:19:43 +00:00
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES) != 0))
|
2017-09-13 11:16:41 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__ANDROID__) && defined(__aarch32__)
|
2018-07-08 06:49:21 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
2018-03-21 20:19:43 +00:00
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES) != 0))
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch64__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_AES) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch32__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP2) & HWCAP2_AES) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
2017-08-17 17:52:26 +00:00
|
|
|
#elif defined(__APPLE__) && defined(__aarch64__)
|
2018-07-14 12:20:16 +00:00
|
|
|
unsigned int device, version;
|
|
|
|
GetAppleMachineInfo(device, version);
|
|
|
|
return IsAppleMachineARMv8(device, version);
|
2017-08-17 16:33:43 +00:00
|
|
|
#endif
|
2016-05-19 08:45:35 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-17 16:33:43 +00:00
|
|
|
inline bool CPU_QuerySHA1()
|
2016-05-19 08:45:35 +00:00
|
|
|
{
|
2017-09-13 11:16:41 +00:00
|
|
|
#if defined(__ANDROID__) && defined(__aarch64__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA1) != 0))
|
2017-09-13 11:16:41 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__ANDROID__) && defined(__aarch32__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA1) != 0))
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch64__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_SHA1) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch32__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP2) & HWCAP2_SHA1) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
2017-08-18 07:03:42 +00:00
|
|
|
#elif defined(__APPLE__) && defined(__aarch64__)
|
2018-07-14 12:20:16 +00:00
|
|
|
unsigned int device, version;
|
|
|
|
GetAppleMachineInfo(device, version);
|
|
|
|
return IsAppleMachineARMv8(device, version);
|
2017-08-17 16:33:43 +00:00
|
|
|
#endif
|
2016-05-19 08:45:35 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-05-08 23:31:31 +00:00
|
|
|
inline bool CPU_QuerySHA256()
|
2016-05-19 08:45:35 +00:00
|
|
|
{
|
2017-09-13 11:16:41 +00:00
|
|
|
#if defined(__ANDROID__) && defined(__aarch64__)
|
2018-07-08 06:49:21 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
|
2018-03-21 20:19:43 +00:00
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA2) != 0))
|
2017-09-13 11:16:41 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__ANDROID__) && defined(__aarch32__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA2) != 0))
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch64__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_SHA2) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch32__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP2) & HWCAP2_SHA2) != 0)
|
2017-08-17 16:33:43 +00:00
|
|
|
return true;
|
2017-08-18 07:03:42 +00:00
|
|
|
#elif defined(__APPLE__) && defined(__aarch64__)
|
2018-07-14 12:20:16 +00:00
|
|
|
unsigned int device, version;
|
|
|
|
GetAppleMachineInfo(device, version);
|
|
|
|
return IsAppleMachineARMv8(device, version);
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
2017-08-18 07:03:42 +00:00
|
|
|
|
2018-07-14 12:20:16 +00:00
|
|
|
inline bool CPU_QuerySHA512()
|
|
|
|
{
|
|
|
|
// Some ARMv8.4 features are disabled at the moment
|
|
|
|
#if defined(__ANDROID__) && defined(__aarch64__) && 0
|
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA512) != 0))
|
2017-08-18 07:03:42 +00:00
|
|
|
return true;
|
2018-07-14 12:20:16 +00:00
|
|
|
#elif defined(__ANDROID__) && defined(__aarch32__) && 0
|
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA512) != 0))
|
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch64__)
|
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_SHA512) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch32__)
|
|
|
|
if ((getauxval(AT_HWCAP2) & HWCAP2_SHA512) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(__APPLE__) && defined(__aarch64__) && 0
|
|
|
|
unsigned int device, version;
|
|
|
|
GetAppleMachineInfo(device, version);
|
|
|
|
return IsAppleMachineARMv84(device, version);
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool CPU_QuerySHA3()
|
|
|
|
{
|
|
|
|
// Some ARMv8.4 features are disabled at the moment
|
|
|
|
#if defined(__ANDROID__) && defined(__aarch64__) && 0
|
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA3) != 0))
|
|
|
|
return true;
|
|
|
|
#elif defined(__ANDROID__) && defined(__aarch32__) && 0
|
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA3) != 0))
|
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch64__)
|
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_SHA3) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch32__)
|
|
|
|
if ((getauxval(AT_HWCAP2) & HWCAP2_SHA3) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(__APPLE__) && defined(__aarch64__) && 0
|
|
|
|
unsigned int device, version;
|
|
|
|
GetAppleMachineInfo(device, version);
|
|
|
|
return IsAppleMachineARMv84(device, version);
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool CPU_QuerySM3()
|
|
|
|
{
|
|
|
|
// Some ARMv8.4 features are disabled at the moment
|
|
|
|
#if defined(__ANDROID__) && defined(__aarch64__) && 0
|
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM3) != 0))
|
|
|
|
return true;
|
|
|
|
#elif defined(__ANDROID__) && defined(__aarch32__) && 0
|
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM3) != 0))
|
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch64__)
|
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_SM3) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch32__)
|
|
|
|
if ((getauxval(AT_HWCAP2) & HWCAP2_SM3) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(__APPLE__) && defined(__aarch64__) && 0
|
|
|
|
unsigned int device, version;
|
|
|
|
GetAppleMachineInfo(device, version);
|
|
|
|
return IsAppleMachineARMv84(device, version);
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool CPU_QuerySM4()
|
|
|
|
{
|
|
|
|
// Some ARMv8.4 features are disabled at the moment
|
|
|
|
#if defined(__ANDROID__) && defined(__aarch64__) && 0
|
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM4) != 0))
|
|
|
|
return true;
|
|
|
|
#elif defined(__ANDROID__) && defined(__aarch32__) && 0
|
|
|
|
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
|
|
|
|
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM4) != 0))
|
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch64__)
|
|
|
|
if ((getauxval(AT_HWCAP) & HWCAP_SM4) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(__linux__) && defined(__aarch32__)
|
|
|
|
if ((getauxval(AT_HWCAP2) & HWCAP2_SM4) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(__APPLE__) && defined(__aarch64__) && 0
|
|
|
|
unsigned int device, version;
|
|
|
|
GetAppleMachineInfo(device, version);
|
|
|
|
return IsAppleMachineARMv84(device, version);
|
2017-08-17 16:33:43 +00:00
|
|
|
#endif
|
2016-05-16 22:47:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DetectArmFeatures()
|
|
|
|
{
|
2017-08-18 07:03:42 +00:00
|
|
|
// The CPU_ProbeXXX's return false for OSes which
|
|
|
|
// can't tolerate SIGILL-based probes
|
2018-07-08 06:49:21 +00:00
|
|
|
g_hasARMv7 = CPU_QueryARMv7() || CPU_ProbeARMv7();
|
|
|
|
g_hasNEON = CPU_QueryNEON() || CPU_ProbeNEON();
|
2017-08-17 16:33:43 +00:00
|
|
|
g_hasCRC32 = CPU_QueryCRC32() || CPU_ProbeCRC32();
|
|
|
|
g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
|
|
|
|
g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
|
|
|
|
g_hasSHA1 = CPU_QuerySHA1() || CPU_ProbeSHA1();
|
2019-05-08 23:31:31 +00:00
|
|
|
g_hasSHA2 = CPU_QuerySHA256() || CPU_ProbeSHA256();
|
2018-07-14 12:20:16 +00:00
|
|
|
g_hasSHA512 = CPU_QuerySHA512(); // || CPU_ProbeSHA512();
|
|
|
|
g_hasSHA3 = CPU_QuerySHA3(); // || CPU_ProbeSHA3();
|
|
|
|
g_hasSM3 = CPU_QuerySM3(); // || CPU_ProbeSM3();
|
|
|
|
g_hasSM4 = CPU_QuerySM4(); // || CPU_ProbeSM4();
|
2016-05-16 22:47:43 +00:00
|
|
|
|
2019-05-08 23:54:05 +00:00
|
|
|
#if defined(_SC_LEVEL1_DCACHE_LINESIZE)
|
2018-03-21 20:19:43 +00:00
|
|
|
// Glibc does not implement on some platforms. The runtime returns 0 instead of error.
|
|
|
|
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
|
|
|
|
int cacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
|
|
|
|
if (cacheLineSize > 0)
|
|
|
|
g_cacheLineSize = cacheLineSize;
|
2017-09-17 06:39:41 +00:00
|
|
|
#endif
|
|
|
|
|
2019-05-08 23:54:05 +00:00
|
|
|
if (g_cacheLineSize == 0)
|
|
|
|
g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
|
|
|
|
|
2017-11-17 00:37:29 +00:00
|
|
|
*const_cast<volatile bool*>(&g_ArmDetectionDone) = true;
|
2016-05-15 06:30:08 +00:00
|
|
|
}
|
|
|
|
|
2017-09-11 07:05:04 +00:00
|
|
|
// *************************** PowerPC and PowerPC64 ***************************
|
|
|
|
|
|
|
|
#elif (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
|
|
|
|
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_PowerpcDetectionDone = false;
|
2018-03-28 03:19:26 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasAltivec = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasPower7 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasPower8 = false;
|
2018-11-27 07:54:26 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasPower9 = false;
|
2018-03-28 03:19:26 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasAES = false;
|
2018-08-06 09:40:38 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
|
2018-03-28 03:19:26 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSHA256 = false;
|
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
|
2018-11-27 07:54:26 +00:00
|
|
|
bool CRYPTOPP_SECTION_INIT g_hasDARN = false;
|
2017-09-11 07:05:04 +00:00
|
|
|
word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
|
|
|
|
|
2017-09-12 02:39:59 +00:00
|
|
|
extern bool CPU_ProbeAltivec();
|
2017-10-18 02:50:45 +00:00
|
|
|
extern bool CPU_ProbePower7();
|
2017-09-12 02:39:59 +00:00
|
|
|
extern bool CPU_ProbePower8();
|
2018-11-27 07:54:26 +00:00
|
|
|
extern bool CPU_ProbePower9();
|
2017-09-12 02:39:59 +00:00
|
|
|
extern bool CPU_ProbeAES();
|
2018-08-06 09:40:38 +00:00
|
|
|
extern bool CPU_ProbePMULL();
|
2017-09-22 12:58:50 +00:00
|
|
|
extern bool CPU_ProbeSHA256();
|
|
|
|
extern bool CPU_ProbeSHA512();
|
2018-11-27 07:54:26 +00:00
|
|
|
extern bool CPU_ProbeDARN();
|
2017-09-11 07:05:04 +00:00
|
|
|
|
2018-11-30 10:57:02 +00:00
|
|
|
// Linux define values from 64-Bit ELF V2 ABI Specification.
|
|
|
|
// http://openpowerfoundation.org/wp-content/uploads/resources/leabi/content/ch_preface.html
|
2017-09-17 04:41:48 +00:00
|
|
|
#ifndef PPC_FEATURE_HAS_ALTIVEC
|
|
|
|
# define PPC_FEATURE_HAS_ALTIVEC 0x10000000
|
|
|
|
#endif
|
|
|
|
#ifndef PPC_FEATURE_ARCH_2_06
|
|
|
|
# define PPC_FEATURE_ARCH_2_06 0x00000100
|
|
|
|
#endif
|
|
|
|
#ifndef PPC_FEATURE2_ARCH_2_07
|
|
|
|
# define PPC_FEATURE2_ARCH_2_07 0x80000000
|
|
|
|
#endif
|
2018-11-27 07:54:26 +00:00
|
|
|
#ifndef PPC_FEATURE2_ARCH_3_00
|
|
|
|
# define PPC_FEATURE2_ARCH_3_00 0x00800000
|
|
|
|
#endif
|
2017-09-17 04:41:48 +00:00
|
|
|
#ifndef PPC_FEATURE2_VEC_CRYPTO
|
|
|
|
# define PPC_FEATURE2_VEC_CRYPTO 0x02000000
|
|
|
|
#endif
|
|
|
|
|
2018-11-27 07:54:26 +00:00
|
|
|
// AIX defines. We used to just call __power_7_andup()
|
|
|
|
// and friends but at Power9, too many compilers were
|
|
|
|
// missing __power_9_andup(). Instead we switched to
|
|
|
|
// a pattern similar to OpenSSL caps testing.
|
|
|
|
#ifndef __power_6_andup
|
|
|
|
# define __power_6_andup() __power_set(0xffffffffU<<14)
|
|
|
|
#endif
|
|
|
|
#ifndef __power_7_andup
|
|
|
|
# define __power_7_andup() __power_set(0xffffffffU<<15)
|
|
|
|
#endif
|
|
|
|
#ifndef __power_8_andup
|
|
|
|
# define __power_8_andup() __power_set(0xffffffffU<<16)
|
|
|
|
#endif
|
|
|
|
#ifndef __power_9_andup
|
|
|
|
# define __power_9_andup() __power_set(0xffffffffU<<17)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// AIX first supported Altivec at Power6, though it
|
|
|
|
// was available much earlier for other vendors.
|
2017-09-11 07:05:04 +00:00
|
|
|
inline bool CPU_QueryAltivec()
|
|
|
|
{
|
|
|
|
#if defined(__linux__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC) != 0)
|
2017-09-11 07:05:04 +00:00
|
|
|
return true;
|
2018-03-21 04:35:56 +00:00
|
|
|
#elif defined(_AIX)
|
2018-11-27 07:54:26 +00:00
|
|
|
if (__power_6_andup() != 0)
|
2018-03-21 04:35:56 +00:00
|
|
|
return true;
|
2017-12-13 16:49:35 +00:00
|
|
|
#elif defined(__APPLE__) && defined(__POWERPC__)
|
2018-07-14 12:20:16 +00:00
|
|
|
unsigned int device, version;
|
|
|
|
GetAppleMachineInfo(device, version);
|
|
|
|
return device == PowerMac;
|
2017-09-11 07:05:04 +00:00
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool CPU_QueryPower7()
|
|
|
|
{
|
|
|
|
// Power7 and ISA 2.06
|
|
|
|
#if defined(__linux__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP) & PPC_FEATURE_ARCH_2_06) != 0)
|
2018-03-21 03:52:10 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(_AIX)
|
2018-03-21 04:35:56 +00:00
|
|
|
if (__power_7_andup() != 0)
|
2017-09-11 07:05:04 +00:00
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool CPU_QueryPower8()
|
|
|
|
{
|
2017-09-12 02:39:59 +00:00
|
|
|
// Power8 and ISA 2.07 provide in-core crypto.
|
2017-09-11 07:05:04 +00:00
|
|
|
#if defined(__linux__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07) != 0)
|
2018-03-21 03:52:10 +00:00
|
|
|
return true;
|
|
|
|
#elif defined(_AIX)
|
|
|
|
if (__power_8_andup() != 0)
|
2017-09-11 07:05:04 +00:00
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-11-27 07:54:26 +00:00
|
|
|
inline bool CPU_QueryPower9()
|
|
|
|
{
|
|
|
|
// Power9 and ISA 3.0.
|
|
|
|
#if defined(__linux__)
|
|
|
|
if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(_AIX)
|
|
|
|
if (__power_9_andup() != 0)
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-11 07:05:04 +00:00
|
|
|
inline bool CPU_QueryAES()
|
|
|
|
{
|
2017-09-12 02:39:59 +00:00
|
|
|
// Power8 and ISA 2.07 provide in-core crypto. Glibc
|
|
|
|
// 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
|
2017-09-11 07:05:04 +00:00
|
|
|
#if defined(__linux__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
|
2017-09-11 07:05:04 +00:00
|
|
|
return true;
|
2018-03-21 03:52:10 +00:00
|
|
|
#elif defined(_AIX)
|
|
|
|
if (__power_8_andup() != 0)
|
|
|
|
return true;
|
2017-09-11 07:05:04 +00:00
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-06 09:40:38 +00:00
|
|
|
inline bool CPU_QueryPMULL()
|
|
|
|
{
|
|
|
|
// Power8 and ISA 2.07 provide in-core crypto. Glibc
|
|
|
|
// 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
|
|
|
|
#if defined(__linux__)
|
|
|
|
if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(_AIX)
|
|
|
|
if (__power_8_andup() != 0)
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-22 12:58:50 +00:00
|
|
|
inline bool CPU_QuerySHA256()
|
2017-09-11 07:05:04 +00:00
|
|
|
{
|
2017-09-12 02:39:59 +00:00
|
|
|
// Power8 and ISA 2.07 provide in-core crypto. Glibc
|
|
|
|
// 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
|
2017-09-11 07:05:04 +00:00
|
|
|
#if defined(__linux__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
|
2017-09-11 07:05:04 +00:00
|
|
|
return true;
|
2018-03-21 03:52:10 +00:00
|
|
|
#elif defined(_AIX)
|
|
|
|
if (__power_8_andup() != 0)
|
|
|
|
return true;
|
2017-09-11 07:05:04 +00:00
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
2017-09-22 12:58:50 +00:00
|
|
|
inline bool CPU_QuerySHA512()
|
2017-09-11 07:05:04 +00:00
|
|
|
{
|
2017-09-12 02:39:59 +00:00
|
|
|
// Power8 and ISA 2.07 provide in-core crypto. Glibc
|
|
|
|
// 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
|
2017-09-11 07:05:04 +00:00
|
|
|
#if defined(__linux__)
|
2018-03-21 20:19:43 +00:00
|
|
|
if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
|
2017-09-11 07:05:04 +00:00
|
|
|
return true;
|
2018-03-21 03:52:10 +00:00
|
|
|
#elif defined(_AIX)
|
|
|
|
if (__power_8_andup() != 0)
|
|
|
|
return true;
|
2017-09-11 07:05:04 +00:00
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-11-27 07:54:26 +00:00
|
|
|
// Power9 random number generator
|
|
|
|
inline bool CPU_QueryDARN()
|
|
|
|
{
|
|
|
|
// Power9 and ISA 3.0 provide DARN.
|
|
|
|
#if defined(__linux__)
|
|
|
|
if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0)
|
|
|
|
return true;
|
|
|
|
#elif defined(_AIX)
|
|
|
|
if (__power_9_andup() != 0)
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-11 07:05:04 +00:00
|
|
|
void DetectPowerpcFeatures()
|
|
|
|
{
|
|
|
|
// The CPU_ProbeXXX's return false for OSes which
|
|
|
|
// can't tolerate SIGILL-based probes, like Apple
|
|
|
|
g_hasAltivec = CPU_QueryAltivec() || CPU_ProbeAltivec();
|
2017-10-18 02:50:45 +00:00
|
|
|
g_hasPower7 = CPU_QueryPower7() || CPU_ProbePower7();
|
2017-09-11 07:05:04 +00:00
|
|
|
g_hasPower8 = CPU_QueryPower8() || CPU_ProbePower8();
|
2018-11-27 07:54:26 +00:00
|
|
|
g_hasPower9 = CPU_QueryPower9() || CPU_ProbePower9();
|
2018-08-06 09:40:38 +00:00
|
|
|
g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
|
2017-09-11 07:05:04 +00:00
|
|
|
g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
|
2017-09-22 12:58:50 +00:00
|
|
|
g_hasSHA256 = CPU_QuerySHA256() || CPU_ProbeSHA256();
|
|
|
|
g_hasSHA512 = CPU_QuerySHA512() || CPU_ProbeSHA512();
|
2018-11-27 07:54:26 +00:00
|
|
|
g_hasDARN = CPU_QueryDARN() || CPU_ProbeDARN();
|
2017-09-11 07:05:04 +00:00
|
|
|
|
2018-03-21 20:19:43 +00:00
|
|
|
#if defined(_AIX) && defined(SC_L1C_DLS)
|
2017-09-11 07:05:04 +00:00
|
|
|
// /usr/include/sys/systemcfg.h
|
2018-03-21 20:19:43 +00:00
|
|
|
int cacheLineSize = getsystemcfg(SC_L1C_DLS);
|
|
|
|
if (cacheLineSize > 0)
|
|
|
|
g_cacheLineSize = cacheLineSize;
|
2019-05-08 23:54:05 +00:00
|
|
|
#elif defined(_SC_LEVEL1_DCACHE_LINESIZE)
|
2018-03-21 20:19:43 +00:00
|
|
|
// Glibc does not implement on some platforms. The runtime returns 0 instead of error.
|
|
|
|
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
|
|
|
|
int cacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
|
|
|
|
if (cacheLineSize > 0)
|
|
|
|
g_cacheLineSize = cacheLineSize;
|
2017-09-11 07:05:04 +00:00
|
|
|
#endif
|
|
|
|
|
2019-05-08 23:54:05 +00:00
|
|
|
if (g_cacheLineSize == 0)
|
|
|
|
g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
|
|
|
|
|
2017-11-17 00:37:29 +00:00
|
|
|
*const_cast<volatile bool*>(&g_PowerpcDetectionDone) = true;
|
2017-09-11 07:05:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-05 06:59:46 +00:00
|
|
|
#endif
|
|
|
|
NAMESPACE_END
|
|
|
|
|
2017-08-18 07:03:42 +00:00
|
|
|
// *************************** C++ Static Initialization ***************************
|
2017-03-20 12:51:10 +00:00
|
|
|
|
|
|
|
ANONYMOUS_NAMESPACE_BEGIN
|
2017-11-12 16:55:57 +00:00
|
|
|
|
|
|
|
class InitCpu
|
2017-03-20 12:51:10 +00:00
|
|
|
{
|
2017-11-12 16:55:57 +00:00
|
|
|
public:
|
|
|
|
InitCpu()
|
2017-03-20 12:51:10 +00:00
|
|
|
{
|
|
|
|
#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
|
|
|
|
CryptoPP::DetectX86Features();
|
2018-12-09 15:24:55 +00:00
|
|
|
#elif CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8
|
2017-03-20 12:51:10 +00:00
|
|
|
CryptoPP::DetectArmFeatures();
|
2017-09-11 07:05:04 +00:00
|
|
|
#elif CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64
|
|
|
|
CryptoPP::DetectPowerpcFeatures();
|
2017-03-20 12:51:10 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-11-12 16:55:57 +00:00
|
|
|
// This is not really needed because HasSSE() and friends can dynamically initialize.
|
|
|
|
// Everything depends on CPU features so we initialize it once at load time.
|
|
|
|
// Dynamic initialization will be used if init priorities are not available.
|
|
|
|
|
2017-03-20 12:51:10 +00:00
|
|
|
#if HAVE_GCC_INIT_PRIORITY
|
2017-11-12 16:55:57 +00:00
|
|
|
const InitCpu s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 10))) = InitCpu();
|
2017-03-20 12:51:10 +00:00
|
|
|
#elif HAVE_MSC_INIT_PRIORITY
|
2017-11-12 16:55:57 +00:00
|
|
|
#pragma warning(disable: 4075)
|
|
|
|
#pragma init_seg(".CRT$XCU")
|
|
|
|
const InitCpu s_init;
|
|
|
|
#pragma warning(default: 4075)
|
2018-11-30 13:23:35 +00:00
|
|
|
#elif HAVE_XLC_INIT_PRIORITY
|
|
|
|
// XLC needs constant, not a define
|
|
|
|
#pragma priority(270)
|
|
|
|
const InitCpu s_init;
|
2017-03-20 12:51:10 +00:00
|
|
|
#else
|
2017-11-12 16:55:57 +00:00
|
|
|
const InitCpu s_init;
|
2015-11-05 06:59:46 +00:00
|
|
|
#endif
|
2017-11-12 16:55:57 +00:00
|
|
|
|
2017-03-20 12:51:10 +00:00
|
|
|
ANONYMOUS_NAMESPACE_END
|
|
|
|
|
|
|
|
#endif // CRYPTOPP_IMPORTS
|