1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "base/cpu.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <limits.h>
8*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
9*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
10*635a8641SAndroid Build Coastguard Worker #include <string.h>
11*635a8641SAndroid Build Coastguard Worker
12*635a8641SAndroid Build Coastguard Worker #include <algorithm>
13*635a8641SAndroid Build Coastguard Worker #include <utility>
14*635a8641SAndroid Build Coastguard Worker
15*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
16*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
17*635a8641SAndroid Build Coastguard Worker
18*635a8641SAndroid Build Coastguard Worker #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
19*635a8641SAndroid Build Coastguard Worker #include "base/files/file_util.h"
20*635a8641SAndroid Build Coastguard Worker #endif
21*635a8641SAndroid Build Coastguard Worker
22*635a8641SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_FAMILY)
23*635a8641SAndroid Build Coastguard Worker #if defined(COMPILER_MSVC)
24*635a8641SAndroid Build Coastguard Worker #include <intrin.h>
25*635a8641SAndroid Build Coastguard Worker #include <immintrin.h> // For _xgetbv()
26*635a8641SAndroid Build Coastguard Worker #endif
27*635a8641SAndroid Build Coastguard Worker #endif
28*635a8641SAndroid Build Coastguard Worker
29*635a8641SAndroid Build Coastguard Worker namespace base {
30*635a8641SAndroid Build Coastguard Worker
CPU()31*635a8641SAndroid Build Coastguard Worker CPU::CPU()
32*635a8641SAndroid Build Coastguard Worker : signature_(0),
33*635a8641SAndroid Build Coastguard Worker type_(0),
34*635a8641SAndroid Build Coastguard Worker family_(0),
35*635a8641SAndroid Build Coastguard Worker model_(0),
36*635a8641SAndroid Build Coastguard Worker stepping_(0),
37*635a8641SAndroid Build Coastguard Worker ext_model_(0),
38*635a8641SAndroid Build Coastguard Worker ext_family_(0),
39*635a8641SAndroid Build Coastguard Worker has_mmx_(false),
40*635a8641SAndroid Build Coastguard Worker has_sse_(false),
41*635a8641SAndroid Build Coastguard Worker has_sse2_(false),
42*635a8641SAndroid Build Coastguard Worker has_sse3_(false),
43*635a8641SAndroid Build Coastguard Worker has_ssse3_(false),
44*635a8641SAndroid Build Coastguard Worker has_sse41_(false),
45*635a8641SAndroid Build Coastguard Worker has_sse42_(false),
46*635a8641SAndroid Build Coastguard Worker has_popcnt_(false),
47*635a8641SAndroid Build Coastguard Worker has_avx_(false),
48*635a8641SAndroid Build Coastguard Worker has_avx2_(false),
49*635a8641SAndroid Build Coastguard Worker has_aesni_(false),
50*635a8641SAndroid Build Coastguard Worker has_non_stop_time_stamp_counter_(false),
51*635a8641SAndroid Build Coastguard Worker cpu_vendor_("unknown") {
52*635a8641SAndroid Build Coastguard Worker Initialize();
53*635a8641SAndroid Build Coastguard Worker }
54*635a8641SAndroid Build Coastguard Worker
55*635a8641SAndroid Build Coastguard Worker namespace {
56*635a8641SAndroid Build Coastguard Worker
57*635a8641SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_FAMILY)
58*635a8641SAndroid Build Coastguard Worker #if !defined(COMPILER_MSVC)
59*635a8641SAndroid Build Coastguard Worker
60*635a8641SAndroid Build Coastguard Worker #if defined(__pic__) && defined(__i386__)
61*635a8641SAndroid Build Coastguard Worker
__cpuid(int cpu_info[4],int info_type)62*635a8641SAndroid Build Coastguard Worker void __cpuid(int cpu_info[4], int info_type) {
63*635a8641SAndroid Build Coastguard Worker __asm__ volatile(
64*635a8641SAndroid Build Coastguard Worker "mov %%ebx, %%edi\n"
65*635a8641SAndroid Build Coastguard Worker "cpuid\n"
66*635a8641SAndroid Build Coastguard Worker "xchg %%edi, %%ebx\n"
67*635a8641SAndroid Build Coastguard Worker : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]),
68*635a8641SAndroid Build Coastguard Worker "=d"(cpu_info[3])
69*635a8641SAndroid Build Coastguard Worker : "a"(info_type), "c"(0));
70*635a8641SAndroid Build Coastguard Worker }
71*635a8641SAndroid Build Coastguard Worker
72*635a8641SAndroid Build Coastguard Worker #else
73*635a8641SAndroid Build Coastguard Worker
74*635a8641SAndroid Build Coastguard Worker void __cpuid(int cpu_info[4], int info_type) {
75*635a8641SAndroid Build Coastguard Worker __asm__ volatile("cpuid\n"
76*635a8641SAndroid Build Coastguard Worker : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
77*635a8641SAndroid Build Coastguard Worker "=d"(cpu_info[3])
78*635a8641SAndroid Build Coastguard Worker : "a"(info_type), "c"(0));
79*635a8641SAndroid Build Coastguard Worker }
80*635a8641SAndroid Build Coastguard Worker
81*635a8641SAndroid Build Coastguard Worker #endif
82*635a8641SAndroid Build Coastguard Worker
83*635a8641SAndroid Build Coastguard Worker // _xgetbv returns the value of an Intel Extended Control Register (XCR).
84*635a8641SAndroid Build Coastguard Worker // Currently only XCR0 is defined by Intel so |xcr| should always be zero.
_xgetbv(uint32_t xcr)85*635a8641SAndroid Build Coastguard Worker uint64_t _xgetbv(uint32_t xcr) {
86*635a8641SAndroid Build Coastguard Worker uint32_t eax, edx;
87*635a8641SAndroid Build Coastguard Worker
88*635a8641SAndroid Build Coastguard Worker __asm__ volatile (
89*635a8641SAndroid Build Coastguard Worker "xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr));
90*635a8641SAndroid Build Coastguard Worker return (static_cast<uint64_t>(edx) << 32) | eax;
91*635a8641SAndroid Build Coastguard Worker }
92*635a8641SAndroid Build Coastguard Worker
93*635a8641SAndroid Build Coastguard Worker #endif // !defined(COMPILER_MSVC)
94*635a8641SAndroid Build Coastguard Worker #endif // ARCH_CPU_X86_FAMILY
95*635a8641SAndroid Build Coastguard Worker
96*635a8641SAndroid Build Coastguard Worker #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
CpuInfoBrand()97*635a8641SAndroid Build Coastguard Worker std::string* CpuInfoBrand() {
98*635a8641SAndroid Build Coastguard Worker static std::string* brand = []() {
99*635a8641SAndroid Build Coastguard Worker // This function finds the value from /proc/cpuinfo under the key "model
100*635a8641SAndroid Build Coastguard Worker // name" or "Processor". "model name" is used in Linux 3.8 and later (3.7
101*635a8641SAndroid Build Coastguard Worker // and later for arm64) and is shown once per CPU. "Processor" is used in
102*635a8641SAndroid Build Coastguard Worker // earler versions and is shown only once at the top of /proc/cpuinfo
103*635a8641SAndroid Build Coastguard Worker // regardless of the number CPUs.
104*635a8641SAndroid Build Coastguard Worker const char kModelNamePrefix[] = "model name\t: ";
105*635a8641SAndroid Build Coastguard Worker const char kProcessorPrefix[] = "Processor\t: ";
106*635a8641SAndroid Build Coastguard Worker
107*635a8641SAndroid Build Coastguard Worker std::string contents;
108*635a8641SAndroid Build Coastguard Worker ReadFileToString(FilePath("/proc/cpuinfo"), &contents);
109*635a8641SAndroid Build Coastguard Worker DCHECK(!contents.empty());
110*635a8641SAndroid Build Coastguard Worker
111*635a8641SAndroid Build Coastguard Worker std::istringstream iss(contents);
112*635a8641SAndroid Build Coastguard Worker std::string line;
113*635a8641SAndroid Build Coastguard Worker while (std::getline(iss, line)) {
114*635a8641SAndroid Build Coastguard Worker if (line.compare(0, strlen(kModelNamePrefix), kModelNamePrefix) == 0)
115*635a8641SAndroid Build Coastguard Worker return new std::string(line.substr(strlen(kModelNamePrefix)));
116*635a8641SAndroid Build Coastguard Worker if (line.compare(0, strlen(kProcessorPrefix), kProcessorPrefix) == 0)
117*635a8641SAndroid Build Coastguard Worker return new std::string(line.substr(strlen(kProcessorPrefix)));
118*635a8641SAndroid Build Coastguard Worker }
119*635a8641SAndroid Build Coastguard Worker
120*635a8641SAndroid Build Coastguard Worker return new std::string();
121*635a8641SAndroid Build Coastguard Worker }();
122*635a8641SAndroid Build Coastguard Worker
123*635a8641SAndroid Build Coastguard Worker return brand;
124*635a8641SAndroid Build Coastguard Worker }
125*635a8641SAndroid Build Coastguard Worker #endif // defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) ||
126*635a8641SAndroid Build Coastguard Worker // defined(OS_LINUX))
127*635a8641SAndroid Build Coastguard Worker
128*635a8641SAndroid Build Coastguard Worker } // namespace
129*635a8641SAndroid Build Coastguard Worker
Initialize()130*635a8641SAndroid Build Coastguard Worker void CPU::Initialize() {
131*635a8641SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_FAMILY)
132*635a8641SAndroid Build Coastguard Worker int cpu_info[4] = {-1};
133*635a8641SAndroid Build Coastguard Worker // This array is used to temporarily hold the vendor name and then the brand
134*635a8641SAndroid Build Coastguard Worker // name. Thus it has to be big enough for both use cases. There are
135*635a8641SAndroid Build Coastguard Worker // static_asserts below for each of the use cases to make sure this array is
136*635a8641SAndroid Build Coastguard Worker // big enough.
137*635a8641SAndroid Build Coastguard Worker char cpu_string[sizeof(cpu_info) * 3 + 1];
138*635a8641SAndroid Build Coastguard Worker
139*635a8641SAndroid Build Coastguard Worker // __cpuid with an InfoType argument of 0 returns the number of
140*635a8641SAndroid Build Coastguard Worker // valid Ids in CPUInfo[0] and the CPU identification string in
141*635a8641SAndroid Build Coastguard Worker // the other three array elements. The CPU identification string is
142*635a8641SAndroid Build Coastguard Worker // not in linear order. The code below arranges the information
143*635a8641SAndroid Build Coastguard Worker // in a human readable form. The human readable order is CPUInfo[1] |
144*635a8641SAndroid Build Coastguard Worker // CPUInfo[3] | CPUInfo[2]. CPUInfo[2] and CPUInfo[3] are swapped
145*635a8641SAndroid Build Coastguard Worker // before using memcpy() to copy these three array elements to |cpu_string|.
146*635a8641SAndroid Build Coastguard Worker __cpuid(cpu_info, 0);
147*635a8641SAndroid Build Coastguard Worker int num_ids = cpu_info[0];
148*635a8641SAndroid Build Coastguard Worker std::swap(cpu_info[2], cpu_info[3]);
149*635a8641SAndroid Build Coastguard Worker static constexpr size_t kVendorNameSize = 3 * sizeof(cpu_info[1]);
150*635a8641SAndroid Build Coastguard Worker static_assert(kVendorNameSize < arraysize(cpu_string),
151*635a8641SAndroid Build Coastguard Worker "cpu_string too small");
152*635a8641SAndroid Build Coastguard Worker memcpy(cpu_string, &cpu_info[1], kVendorNameSize);
153*635a8641SAndroid Build Coastguard Worker cpu_string[kVendorNameSize] = '\0';
154*635a8641SAndroid Build Coastguard Worker cpu_vendor_ = cpu_string;
155*635a8641SAndroid Build Coastguard Worker
156*635a8641SAndroid Build Coastguard Worker // Interpret CPU feature information.
157*635a8641SAndroid Build Coastguard Worker if (num_ids > 0) {
158*635a8641SAndroid Build Coastguard Worker int cpu_info7[4] = {0};
159*635a8641SAndroid Build Coastguard Worker __cpuid(cpu_info, 1);
160*635a8641SAndroid Build Coastguard Worker if (num_ids >= 7) {
161*635a8641SAndroid Build Coastguard Worker __cpuid(cpu_info7, 7);
162*635a8641SAndroid Build Coastguard Worker }
163*635a8641SAndroid Build Coastguard Worker signature_ = cpu_info[0];
164*635a8641SAndroid Build Coastguard Worker stepping_ = cpu_info[0] & 0xf;
165*635a8641SAndroid Build Coastguard Worker model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0);
166*635a8641SAndroid Build Coastguard Worker family_ = (cpu_info[0] >> 8) & 0xf;
167*635a8641SAndroid Build Coastguard Worker type_ = (cpu_info[0] >> 12) & 0x3;
168*635a8641SAndroid Build Coastguard Worker ext_model_ = (cpu_info[0] >> 16) & 0xf;
169*635a8641SAndroid Build Coastguard Worker ext_family_ = (cpu_info[0] >> 20) & 0xff;
170*635a8641SAndroid Build Coastguard Worker has_mmx_ = (cpu_info[3] & 0x00800000) != 0;
171*635a8641SAndroid Build Coastguard Worker has_sse_ = (cpu_info[3] & 0x02000000) != 0;
172*635a8641SAndroid Build Coastguard Worker has_sse2_ = (cpu_info[3] & 0x04000000) != 0;
173*635a8641SAndroid Build Coastguard Worker has_sse3_ = (cpu_info[2] & 0x00000001) != 0;
174*635a8641SAndroid Build Coastguard Worker has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
175*635a8641SAndroid Build Coastguard Worker has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
176*635a8641SAndroid Build Coastguard Worker has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
177*635a8641SAndroid Build Coastguard Worker has_popcnt_ = (cpu_info[2] & 0x00800000) != 0;
178*635a8641SAndroid Build Coastguard Worker
179*635a8641SAndroid Build Coastguard Worker // AVX instructions will generate an illegal instruction exception unless
180*635a8641SAndroid Build Coastguard Worker // a) they are supported by the CPU,
181*635a8641SAndroid Build Coastguard Worker // b) XSAVE is supported by the CPU and
182*635a8641SAndroid Build Coastguard Worker // c) XSAVE is enabled by the kernel.
183*635a8641SAndroid Build Coastguard Worker // See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
184*635a8641SAndroid Build Coastguard Worker //
185*635a8641SAndroid Build Coastguard Worker // In addition, we have observed some crashes with the xgetbv instruction
186*635a8641SAndroid Build Coastguard Worker // even after following Intel's example code. (See crbug.com/375968.)
187*635a8641SAndroid Build Coastguard Worker // Because of that, we also test the XSAVE bit because its description in
188*635a8641SAndroid Build Coastguard Worker // the CPUID documentation suggests that it signals xgetbv support.
189*635a8641SAndroid Build Coastguard Worker has_avx_ =
190*635a8641SAndroid Build Coastguard Worker (cpu_info[2] & 0x10000000) != 0 &&
191*635a8641SAndroid Build Coastguard Worker (cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
192*635a8641SAndroid Build Coastguard Worker (cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
193*635a8641SAndroid Build Coastguard Worker (_xgetbv(0) & 6) == 6 /* XSAVE enabled by kernel */;
194*635a8641SAndroid Build Coastguard Worker has_aesni_ = (cpu_info[2] & 0x02000000) != 0;
195*635a8641SAndroid Build Coastguard Worker has_avx2_ = has_avx_ && (cpu_info7[1] & 0x00000020) != 0;
196*635a8641SAndroid Build Coastguard Worker }
197*635a8641SAndroid Build Coastguard Worker
198*635a8641SAndroid Build Coastguard Worker // Get the brand string of the cpu.
199*635a8641SAndroid Build Coastguard Worker __cpuid(cpu_info, 0x80000000);
200*635a8641SAndroid Build Coastguard Worker const int max_parameter = cpu_info[0];
201*635a8641SAndroid Build Coastguard Worker
202*635a8641SAndroid Build Coastguard Worker static constexpr int kParameterStart = 0x80000002;
203*635a8641SAndroid Build Coastguard Worker static constexpr int kParameterEnd = 0x80000004;
204*635a8641SAndroid Build Coastguard Worker static constexpr int kParameterSize = kParameterEnd - kParameterStart + 1;
205*635a8641SAndroid Build Coastguard Worker static_assert(kParameterSize * sizeof(cpu_info) + 1 == arraysize(cpu_string),
206*635a8641SAndroid Build Coastguard Worker "cpu_string has wrong size");
207*635a8641SAndroid Build Coastguard Worker
208*635a8641SAndroid Build Coastguard Worker if (max_parameter >= kParameterEnd) {
209*635a8641SAndroid Build Coastguard Worker size_t i = 0;
210*635a8641SAndroid Build Coastguard Worker for (int parameter = kParameterStart; parameter <= kParameterEnd;
211*635a8641SAndroid Build Coastguard Worker ++parameter) {
212*635a8641SAndroid Build Coastguard Worker __cpuid(cpu_info, parameter);
213*635a8641SAndroid Build Coastguard Worker memcpy(&cpu_string[i], cpu_info, sizeof(cpu_info));
214*635a8641SAndroid Build Coastguard Worker i += sizeof(cpu_info);
215*635a8641SAndroid Build Coastguard Worker }
216*635a8641SAndroid Build Coastguard Worker cpu_string[i] = '\0';
217*635a8641SAndroid Build Coastguard Worker cpu_brand_ = cpu_string;
218*635a8641SAndroid Build Coastguard Worker }
219*635a8641SAndroid Build Coastguard Worker
220*635a8641SAndroid Build Coastguard Worker static constexpr int kParameterContainingNonStopTimeStampCounter = 0x80000007;
221*635a8641SAndroid Build Coastguard Worker if (max_parameter >= kParameterContainingNonStopTimeStampCounter) {
222*635a8641SAndroid Build Coastguard Worker __cpuid(cpu_info, kParameterContainingNonStopTimeStampCounter);
223*635a8641SAndroid Build Coastguard Worker has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0;
224*635a8641SAndroid Build Coastguard Worker }
225*635a8641SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
226*635a8641SAndroid Build Coastguard Worker cpu_brand_ = *CpuInfoBrand();
227*635a8641SAndroid Build Coastguard Worker #endif
228*635a8641SAndroid Build Coastguard Worker }
229*635a8641SAndroid Build Coastguard Worker
GetIntelMicroArchitecture() const230*635a8641SAndroid Build Coastguard Worker CPU::IntelMicroArchitecture CPU::GetIntelMicroArchitecture() const {
231*635a8641SAndroid Build Coastguard Worker if (has_avx2()) return AVX2;
232*635a8641SAndroid Build Coastguard Worker if (has_avx()) return AVX;
233*635a8641SAndroid Build Coastguard Worker if (has_sse42()) return SSE42;
234*635a8641SAndroid Build Coastguard Worker if (has_sse41()) return SSE41;
235*635a8641SAndroid Build Coastguard Worker if (has_ssse3()) return SSSE3;
236*635a8641SAndroid Build Coastguard Worker if (has_sse3()) return SSE3;
237*635a8641SAndroid Build Coastguard Worker if (has_sse2()) return SSE2;
238*635a8641SAndroid Build Coastguard Worker if (has_sse()) return SSE;
239*635a8641SAndroid Build Coastguard Worker return PENTIUM;
240*635a8641SAndroid Build Coastguard Worker }
241*635a8641SAndroid Build Coastguard Worker
242*635a8641SAndroid Build Coastguard Worker } // namespace base
243