15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/cpu.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/basictypes.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/file_util.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/lazy_instance.h"
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ARCH_CPU_X86_FAMILY)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_MSC_VER)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <intrin.h>
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <immintrin.h>  // For _xgetbv()
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CPU::CPU()
29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  : signature_(0),
30ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    type_(0),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    family_(0),
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model_(0),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stepping_(0),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_model_(0),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_family_(0),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_mmx_(false),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_sse_(false),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_sse2_(false),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_sse3_(false),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_ssse3_(false),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_sse41_(false),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_sse42_(false),
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    has_avx_(false),
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    has_avx_hardware_(false),
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    has_aesni_(false),
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    has_non_stop_time_stamp_counter_(false),
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cpu_vendor_("unknown") {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace {
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ARCH_CPU_X86_FAMILY)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef _MSC_VER
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__pic__) && defined(__i386__)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void __cpuid(int cpu_info[4], int info_type) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __asm__ volatile (
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "mov %%ebx, %%edi\n"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "cpuid\n"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "xchg %%edi, %%ebx\n"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : "a"(info_type)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void __cpuid(int cpu_info[4], int info_type) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __asm__ volatile (
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "cpuid \n\t"
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : "a"(info_type)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// _xgetbv returns the value of an Intel Extended Control Register (XCR).
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Currently only XCR0 is defined by Intel so |xcr| should always be zero.
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)uint64 _xgetbv(uint32 xcr) {
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  uint32 eax, edx;
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  __asm__ volatile ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (xcr));
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return (static_cast<uint64>(edx) << 32) | eax;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif  // !_MSC_VER
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // ARCH_CPU_X86_FAMILY
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Returns the string found in /proc/cpuinfo under the key "model name" or
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// "Processor". "model name" is used in Linux 3.8 and later (3.7 and later for
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// arm64) and is shown once per CPU. "Processor" is used in earler versions and
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// is shown only once at the top of /proc/cpuinfo regardless of the number CPUs.
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustd::string ParseCpuInfo() {
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const char kModelNamePrefix[] = "model name\t: ";
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const char kProcessorPrefix[] = "Processor\t: ";
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string contents;
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ReadFileToString(FilePath("/proc/cpuinfo"), &contents);
1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(!contents.empty());
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string cpu_brand;
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!contents.empty()) {
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    std::istringstream iss(contents);
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    std::string line;
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    while (std::getline(iss, line)) {
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (line.compare(0, strlen(kModelNamePrefix), kModelNamePrefix) == 0) {
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        cpu_brand.assign(line.substr(strlen(kModelNamePrefix)));
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        break;
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (line.compare(0, strlen(kProcessorPrefix), kProcessorPrefix) == 0) {
114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        cpu_brand.assign(line.substr(strlen(kProcessorPrefix)));
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        break;
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return cpu_brand;
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass LazyCpuInfoValue {
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  LazyCpuInfoValue() : value_(ParseCpuInfo()) {}
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const std::string& value() { return value_; }
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const std::string value_;
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DISALLOW_COPY_AND_ASSIGN(LazyCpuInfoValue);
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubase::LazyInstance<LazyCpuInfoValue> g_lazy_cpu_brand =
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    LAZY_INSTANCE_INITIALIZER;
1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst std::string& CpuBrandInfo() {
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return g_lazy_cpu_brand.Get().value();
1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif  // defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) ||
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // defined(OS_LINUX))
1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // anonymous namespace
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CPU::Initialize() {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ARCH_CPU_X86_FAMILY)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int cpu_info[4] = {-1};
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char cpu_string[48];
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // __cpuid with an InfoType argument of 0 returns the number of
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // valid Ids in CPUInfo[0] and the CPU identification string in
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the other three array elements. The CPU identification string is
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not in linear order. The code below arranges the information
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in a human readable form. The human readable order is CPUInfo[1] |
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CPUInfo[3] | CPUInfo[2]. CPUInfo[2] and CPUInfo[3] are swapped
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before using memcpy to copy these three array elements to cpu_string.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __cpuid(cpu_info, 0);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_ids = cpu_info[0];
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::swap(cpu_info[2], cpu_info[3]);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(cpu_string, &cpu_info[1], 3 * sizeof(cpu_info[1]));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cpu_vendor_.assign(cpu_string, 3 * sizeof(cpu_info[1]));
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Interpret CPU feature information.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_ids > 0) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __cpuid(cpu_info, 1);
165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    signature_ = cpu_info[0];
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stepping_ = cpu_info[0] & 0xf;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    family_ = (cpu_info[0] >> 8) & 0xf;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    type_ = (cpu_info[0] >> 12) & 0x3;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_model_ = (cpu_info[0] >> 16) & 0xf;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_family_ = (cpu_info[0] >> 20) & 0xff;
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    has_mmx_ =   (cpu_info[3] & 0x00800000) != 0;
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    has_sse_ =   (cpu_info[3] & 0x02000000) != 0;
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    has_sse2_ =  (cpu_info[3] & 0x04000000) != 0;
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    has_sse3_ =  (cpu_info[2] & 0x00000001) != 0;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    has_avx_hardware_ =
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 (cpu_info[2] & 0x10000000) != 0;
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // AVX instructions will generate an illegal instruction exception unless
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    //   a) they are supported by the CPU,
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    //   b) XSAVE is supported by the CPU and
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    //   c) XSAVE is enabled by the kernel.
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    //
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // In addition, we have observed some crashes with the xgetbv instruction
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // even after following Intel's example code. (See crbug.com/375968.)
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Because of that, we also test the XSAVE bit because its description in
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // the CPUID documentation suggests that it signals xgetbv support.
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    has_avx_ =
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        has_avx_hardware_ &&
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        (cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        (cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        (_xgetbv(0) & 6) == 6 /* XSAVE enabled by kernel */;
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    has_aesni_ = (cpu_info[2] & 0x02000000) != 0;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the brand string of the cpu.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __cpuid(cpu_info, 0x80000000);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int parameter_end = 0x80000004;
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int max_parameter = cpu_info[0];
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cpu_info[0] >= parameter_end) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* cpu_string_ptr = cpu_string;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int parameter = 0x80000002; parameter <= parameter_end &&
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         cpu_string_ptr < &cpu_string[sizeof(cpu_string)]; parameter++) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      __cpuid(cpu_info, parameter);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(cpu_string_ptr, cpu_info, sizeof(cpu_info));
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cpu_string_ptr += sizeof(cpu_info);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cpu_brand_.assign(cpu_string, cpu_string_ptr - cpu_string);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int parameter_containing_non_stop_time_stamp_counter = 0x80000007;
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (max_parameter >= parameter_containing_non_stop_time_stamp_counter) {
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    __cpuid(cpu_info, parameter_containing_non_stop_time_stamp_counter);
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0;
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  cpu_brand_.assign(CpuBrandInfo());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CPU::IntelMicroArchitecture CPU::GetIntelMicroArchitecture() const {
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_avx()) return AVX;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_sse42()) return SSE42;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_sse41()) return SSE41;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_ssse3()) return SSSE3;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_sse3()) return SSE3;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_sse2()) return SSE2;
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_sse()) return SSE;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PENTIUM;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
238