Crypto++  8.3
Free C++ class library of cryptographic schemes
cpu.cpp
1 // cpu.cpp - originally written and placed in the public domain by Wei Dai
2 // modified by Jeffrey Walton and the community over the years.
3 
4 #include "pch.h"
5 #include "config.h"
6 
7 #ifndef EXCEPTION_EXECUTE_HANDLER
8 # define EXCEPTION_EXECUTE_HANDLER 1
9 #endif
10 
11 #ifndef CRYPTOPP_IMPORTS
12 
13 #include "cpu.h"
14 #include "misc.h"
15 #include "stdcpp.h"
16 
17 // For _xgetbv on Microsoft 32-bit and 64-bit Intel platforms
18 // https://github.com/weidai11/cryptopp/issues/972
19 #if _MSC_VER >= 1600 && (defined(_M_IX86) || defined(_M_X64))
20 # include <immintrin.h>
21 #endif
22 
23 #ifdef _AIX
24 # include <sys/systemcfg.h>
25 #endif
26 
27 #ifdef __linux__
28 # include <unistd.h>
29 #endif
30 
31 // Capability queries, requires Glibc 2.16, http://lwn.net/Articles/519085/
32 // CRYPTOPP_GLIBC_VERSION not used because config.h is missing <feature.h>
33 #if (((__GLIBC__ * 100) + __GLIBC_MINOR__) >= 216)
34 # define CRYPTOPP_GETAUXV_AVAILABLE 1
35 #endif
36 
37 #if CRYPTOPP_GETAUXV_AVAILABLE
38 # include <sys/auxv.h>
39 #else
40 #ifndef AT_HWCAP
41 # define AT_HWCAP 16
42 #endif
43 #ifndef AT_HWCAP2
44 # define AT_HWCAP2 26
45 #endif
46 unsigned long int getauxval(unsigned long int) { return 0; }
47 #endif
48 
49 #if defined(__APPLE__)
50 # include <sys/utsname.h>
51 #endif
52 
53 // The cpu-features header and source file are located in
54 // "$ANDROID_NDK_ROOT/sources/android/cpufeatures".
55 // setenv-android.sh will copy the header and source file
56 // into PWD and the makefile will build it in place.
57 #if defined(__ANDROID__)
58 # include "cpu-features.h"
59 #endif
60 
61 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
62 # include <signal.h>
63 # include <setjmp.h>
64 #endif
65 
66 // Visual Studio 2008 and below are missing _xgetbv and _cpuidex.
67 // The 32-bit versions use inline ASM below. The 64-bit versions are in x64dll.asm.
68 #if defined(_MSC_VER) && defined(_M_X64)
69 extern "C" unsigned long long __fastcall XGETBV64(unsigned int);
70 extern "C" unsigned long long __fastcall CPUID64(unsigned int, unsigned int, unsigned int*);
71 #endif
72 
73 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
74 extern "C" {
75  typedef void (*SigHandler)(int);
76 }
77 
78 extern "C"
79 {
80  static jmp_buf s_jmpNoCPUID;
81  static void SigIllHandler(int)
82  {
83  longjmp(s_jmpNoCPUID, 1);
84  }
85 }
86 #endif // CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
87 
88 ANONYMOUS_NAMESPACE_BEGIN
89 
90 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
91 
92 using CryptoPP::word32;
93 
94 inline bool IsIntel(const word32 output[4])
95 {
96  // This is the "GenuineIntel" string
97  return (output[1] /*EBX*/ == 0x756e6547) &&
98  (output[2] /*ECX*/ == 0x6c65746e) &&
99  (output[3] /*EDX*/ == 0x49656e69);
100 }
101 
102 inline bool IsAMD(const word32 output[4])
103 {
104  // This is the "AuthenticAMD" string.
105  return ((output[1] /*EBX*/ == 0x68747541) &&
106  (output[2] /*ECX*/ == 0x444D4163) &&
107  (output[3] /*EDX*/ == 0x69746E65)) ||
108  // Early K5's can return "AMDisbetter!"
109  ((output[1] /*EBX*/ == 0x69444d41) &&
110  (output[2] /*ECX*/ == 0x74656273) &&
111  (output[3] /*EDX*/ == 0x21726574));
112 }
113 
114 inline bool IsHygon(const word32 output[4])
115 {
116  // This is the "HygonGenuine" string.
117  return (output[1] /*EBX*/ == 0x6f677948) &&
118  (output[2] /*ECX*/ == 0x656e6975) &&
119  (output[3] /*EDX*/ == 0x6e65476e);
120 }
121 
122 inline bool IsVIA(const word32 output[4])
123 {
124  // This is the "CentaurHauls" string.
125  return ((output[1] /*EBX*/ == 0x746e6543) &&
126  (output[2] /*ECX*/ == 0x736c7561) &&
127  (output[3] /*EDX*/ == 0x48727561)) ||
128  // Some non-PadLock's return "VIA VIA VIA "
129  ((output[1] /*EBX*/ == 0x32414956) &&
130  (output[2] /*ECX*/ == 0x32414956) &&
131  (output[3] /*EDX*/ == 0x32414956));
132 }
133 
134 #endif // X86, X32 and X64
135 
136 #if defined(__APPLE__)
137 
138 // http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
139 class AppleMachineInfo
140 {
141 public:
142  enum { PowerMac=1, Mac, iPhone, iPod, iPad, AppleTV, AppleWatch };
143  enum { PowerPC=1, I386, I686, X86_64, ARM32, ARMV8, ARMV84 };
144 
145  AppleMachineInfo() : m_device(0), m_version(0), m_arch(0)
146  {
147  struct utsname systemInfo;
148  systemInfo.machine[0] = '\0';
149  uname(&systemInfo);
150 
151  std::string machine(systemInfo.machine);
152 
153  std::string::size_type pos = machine.find_first_of("0123456789");
154  if (pos != std::string::npos)
155  m_version = std::atoi(machine.substr(pos).c_str());
156 
157  if (machine.find("iPhone") != std::string::npos)
158  {
159  m_device = iPhone;
160  if (m_version >= 6) { m_arch = ARMV8; }
161  else { m_arch = ARM32; }
162  }
163  else if (machine.find("iPod") != std::string::npos)
164  {
165  m_device = iPod;
166  if (m_version >= 6) { m_arch = ARMV8; }
167  else { m_arch = ARM32; }
168  }
169  else if (machine.find("iPad") != std::string::npos)
170  {
171  m_device = iPad;
172  if (m_version >= 5) { m_arch = ARMV8; }
173  else { m_arch = ARM32; }
174  }
175  else if (machine.find("PowerMac") != std::string::npos ||
176  machine.find("Power Macintosh") != std::string::npos)
177  {
178  m_device = PowerMac;
179  m_arch = PowerPC;
180  }
181  else if (machine.find("Mac") != std::string::npos ||
182  machine.find("Macintosh") != std::string::npos)
183  {
184 #if defined(__x86_64) || defined(__amd64)
185  m_device = Mac;
186  m_arch = X86_64;
187 #elif defined(__i386)
188  m_device = Mac;
189  m_arch = I386;
190 #elif defined(__i686)
191  m_device = Mac;
192  m_arch = I686;
193 #else
194  // Should never get here
195  m_device = Mac;
196  m_arch = 0;
197 #endif
198  }
199  else if (machine.find("AppleTV") != std::string::npos)
200  {
201  m_device = AppleTV;
202  if (m_version >= 4) { m_arch = ARMV8; }
203  else { m_arch = ARM32; }
204  }
205  else if (machine.find("AppleWatch") != std::string::npos)
206  {
207  m_device = AppleWatch;
208  if (m_version >= 4) { m_arch = ARMV8; }
209  else { m_arch = ARM32; }
210  }
211  }
212 
213  unsigned int Device() const {
214  return m_device;
215  }
216 
217  unsigned int Version() const {
218  return m_version;
219  }
220 
221  unsigned int Arch() const {
222  return m_arch;
223  }
224 
225  bool IsARM32() const {
226  return m_arch == ARM32;
227  }
228 
229  bool IsARMv8() const {
230  return m_arch == ARMV8;
231  }
232 
233  bool IsARMv84() const {
234  return m_arch == ARMV84;
235  }
236 
237 private:
238  unsigned int m_device, m_version, m_arch;
239 };
240 
241 void GetAppleMachineInfo(unsigned int& device, unsigned int& version, unsigned int& arch)
242 {
243 #if CRYPTOPP_CXX11_STATIC_INIT
244  static const AppleMachineInfo info;
245 #else
246  using CryptoPP::Singleton;
247  const AppleMachineInfo& info = Singleton<AppleMachineInfo>().Ref();
248 #endif
249 
250  device = info.Device();
251  version = info.Version();
252  arch = info.Arch();
253 }
254 
255 inline bool IsAppleMachineARM32()
256 {
257  static unsigned int arch;
258  if (arch == 0)
259  {
260  unsigned int unused;
261  GetAppleMachineInfo(unused, unused, arch);
262  }
263  return arch == AppleMachineInfo::ARM32;
264 }
265 
266 inline bool IsAppleMachineARMv8()
267 {
268  static unsigned int arch;
269  if (arch == 0)
270  {
271  unsigned int unused;
272  GetAppleMachineInfo(unused, unused, arch);
273  }
274  return arch == AppleMachineInfo::ARMV8;
275 }
276 
277 #endif // __APPLE__
278 
279 ANONYMOUS_NAMESPACE_END
280 
281 NAMESPACE_BEGIN(CryptoPP)
282 
283 // *************************** IA-32 CPUs ***************************
284 
285 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
286 
287 bool CRYPTOPP_SECTION_INIT g_x86DetectionDone = false;
288 bool CRYPTOPP_SECTION_INIT g_hasSSE2 = false;
289 bool CRYPTOPP_SECTION_INIT g_hasSSSE3 = false;
290 bool CRYPTOPP_SECTION_INIT g_hasSSE41 = false;
291 bool CRYPTOPP_SECTION_INIT g_hasSSE42 = false;
292 bool CRYPTOPP_SECTION_INIT g_hasAESNI = false;
293 bool CRYPTOPP_SECTION_INIT g_hasCLMUL = false;
294 bool CRYPTOPP_SECTION_INIT g_hasMOVBE = false;
295 bool CRYPTOPP_SECTION_INIT g_hasAVX = false;
296 bool CRYPTOPP_SECTION_INIT g_hasAVX2 = false;
297 bool CRYPTOPP_SECTION_INIT g_hasADX = false;
298 bool CRYPTOPP_SECTION_INIT g_hasSHA = false;
299 bool CRYPTOPP_SECTION_INIT g_hasRDRAND = false;
300 bool CRYPTOPP_SECTION_INIT g_hasRDSEED = false;
301 bool CRYPTOPP_SECTION_INIT g_isP4 = false;
302 bool CRYPTOPP_SECTION_INIT g_hasPadlockRNG = false;
303 bool CRYPTOPP_SECTION_INIT g_hasPadlockACE = false;
304 bool CRYPTOPP_SECTION_INIT g_hasPadlockACE2 = false;
305 bool CRYPTOPP_SECTION_INIT g_hasPadlockPHE = false;
306 bool CRYPTOPP_SECTION_INIT g_hasPadlockPMM = false;
307 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
308 
309 // For Solaris 11
310 extern bool CPU_ProbeSSE2();
311 
312 // xcr0 is available when xgetbv is present.
313 // The intrinsic is broke on GCC 8.1 and earlier. Also see
314 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85684.
315 word64 XGetBV(word32 num)
316 {
317 // Visual Studio 2010 SP1 and above, 32 and 64-bit
318 // https://github.com/weidai11/cryptopp/issues/972
319 #if defined(_MSC_VER) && (_MSC_FULL_VER >= 160040219)
320 
321  return _xgetbv(num);
322 
323 // Visual Studio 2008 and below, 64-bit
324 #elif defined(_MSC_VER) && defined(_M_X64)
325 
326  return XGETBV64(num);
327 
328 // Visual Studio 2008 and below, 32-bit
329 #elif defined(_MSC_VER) && defined(_M_IX86)
330 
331  word32 a=0, d=0;
332  __asm {
333  push eax
334  push edx
335  push ecx
336  mov ecx, num
337  _emit 0x0f
338  _emit 0x01
339  _emit 0xd0
340  mov a, eax
341  mov d, edx
342  pop ecx
343  pop edx
344  pop eax
345  }
346  return (static_cast<word64>(d) << 32) | a;
347 
348 // GCC 4.4 and above
349 #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
350 
351  word32 a=0, d=0;
352  __asm__
353  (
354  "xgetbv" : "=a"(a), "=d"(d) : "c"(num) : "cc"
355  );
356  return (static_cast<word64>(d) << 32) | a;
357 
358 // Remainder of GCC and compatibles.
359 #elif defined(__GNUC__) || defined(__clang__)
360 
361  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71659 and
362  // http://www.agner.org/optimize/vectorclass/read.php?i=65
363  word32 a=0, d=0;
364  __asm__
365  (
366  ".byte 0x0f, 0x01, 0xd0" "\n\t"
367  : "=a"(a), "=d"(d) : "c"(num) : "cc"
368  );
369  return (static_cast<word64>(d) << 32) | a;
370 #else
371  # error "Need an xgetbv function"
372 #endif
373 }
374 
375 // No inline due to Borland/Embarcadero and Issue 498
376 // cpu.cpp (131): E2211 Inline assembly not allowed in inline and template functions
377 bool CpuId(word32 func, word32 subfunc, word32 output[4])
378 {
379 // Visual Studio 2010 and above, 32 and 64-bit
380 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
381 
382  __cpuidex((int *)output, func, subfunc);
383  return true;
384 
385 // Visual Studio 2008 and below, 64-bit
386 #elif defined(_MSC_VER) && defined(_M_X64)
387 
388  CPUID64(func, subfunc, output);
389  return true;
390 
391 // Visual Studio 2008 and below, 32-bit
392 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__BORLANDC__)
393 
394  __try
395  {
396  // Borland/Embarcadero and Issue 500
397  // Local variables for cpuid output
398  word32 a, b, c, d;
399  __asm
400  {
401  push ebx
402  mov eax, func
403  mov ecx, subfunc
404  cpuid
405  mov [a], eax
406  mov [b], ebx
407  mov [c], ecx
408  mov [d], edx
409  pop ebx
410  }
411  output[0] = a;
412  output[1] = b;
413  output[2] = c;
414  output[3] = d;
415  }
416  __except (EXCEPTION_EXECUTE_HANDLER)
417  {
418  return false;
419  }
420 
421  return true;
422 
423 // Linux, Unix, OS X, Solaris, Cygwin, MinGW
424 #else
425 
426  // longjmp and clobber warnings. Volatile is required.
427  // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
428  volatile bool result = true;
429 
430  volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
431  if (oldHandler == SIG_ERR)
432  return false;
433 
434 # ifndef __MINGW32__
435  volatile sigset_t oldMask;
436  if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask) != 0)
437  {
438  signal(SIGILL, oldHandler);
439  return false;
440  }
441 # endif
442 
443  if (setjmp(s_jmpNoCPUID))
444  result = false;
445  else
446  {
447  asm volatile
448  (
449  // save ebx in case -fPIC is being used
450 # if CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
451  "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
452 # else
453  "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
454 # endif
455  : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
456  : "a" (func), "c" (subfunc)
457  : "cc"
458  );
459  }
460 
461 # ifndef __MINGW32__
462  sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
463 # endif
464 
465  signal(SIGILL, oldHandler);
466  return result;
467 #endif
468 }
469 
470 void DetectX86Features()
471 {
472  // Coverity finding CID 171239. Initialize arrays.
473  // Indexes: EAX=0, EBX=1, ECX=2, EDX=3
474  word32 cpuid0[4]={0}, cpuid1[4]={0}, cpuid2[4]={0};
475 
476 #if defined(CRYPTOPP_DISABLE_ASM)
477  // Not available
478  goto done;
479 #else
480  if (!CpuId(0, 0, cpuid0))
481  goto done;
482  if (!CpuId(1, 0, cpuid1))
483  goto done;
484 #endif
485 
486  CRYPTOPP_CONSTANT(EAX_REG = 0);
487  CRYPTOPP_CONSTANT(EBX_REG = 1);
488  CRYPTOPP_CONSTANT(ECX_REG = 2);
489  CRYPTOPP_CONSTANT(EDX_REG = 3);
490 
491  CRYPTOPP_CONSTANT(MMX_FLAG = (1 << 24)); // EDX
492  CRYPTOPP_CONSTANT(SSE_FLAG = (1 << 25)); // EDX
493  CRYPTOPP_CONSTANT(SSE2_FLAG = (1 << 26)); // EDX
494 
495  CRYPTOPP_CONSTANT(SSE3_FLAG = (1 << 0)); // ECX
496  CRYPTOPP_CONSTANT(SSSE3_FLAG = (1 << 9)); // ECX
497  CRYPTOPP_CONSTANT(SSE41_FLAG = (1 << 19)); // ECX
498  CRYPTOPP_CONSTANT(SSE42_FLAG = (1 << 20)); // ECX
499  CRYPTOPP_CONSTANT(MOVBE_FLAG = (1 << 22)); // ECX
500  CRYPTOPP_CONSTANT(AESNI_FLAG = (1 << 25)); // ECX
501  CRYPTOPP_CONSTANT(CLMUL_FLAG = (1 << 1)); // ECX
502 
503  CRYPTOPP_CONSTANT(XSAVE_FLAG = (1 << 26)); // ECX
504  CRYPTOPP_CONSTANT(OSXSAVE_FLAG = (1 << 27)); // ECX
505 
506  CRYPTOPP_CONSTANT(AVX_FLAG = (3 << 27)); // ECX
507  CRYPTOPP_CONSTANT(YMM_FLAG = (3 << 1)); // CR0
508 
509  // x86_64 machines don't check some flags because SSE2
510  // is part of the core instruction set architecture
511  CRYPTOPP_UNUSED(MMX_FLAG); CRYPTOPP_UNUSED(SSE_FLAG);
512  CRYPTOPP_UNUSED(SSE3_FLAG); CRYPTOPP_UNUSED(XSAVE_FLAG);
513 
514 #if (CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
515  // 64-bit core instruction set includes SSE2. Just check
516  // the OS enabled SSE2 support using OSXSAVE.
517  g_hasSSE2 = (cpuid1[ECX_REG] & OSXSAVE_FLAG) != 0;
518 #else
519  // Check the processor supports SSE2. Then use OSXSAVE to
520  // signal OS support for SSE2 to avoid probes.
521  // Also see http://stackoverflow.com/a/22521619/608639
522  // and http://github.com/weidai11/cryptopp/issues/511.
523  if ((cpuid1[EDX_REG] & SSE2_FLAG) == SSE2_FLAG)
524  g_hasSSE2 = (cpuid1[ECX_REG] & XSAVE_FLAG) != 0 &&
525  (cpuid1[ECX_REG] & OSXSAVE_FLAG) != 0;
526 #endif
527 
528  // Solaris 11 i86pc does not signal SSE support using
529  // OSXSAVE. We need to probe for SSE support.
530  if (g_hasSSE2 == false)
531  g_hasSSE2 = CPU_ProbeSSE2();
532 
533  if (g_hasSSE2 == false)
534  goto done;
535 
536  g_hasSSSE3 = (cpuid1[ECX_REG] & SSSE3_FLAG) != 0;
537  g_hasSSE41 = (cpuid1[ECX_REG] & SSE41_FLAG) != 0;
538  g_hasSSE42 = (cpuid1[ECX_REG] & SSE42_FLAG) != 0;
539  g_hasMOVBE = (cpuid1[ECX_REG] & MOVBE_FLAG) != 0;
540  g_hasAESNI = (cpuid1[ECX_REG] & AESNI_FLAG) != 0;
541  g_hasCLMUL = (cpuid1[ECX_REG] & CLMUL_FLAG) != 0;
542 
543  // AVX is similar to SSE. Check if AVX is available on the cpu, then
544  // check if the OS enabled XSAVE/XRESTORE for the extended registers.
545  // https://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
546  if ((cpuid1[ECX_REG] & AVX_FLAG) == AVX_FLAG)
547  {
548  word64 xcr0 = XGetBV(0);
549  g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
550  }
551 
552  if (IsIntel(cpuid0))
553  {
554  CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30));
555  CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18));
556  CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19));
557  CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29));
558  CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5));
559 
560  g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
561  g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
562  g_hasRDRAND = (cpuid1[ECX_REG] & RDRAND_FLAG) != 0;
563 
564  if (cpuid0[EAX_REG] >= 7)
565  {
566  if (CpuId(7, 0, cpuid2))
567  {
568  g_hasRDSEED = (cpuid2[EBX_REG] & RDSEED_FLAG) != 0;
569  g_hasADX = (cpuid2[EBX_REG] & ADX_FLAG) != 0;
570  g_hasSHA = (cpuid2[EBX_REG] & SHA_FLAG) != 0;
571  g_hasAVX2 = (cpuid2[EBX_REG] & AVX2_FLAG) != 0;
572  }
573  }
574  }
575  else if (IsAMD(cpuid0) || IsHygon(cpuid0))
576  {
577  CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30));
578  CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18));
579  CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19));
580  CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29));
581  CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5));
582 
583  CpuId(0x80000005, 0, cpuid2);
584  g_cacheLineSize = GETBYTE(cpuid2[ECX_REG], 0);
585  g_hasRDRAND = (cpuid1[ECX_REG] & RDRAND_FLAG) != 0;
586 
587  if (cpuid0[EAX_REG] >= 7)
588  {
589  if (CpuId(7, 0, cpuid2))
590  {
591  g_hasRDSEED = (cpuid2[EBX_REG] & RDSEED_FLAG) != 0;
592  g_hasADX = (cpuid2[EBX_REG] & ADX_FLAG) != 0;
593  g_hasSHA = (cpuid2[EBX_REG] & SHA_FLAG) != 0;
594  g_hasAVX2 = (cpuid2[EBX_REG] & AVX2_FLAG) != 0;
595  }
596  }
597 
598  // Unconditionally disable RDRAND and RDSEED on AMD cpu's with family 15h or 16h.
599  // See Crypto++ Issue 924, https://github.com/weidai11/cryptopp/issues/924,
600  // Clear RDRAND CPUID bit on AMD family 15h/16h, https://lore.kernel.org/patchwork/patch/1115413/,
601  // and AMD CPUID Specification, https://www.amd.com/system/files/TechDocs/25481.pdf
602  {
603  CRYPTOPP_CONSTANT(FAMILY_BASE_FLAG = (0x0f << 8));
604  CRYPTOPP_CONSTANT(FAMILY_EXT_FLAG = (0xff << 20));
605 
606  word32 family = (cpuid1[0] & FAMILY_BASE_FLAG) >> 8;
607  if (family == 0xf)
608  family += (cpuid1[0] & FAMILY_EXT_FLAG) >> 20;
609  if (family == 0x15 || family == 0x16)
610  {
611  g_hasRDRAND = false;
612  g_hasRDSEED = false;
613  }
614  }
615  }
616  else if (IsVIA(cpuid0))
617  {
618  // Two bits: available and enabled
619  CRYPTOPP_CONSTANT( RNG_FLAGS = (0x3 << 2));
620  CRYPTOPP_CONSTANT( ACE_FLAGS = (0x3 << 6));
621  CRYPTOPP_CONSTANT(ACE2_FLAGS = (0x3 << 8));
622  CRYPTOPP_CONSTANT( PHE_FLAGS = (0x3 << 10));
623  CRYPTOPP_CONSTANT( PMM_FLAGS = (0x3 << 12));
624 
625  CpuId(0xC0000000, 0, cpuid2);
626  word32 extendedFeatures = cpuid2[0];
627 
628  if (extendedFeatures >= 0xC0000001)
629  {
630  CpuId(0xC0000001, 0, cpuid2);
631  g_hasPadlockRNG = (cpuid2[EDX_REG] & RNG_FLAGS) != 0;
632  g_hasPadlockACE = (cpuid2[EDX_REG] & ACE_FLAGS) != 0;
633  g_hasPadlockACE2 = (cpuid2[EDX_REG] & ACE2_FLAGS) != 0;
634  g_hasPadlockPHE = (cpuid2[EDX_REG] & PHE_FLAGS) != 0;
635  g_hasPadlockPMM = (cpuid2[EDX_REG] & PMM_FLAGS) != 0;
636  }
637 
638  if (extendedFeatures >= 0xC0000005)
639  {
640  CpuId(0xC0000005, 0, cpuid2);
641  g_cacheLineSize = GETBYTE(cpuid2[ECX_REG], 0);
642  }
643  }
644 
645  // Keep AVX2 in sync with OS support for AVX. AVX tests both
646  // cpu support and OS support, while AVX2 only tests cpu support.
647  g_hasAVX2 &= g_hasAVX;
648 
649 done:
650 
651 #if defined(_SC_LEVEL1_DCACHE_LINESIZE)
652  // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
653  // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
654  int cacheLineSize = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
655  if (g_cacheLineSize == 0 && cacheLineSize > 0)
656  g_cacheLineSize = cacheLineSize;
657 #endif
658 
659  if (g_cacheLineSize == 0)
660  g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
661 
662  *const_cast<volatile bool*>(&g_x86DetectionDone) = true;
663 }
664 
665 // *************************** ARM-32, Aarch32 and Aarch64 ***************************
666 
667 #elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8)
668 
669 bool CRYPTOPP_SECTION_INIT g_ArmDetectionDone = false;
670 bool CRYPTOPP_SECTION_INIT g_hasARMv7 = false;
671 bool CRYPTOPP_SECTION_INIT g_hasNEON = false;
672 bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
673 bool CRYPTOPP_SECTION_INIT g_hasCRC32 = false;
674 bool CRYPTOPP_SECTION_INIT g_hasAES = false;
675 bool CRYPTOPP_SECTION_INIT g_hasSHA1 = false;
676 bool CRYPTOPP_SECTION_INIT g_hasSHA2 = false;
677 bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
678 bool CRYPTOPP_SECTION_INIT g_hasSHA3 = false;
679 bool CRYPTOPP_SECTION_INIT g_hasSM3 = false;
680 bool CRYPTOPP_SECTION_INIT g_hasSM4 = false;
681 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
682 
683 // ARM does not have an unprivliged equivalent to CPUID on IA-32. We have to
684 // jump through some hoops to detect features on a wide array of platforms.
685 // Our strategy is two part. First, attempt to *Query* the OS for a feature,
686 // like using getauxval on Linux. If that fails, then *Probe* the cpu
687 // executing an instruction and an observe a SIGILL if unsupported. The probes
688 // are in source files where compilation options like -march=armv8-a+crc make
689 // intrinsics available. They are expensive when compared to a standard OS
690 // feature query. Always perform the feature query first. For Linux see
691 // http://sourceware.org/ml/libc-help/2017-08/msg00012.html
692 // Avoid probes on Apple platforms because Apple's signal handling for SIGILLs
693 // appears broken. We are trying to figure out a way to feature test without
694 // probes. Also see http://stackoverflow.com/a/11197770/608639 and
695 // http://gist.github.com/erkanyildiz/390a480f27e86f8cd6ba.
696 
697 extern bool CPU_ProbeARMv7();
698 extern bool CPU_ProbeNEON();
699 extern bool CPU_ProbeCRC32();
700 extern bool CPU_ProbeAES();
701 extern bool CPU_ProbeSHA1();
702 extern bool CPU_ProbeSHA256();
703 extern bool CPU_ProbeSHA512();
704 extern bool CPU_ProbeSHA3();
705 extern bool CPU_ProbeSM3();
706 extern bool CPU_ProbeSM4();
707 extern bool CPU_ProbePMULL();
708 
709 // https://github.com/torvalds/linux/blob/master/arch/arm/include/uapi/asm/hwcap.h
710 // https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
711 #ifndef HWCAP_ARMv7
712 # define HWCAP_ARMv7 (1 << 29)
713 #endif
714 #ifndef HWCAP_ASIMD
715 # define HWCAP_ASIMD (1 << 1)
716 #endif
717 #ifndef HWCAP_NEON
718 # define HWCAP_NEON (1 << 12)
719 #endif
720 #ifndef HWCAP_CRC32
721 # define HWCAP_CRC32 (1 << 7)
722 #endif
723 #ifndef HWCAP2_CRC32
724 # define HWCAP2_CRC32 (1 << 4)
725 #endif
726 #ifndef HWCAP_PMULL
727 # define HWCAP_PMULL (1 << 4)
728 #endif
729 #ifndef HWCAP2_PMULL
730 # define HWCAP2_PMULL (1 << 1)
731 #endif
732 #ifndef HWCAP_AES
733 # define HWCAP_AES (1 << 3)
734 #endif
735 #ifndef HWCAP2_AES
736 # define HWCAP2_AES (1 << 0)
737 #endif
738 #ifndef HWCAP_SHA1
739 # define HWCAP_SHA1 (1 << 5)
740 #endif
741 #ifndef HWCAP_SHA2
742 # define HWCAP_SHA2 (1 << 6)
743 #endif
744 #ifndef HWCAP2_SHA1
745 # define HWCAP2_SHA1 (1 << 2)
746 #endif
747 #ifndef HWCAP2_SHA2
748 # define HWCAP2_SHA2 (1 << 3)
749 #endif
750 #ifndef HWCAP_SHA3
751 # define HWCAP_SHA3 (1 << 17)
752 #endif
753 #ifndef HWCAP_SM3
754 # define HWCAP_SM3 (1 << 18)
755 #endif
756 #ifndef HWCAP_SM4
757 # define HWCAP_SM4 (1 << 19)
758 #endif
759 #ifndef HWCAP_SHA512
760 # define HWCAP_SHA512 (1 << 21)
761 #endif
762 
763 inline bool CPU_QueryARMv7()
764 {
765 #if defined(__ANDROID__) && defined(__arm__)
766  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
767  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0))
768  return true;
769 #elif defined(__linux__) && defined(__arm__)
770  if ((getauxval(AT_HWCAP) & HWCAP_ARMv7) != 0 ||
771  (getauxval(AT_HWCAP) & HWCAP_NEON) != 0)
772  return true;
773 #elif defined(__APPLE__) && defined(__arm__)
774  // Apple hardware is ARMv7 or above.
775  return true;
776 #endif
777  return false;
778 }
779 
780 inline bool CPU_QueryNEON()
781 {
782 #if defined(__ANDROID__) && defined(__aarch64__)
783  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
784  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_ASIMD) != 0))
785  return true;
786 #elif defined(__ANDROID__) && defined(__arm__)
787  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
788  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0))
789  return true;
790 #elif defined(__linux__) && defined(__aarch64__)
791  if ((getauxval(AT_HWCAP) & HWCAP_ASIMD) != 0)
792  return true;
793 #elif defined(__linux__) && defined(__aarch32__)
794  if ((getauxval(AT_HWCAP2) & HWCAP2_ASIMD) != 0)
795  return true;
796 #elif defined(__linux__) && defined(__arm__)
797  if ((getauxval(AT_HWCAP) & HWCAP_NEON) != 0)
798  return true;
799 #elif defined(__APPLE__) && defined(__aarch64__)
800  // Core feature set for Aarch32 and Aarch64.
801  return true;
802 #endif
803  return false;
804 }
805 
806 inline bool CPU_QueryCRC32()
807 {
808 #if defined(__ANDROID__) && defined(__aarch64__)
809  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
810  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_CRC32) != 0))
811  return true;
812 #elif defined(__ANDROID__) && defined(__aarch32__)
813  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
814  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_CRC32) != 0))
815  return true;
816 #elif defined(__linux__) && defined(__aarch64__)
817  if ((getauxval(AT_HWCAP) & HWCAP_CRC32) != 0)
818  return true;
819 #elif defined(__linux__) && defined(__aarch32__)
820  if ((getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0)
821  return true;
822 #elif defined(__APPLE__) && defined(__aarch64__)
823  // No compiler support. CRC intrinsics result in a failed compiled.
824  return false;
825 #endif
826  return false;
827 }
828 
829 inline bool CPU_QueryPMULL()
830 {
831 #if defined(__ANDROID__) && defined(__aarch64__)
832  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
833  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_PMULL) != 0))
834  return true;
835 #elif defined(__ANDROID__) && defined(__aarch32__)
836  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
837  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_PMULL) != 0))
838  return true;
839 #elif defined(__linux__) && defined(__aarch64__)
840  if ((getauxval(AT_HWCAP) & HWCAP_PMULL) != 0)
841  return true;
842 #elif defined(__linux__) && defined(__aarch32__)
843  if ((getauxval(AT_HWCAP2) & HWCAP2_PMULL) != 0)
844  return true;
845 #elif defined(__APPLE__) && defined(__aarch64__)
846  // No compiler support. PMULL intrinsics result in a failed compiled.
847  return false;
848 #endif
849  return false;
850 }
851 
852 inline bool CPU_QueryAES()
853 {
854 #if defined(__ANDROID__) && defined(__aarch64__)
855  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
856  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES) != 0))
857  return true;
858 #elif defined(__ANDROID__) && defined(__aarch32__)
859  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
860  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES) != 0))
861  return true;
862 #elif defined(__linux__) && defined(__aarch64__)
863  if ((getauxval(AT_HWCAP) & HWCAP_AES) != 0)
864  return true;
865 #elif defined(__linux__) && defined(__aarch32__)
866  if ((getauxval(AT_HWCAP2) & HWCAP2_AES) != 0)
867  return true;
868 #elif defined(__APPLE__) && defined(__aarch64__)
869  return IsAppleMachineARMv8();
870 #endif
871  return false;
872 }
873 
874 inline bool CPU_QuerySHA1()
875 {
876 #if defined(__ANDROID__) && defined(__aarch64__)
877  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
878  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA1) != 0))
879  return true;
880 #elif defined(__ANDROID__) && defined(__aarch32__)
881  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
882  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA1) != 0))
883  return true;
884 #elif defined(__linux__) && defined(__aarch64__)
885  if ((getauxval(AT_HWCAP) & HWCAP_SHA1) != 0)
886  return true;
887 #elif defined(__linux__) && defined(__aarch32__)
888  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA1) != 0)
889  return true;
890 #elif defined(__APPLE__) && defined(__aarch64__)
891  return IsAppleMachineARMv8();
892 #endif
893  return false;
894 }
895 
896 inline bool CPU_QuerySHA256()
897 {
898 #if defined(__ANDROID__) && defined(__aarch64__)
899  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
900  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA2) != 0))
901  return true;
902 #elif defined(__ANDROID__) && defined(__aarch32__)
903  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
904  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA2) != 0))
905  return true;
906 #elif defined(__linux__) && defined(__aarch64__)
907  if ((getauxval(AT_HWCAP) & HWCAP_SHA2) != 0)
908  return true;
909 #elif defined(__linux__) && defined(__aarch32__)
910  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA2) != 0)
911  return true;
912 #elif defined(__APPLE__) && defined(__aarch64__)
913  return IsAppleMachineARMv8();
914 #endif
915  return false;
916 }
917 
918 inline bool CPU_QuerySHA512()
919 {
920 // Some ARMv8.4 features are disabled at the moment
921 #if defined(__ANDROID__) && defined(__aarch64__) && 0
922  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
923  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA512) != 0))
924  return true;
925 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
926  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
927  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA512) != 0))
928  return true;
929 #elif defined(__linux__) && defined(__aarch64__)
930  if ((getauxval(AT_HWCAP) & HWCAP_SHA512) != 0)
931  return true;
932 #elif defined(__linux__) && defined(__aarch32__)
933  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA512) != 0)
934  return true;
935 #elif defined(__APPLE__) && defined(__aarch64__) && 0
936  return false;
937 #endif
938  return false;
939 }
940 
941 inline bool CPU_QuerySHA3()
942 {
943 // Some ARMv8.4 features are disabled at the moment
944 #if defined(__ANDROID__) && defined(__aarch64__) && 0
945  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
946  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA3) != 0))
947  return true;
948 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
949  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
950  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA3) != 0))
951  return true;
952 #elif defined(__linux__) && defined(__aarch64__)
953  if ((getauxval(AT_HWCAP) & HWCAP_SHA3) != 0)
954  return true;
955 #elif defined(__linux__) && defined(__aarch32__)
956  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA3) != 0)
957  return true;
958 #elif defined(__APPLE__) && defined(__aarch64__) && 0
959  return false;
960 #endif
961  return false;
962 }
963 
964 inline bool CPU_QuerySM3()
965 {
966 // Some ARMv8.4 features are disabled at the moment
967 #if defined(__ANDROID__) && defined(__aarch64__) && 0
968  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
969  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM3) != 0))
970  return true;
971 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
972  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
973  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM3) != 0))
974  return true;
975 #elif defined(__linux__) && defined(__aarch64__)
976  if ((getauxval(AT_HWCAP) & HWCAP_SM3) != 0)
977  return true;
978 #elif defined(__linux__) && defined(__aarch32__)
979  if ((getauxval(AT_HWCAP2) & HWCAP2_SM3) != 0)
980  return true;
981 #elif defined(__APPLE__) && defined(__aarch64__) && 0
982  return false;
983 #endif
984  return false;
985 }
986 
987 inline bool CPU_QuerySM4()
988 {
989 // Some ARMv8.4 features are disabled at the moment
990 #if defined(__ANDROID__) && defined(__aarch64__) && 0
991  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
992  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM4) != 0))
993  return true;
994 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
995  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
996  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM4) != 0))
997  return true;
998 #elif defined(__linux__) && defined(__aarch64__)
999  if ((getauxval(AT_HWCAP) & HWCAP_SM4) != 0)
1000  return true;
1001 #elif defined(__linux__) && defined(__aarch32__)
1002  if ((getauxval(AT_HWCAP2) & HWCAP2_SM4) != 0)
1003  return true;
1004 #elif defined(__APPLE__) && defined(__aarch64__) && 0
1005  return false;
1006 #endif
1007  return false;
1008 }
1009 
1010 void DetectArmFeatures()
1011 {
1012  // The CPU_ProbeXXX's return false for OSes which
1013  // can't tolerate SIGILL-based probes
1014  g_hasARMv7 = CPU_QueryARMv7() || CPU_ProbeARMv7();
1015  g_hasNEON = CPU_QueryNEON() || CPU_ProbeNEON();
1016  g_hasCRC32 = CPU_QueryCRC32() || CPU_ProbeCRC32();
1017  g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
1018  g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
1019  g_hasSHA1 = CPU_QuerySHA1() || CPU_ProbeSHA1();
1020  g_hasSHA2 = CPU_QuerySHA256() || CPU_ProbeSHA256();
1021  g_hasSHA512 = CPU_QuerySHA512(); // || CPU_ProbeSHA512();
1022  g_hasSHA3 = CPU_QuerySHA3(); // || CPU_ProbeSHA3();
1023  g_hasSM3 = CPU_QuerySM3(); // || CPU_ProbeSM3();
1024  g_hasSM4 = CPU_QuerySM4(); // || CPU_ProbeSM4();
1025 
1026 #if defined(_SC_LEVEL1_DCACHE_LINESIZE)
1027  // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
1028  // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
1029  int cacheLineSize = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
1030  if (cacheLineSize > 0)
1031  g_cacheLineSize = cacheLineSize;
1032 #endif
1033 
1034  if (g_cacheLineSize == 0)
1035  g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
1036 
1037  *const_cast<volatile bool*>(&g_ArmDetectionDone) = true;
1038 }
1039 
1040 // *************************** PowerPC and PowerPC64 ***************************
1041 
1042 #elif (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
1043 
1044 bool CRYPTOPP_SECTION_INIT g_PowerpcDetectionDone = false;
1045 bool CRYPTOPP_SECTION_INIT g_hasAltivec = false;
1046 bool CRYPTOPP_SECTION_INIT g_hasPower7 = false;
1047 bool CRYPTOPP_SECTION_INIT g_hasPower8 = false;
1048 bool CRYPTOPP_SECTION_INIT g_hasPower9 = false;
1049 bool CRYPTOPP_SECTION_INIT g_hasAES = false;
1050 bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
1051 bool CRYPTOPP_SECTION_INIT g_hasSHA256 = false;
1052 bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
1053 bool CRYPTOPP_SECTION_INIT g_hasDARN = false;
1054 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
1055 
1056 extern bool CPU_ProbeAltivec();
1057 extern bool CPU_ProbePower7();
1058 extern bool CPU_ProbePower8();
1059 extern bool CPU_ProbePower9();
1060 extern bool CPU_ProbeAES();
1061 extern bool CPU_ProbePMULL();
1062 extern bool CPU_ProbeSHA256();
1063 extern bool CPU_ProbeSHA512();
1064 extern bool CPU_ProbeDARN();
1065 
1066 // AIX defines. We used to just call __power_7_andup()
1067 // and friends but at Power9, too many compilers were
1068 // missing __power_9_andup(). Instead we switched to
1069 // a pattern similar to OpenSSL caps testing.
1070 #ifndef __power_6_andup
1071 # define __power_6_andup() __power_set(0xffffffffU<<14)
1072 #endif
1073 #ifndef __power_7_andup
1074 # define __power_7_andup() __power_set(0xffffffffU<<15)
1075 #endif
1076 #ifndef __power_8_andup
1077 # define __power_8_andup() __power_set(0xffffffffU<<16)
1078 #endif
1079 #ifndef __power_9_andup
1080 # define __power_9_andup() __power_set(0xffffffffU<<17)
1081 #endif
1082 
1083 // AIX first supported Altivec at Power6, though it
1084 // was available much earlier for other vendors.
1085 inline bool CPU_QueryAltivec()
1086 {
1087 #if defined(__linux__) && defined(PPC_FEATURE_HAS_ALTIVEC)
1088  if ((getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC) != 0)
1089  return true;
1090 #elif defined(_AIX)
1091  if (__power_6_andup() != 0)
1092  return true;
1093 #elif defined(__APPLE__) && defined(__POWERPC__)
1094  unsigned int unused, arch;
1095  GetAppleMachineInfo(unused, unused, arch);
1096  return arch == AppleMachineInfo::PowerMac;
1097 #endif
1098  return false;
1099 }
1100 
1101 inline bool CPU_QueryPower7()
1102 {
1103  // Power7 and ISA 2.06
1104 #if defined(__linux__) && defined(PPC_FEATURE_ARCH_2_06)
1105  if ((getauxval(AT_HWCAP) & PPC_FEATURE_ARCH_2_06) != 0)
1106  return true;
1107 #elif defined(_AIX)
1108  if (__power_7_andup() != 0)
1109  return true;
1110 #endif
1111  return false;
1112 }
1113 
1114 inline bool CPU_QueryPower8()
1115 {
1116  // Power8 and ISA 2.07 provide in-core crypto.
1117 #if defined(__linux__) && defined(PPC_FEATURE2_ARCH_2_07)
1118  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07) != 0)
1119  return true;
1120 #elif defined(_AIX)
1121  if (__power_8_andup() != 0)
1122  return true;
1123 #endif
1124  return false;
1125 }
1126 
1127 inline bool CPU_QueryPower9()
1128 {
1129  // Power9 and ISA 3.0.
1130 #if defined(__linux__) && defined(PPC_FEATURE2_ARCH_3_00)
1131  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0)
1132  return true;
1133 #elif defined(_AIX)
1134  if (__power_9_andup() != 0)
1135  return true;
1136 #endif
1137  return false;
1138 }
1139 
1140 inline bool CPU_QueryAES()
1141 {
1142  // Power8 and ISA 2.07 provide in-core crypto. Glibc
1143  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
1144 #if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO)
1145  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
1146  return true;
1147 #elif defined(_AIX)
1148  if (__power_8_andup() != 0)
1149  return true;
1150 #endif
1151  return false;
1152 }
1153 
1154 inline bool CPU_QueryPMULL()
1155 {
1156  // Power8 and ISA 2.07 provide in-core crypto. Glibc
1157  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
1158 #if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO)
1159  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
1160  return true;
1161 #elif defined(_AIX)
1162  if (__power_8_andup() != 0)
1163  return true;
1164 #endif
1165  return false;
1166 }
1167 
1168 inline bool CPU_QuerySHA256()
1169 {
1170  // Power8 and ISA 2.07 provide in-core crypto. Glibc
1171  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
1172 #if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO)
1173  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
1174  return true;
1175 #elif defined(_AIX)
1176  if (__power_8_andup() != 0)
1177  return true;
1178 #endif
1179  return false;
1180 }
1181 inline bool CPU_QuerySHA512()
1182 {
1183  // Power8 and ISA 2.07 provide in-core crypto. Glibc
1184  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
1185 #if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO)
1186  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
1187  return true;
1188 #elif defined(_AIX)
1189  if (__power_8_andup() != 0)
1190  return true;
1191 #endif
1192  return false;
1193 }
1194 
1195 // Power9 random number generator
1196 inline bool CPU_QueryDARN()
1197 {
1198  // Power9 and ISA 3.0 provide DARN.
1199 #if defined(__linux__) && defined(PPC_FEATURE2_ARCH_3_00)
1200  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0)
1201  return true;
1202 #elif defined(_AIX)
1203  if (__power_9_andup() != 0)
1204  return true;
1205 #endif
1206  return false;
1207 }
1208 
1209 void DetectPowerpcFeatures()
1210 {
1211  // The CPU_ProbeXXX's return false for OSes which
1212  // can't tolerate SIGILL-based probes, like Apple
1213  g_hasAltivec = CPU_QueryAltivec() || CPU_ProbeAltivec();
1214  g_hasPower7 = CPU_QueryPower7() || CPU_ProbePower7();
1215  g_hasPower8 = CPU_QueryPower8() || CPU_ProbePower8();
1216  g_hasPower9 = CPU_QueryPower9() || CPU_ProbePower9();
1217  g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
1218  g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
1219  g_hasSHA256 = CPU_QuerySHA256() || CPU_ProbeSHA256();
1220  g_hasSHA512 = CPU_QuerySHA512() || CPU_ProbeSHA512();
1221  g_hasDARN = CPU_QueryDARN() || CPU_ProbeDARN();
1222 
1223 #if defined(_AIX) && defined(SC_L1C_DLS)
1224  // /usr/include/sys/systemcfg.h
1225  int cacheLineSize = getsystemcfg(SC_L1C_DLS);
1226  if (cacheLineSize > 0)
1227  g_cacheLineSize = cacheLineSize;
1228 #elif defined(_SC_LEVEL1_DCACHE_LINESIZE)
1229  // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
1230  // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
1231  int cacheLineSize = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
1232  if (cacheLineSize > 0)
1233  g_cacheLineSize = cacheLineSize;
1234 #endif
1235 
1236  if (g_cacheLineSize == 0)
1237  g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
1238 
1239  *const_cast<volatile bool*>(&g_PowerpcDetectionDone) = true;
1240 }
1241 
1242 #endif
1243 NAMESPACE_END
1244 
1245 // *************************** C++ Static Initialization ***************************
1246 
1247 ANONYMOUS_NAMESPACE_BEGIN
1248 
1249 class InitCpu
1250 {
1251 public:
1252  InitCpu()
1253  {
1254 #if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
1255  CryptoPP::DetectX86Features();
1256 #elif CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8
1257  CryptoPP::DetectArmFeatures();
1258 #elif CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64
1259  CryptoPP::DetectPowerpcFeatures();
1260 #endif
1261  }
1262 };
1263 
1264 // This is not really needed because HasSSE() and friends can dynamically initialize.
1265 // Everything depends on CPU features so we initialize it once at load time.
1266 // Dynamic initialization will be used if init priorities are not available.
1267 
1268 #if HAVE_GCC_INIT_PRIORITY
1269  const InitCpu s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 10))) = InitCpu();
1270 #elif HAVE_MSC_INIT_PRIORITY
1271  #pragma warning(disable: 4075)
1272  #pragma init_seg(".CRT$XCU")
1273  const InitCpu s_init;
1274  #pragma warning(default: 4075)
1275 #elif HAVE_XLC_INIT_PRIORITY
1276  // XLC needs constant, not a define
1277  #pragma priority(270)
1278  const InitCpu s_init;
1279 #else
1280  const InitCpu s_init;
1281 #endif
1282 
1283 ANONYMOUS_NAMESPACE_END
1284 
1285 #endif // CRYPTOPP_IMPORTS
Singleton::Ref
const T & Ref(...) const
Return a reference to the inner Singleton object.
Definition: misc.h:325
Name::Version
const char * Version()
int
Definition: argnames.h:18
Singleton
Restricts the instantiation of a class to one static object without locks.
Definition: misc.h:305
pch.h
Precompiled header file.
misc.h
Utility functions for the Crypto++ library.
cpu.h
Functions for CPU features and intrinsics.
stdcpp.h
Common C++ header files.
CryptoPP
Crypto++ library namespace.
config.h
Library configuration file.