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