Botan  2.4.0
Crypto and TLS for C++11
cpuid_ppc.cpp
Go to the documentation of this file.
1 /*
2 * Runtime CPU detection for POWER/PowerPC
3 * (C) 2009,2010,2013,2017 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/cpuid.h>
9 #include <botan/internal/os_utils.h>
10 
11 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
12 
13 /*
14 * On Darwin and OpenBSD ppc, use sysctl to detect AltiVec
15 */
16 #if defined(BOTAN_TARGET_OS_IS_DARWIN)
17  #include <sys/sysctl.h>
18 #elif defined(BOTAN_TARGET_OS_IS_OPENBSD)
19  #include <sys/param.h>
20  #include <sys/sysctl.h>
21  #include <machine/cpu.h>
22 #endif
23 
24 #endif
25 
26 namespace Botan {
27 
28 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
29 
30 /*
31 * PowerPC specific block: check for AltiVec using either
32 * sysctl or by reading processor version number register.
33 */
34 uint64_t CPUID::detect_cpu_features(size_t* cache_line_size)
35  {
36 #if defined(BOTAN_TARGET_OS_IS_DARWIN) || defined(BOTAN_TARGET_OS_IS_OPENBSD)
37  // On Darwin/OS X and OpenBSD, use sysctl
38 
39  int sels[2] = {
40 #if defined(BOTAN_TARGET_OS_IS_OPENBSD)
41  CTL_MACHDEP, CPU_ALTIVEC
42 #else
43  CTL_HW, HW_VECTORUNIT
44 #endif
45  };
46 
47  int vector_type = 0;
48  size_t length = sizeof(vector_type);
49  int error = ::sysctl(sels, 2, &vector_type, &length, NULL, 0);
50 
51  if(error == 0 && vector_type > 0)
52  return CPUID::CPUID_ALTIVEC_BIT;
53 
54 #else
55 
56  /*
57  On PowerPC, MSR 287 is PVR, the Processor Version Number
58  Normally it is only accessible to ring 0, but Linux and NetBSD
59  (others, too, maybe?) will trap and emulate it for us.
60  */
61 
62  int pvr = OS::run_cpu_instruction_probe([]() -> int {
63  uint32_t pvr = 0;
64  asm volatile("mfspr %0, 287" : "=r" (pvr));
65  // Top 16 bits suffice to identify the model
66  return static_cast<int>(pvr >> 16);
67  });
68 
69  if(pvr > 0)
70  {
71  const uint16_t ALTIVEC_PVR[] = {
72  0x003E, // IBM POWER6
73  0x003F, // IBM POWER7
74  0x004A, // IBM POWER7p
75  0x004D, // IBM POWER8
76  0x004B, // IBM POWER8E
77  0x000C, // G4-7400
78  0x0039, // G5 970
79  0x003C, // G5 970FX
80  0x0044, // G5 970MP
81  0x0070, // Cell PPU
82  0, // end
83  };
84 
85  for(size_t i = 0; ALTIVEC_PVR[i]; ++i)
86  {
87  if(pvr == ALTIVEC_PVR[i])
88  return CPUID::CPUID_ALTIVEC_BIT;
89  }
90 
91  return 0;
92  }
93 
94  // TODO try direct instruction probing
95 
96 #endif
97 
98  return 0;
99  }
100 
101 #endif
102 
103 }
int BOTAN_TEST_API run_cpu_instruction_probe(std::function< int()> probe_fn)
Definition: os_utils.cpp:372
Definition: alg_id.cpp:13