2
* Runtime CPU detection for POWER/PowerPC
3
* (C) 2009,2010,2013,2017 Jack Lloyd
5
* Botan is released under the Simplified BSD License (see license.txt)
8
#include <botan/cpuid.h>
9
#include <botan/internal/os_utils.h>
11
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
14
* On Darwin and OpenBSD ppc, use sysctl to detect AltiVec
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>
28
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
31
* PowerPC specific block: check for AltiVec using either
32
* sysctl or by reading processor version number register.
34
uint64_t CPUID::detect_cpu_features(size_t* cache_line_size)
36
#if defined(BOTAN_TARGET_OS_IS_DARWIN) || defined(BOTAN_TARGET_OS_IS_OPENBSD)
37
// On Darwin/OS X and OpenBSD, use sysctl
40
#if defined(BOTAN_TARGET_OS_IS_OPENBSD)
41
CTL_MACHDEP, CPU_ALTIVEC
48
size_t length = sizeof(vector_type);
49
int error = ::sysctl(sels, 2, &vector_type, &length, NULL, 0);
51
if(error == 0 && vector_type > 0)
52
return CPUID::CPUID_ALTIVEC_BIT;
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.
62
int pvr = OS::run_cpu_instruction_probe([]() -> int {
64
asm volatile("mfspr %0, 287" : "=r" (pvr));
65
// Top 16 bits suffice to identify the model
66
return static_cast<int>(pvr >> 16);
71
const uint16_t ALTIVEC_PVR[] = {
74
0x004A, // IBM POWER7p
76
0x004B, // IBM POWER8E
85
for(size_t i = 0; ALTIVEC_PVR[i]; ++i)
87
if(pvr == ALTIVEC_PVR[i])
88
return CPUID::CPUID_ALTIVEC_BIT;
94
// TODO try direct instruction probing