1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_CPU_H_ 6 #define BASE_CPU_H_ 7 8 #include <cstdint> 9 #include <string> 10 11 #include "base/base_export.h" 12 #include "build/build_config.h" 13 14 namespace base { 15 16 #if defined(ARCH_CPU_X86_FAMILY) 17 namespace internal { 18 19 struct X86ModelInfo { 20 int family; 21 int model; 22 int ext_family; 23 int ext_model; 24 }; 25 26 // Compute the CPU family and model based on the vendor and CPUID signature. 27 BASE_EXPORT X86ModelInfo ComputeX86FamilyAndModel(const std::string& vendor, 28 int signature); 29 30 } // namespace internal 31 #endif // defined(ARCH_CPU_X86_FAMILY) 32 33 // Query information about the processor. 34 class BASE_EXPORT CPU final { 35 public: 36 CPU(); 37 CPU(CPU&&); 38 CPU(const CPU&) = delete; 39 40 // Get a preallocated instance of CPU. 41 // It can be used in very early application startup or in memory allocation 42 // handlers. The instance of CPU is created without branding, see `CPU(bool 43 // requires_branding)` for details and implications. 44 // 45 // Support for various security features such as Arm's BTI and MTE uses this 46 // instance to detect CPU support. To prevent any attempt 47 // to disable a feature by attacking this data, base::ProtectedMemory is used 48 // to protected it from write accesses. 49 // Note that base::ProtectedMemory falls back to unprotected memory if the 50 // target OS is not supported. 51 static const CPU& GetInstanceNoAllocation(); 52 53 enum IntelMicroArchitecture { 54 PENTIUM = 0, 55 SSE = 1, 56 SSE2 = 2, 57 SSE3 = 3, 58 SSSE3 = 4, 59 SSE41 = 5, 60 SSE42 = 6, 61 AVX = 7, 62 AVX2 = 8, 63 FMA3 = 9, 64 AVX_VNNI = 10, 65 AVX512F = 11, 66 AVX512BW = 12, 67 AVX512_VNNI = 13, 68 MAX_INTEL_MICRO_ARCHITECTURE = 14 69 }; 70 71 // Accessors for CPU information. 72 // TODO(crbug.com/335001230): Most if not all of these should be x86-only. vendor_name()73 std::string vendor_name() const { return cpu_vendor_; } signature()74 int signature() const { return signature_; } stepping()75 int stepping() const { return stepping_; } model()76 int model() const { return model_; } family()77 int family() const { return family_; } type()78 int type() const { return type_; } extended_model()79 int extended_model() const { return ext_model_; } extended_family()80 int extended_family() const { return ext_family_; } 81 #if defined(ARCH_CPU_X86_FAMILY) has_mmx()82 bool has_mmx() const { return has_mmx_; } has_sse()83 bool has_sse() const { return has_sse_; } has_sse2()84 bool has_sse2() const { return has_sse2_; } has_sse3()85 bool has_sse3() const { return has_sse3_; } has_ssse3()86 bool has_ssse3() const { return has_ssse3_; } has_sse41()87 bool has_sse41() const { return has_sse41_; } has_sse42()88 bool has_sse42() const { return has_sse42_; } has_popcnt()89 bool has_popcnt() const { return has_popcnt_; } has_avx()90 bool has_avx() const { return has_avx_; } has_fma3()91 bool has_fma3() const { return has_fma3_; } has_avx2()92 bool has_avx2() const { return has_avx2_; } has_avx_vnni()93 bool has_avx_vnni() const { return has_avx_vnni_; } has_avx512_f()94 bool has_avx512_f() const { return has_avx512_f_; } has_avx512_bw()95 bool has_avx512_bw() const { return has_avx512_bw_; } has_avx512_vnni()96 bool has_avx512_vnni() const { return has_avx512_vnni_; } 97 #endif has_aesni()98 bool has_aesni() const { return has_aesni_; } has_non_stop_time_stamp_counter()99 bool has_non_stop_time_stamp_counter() const { 100 return has_non_stop_time_stamp_counter_; 101 } is_running_in_vm()102 bool is_running_in_vm() const { return is_running_in_vm_; } 103 104 // Armv8.5-A extensions for control flow and memory safety. 105 #if defined(ARCH_CPU_ARM_FAMILY) has_mte()106 bool has_mte() const { return has_mte_; } has_bti()107 bool has_bti() const { return has_bti_; } 108 #else has_mte()109 constexpr bool has_mte() const { return false; } has_bti()110 constexpr bool has_bti() const { return false; } 111 #endif 112 113 #if defined(ARCH_CPU_X86_FAMILY) 114 // Memory protection key support for user-mode pages has_pku()115 bool has_pku() const { return has_pku_; } 116 #else has_pku()117 constexpr bool has_pku() const { return false; } 118 #endif 119 120 #if defined(ARCH_CPU_X86_FAMILY) 121 IntelMicroArchitecture GetIntelMicroArchitecture() const; 122 #endif cpu_brand()123 std::string cpu_brand() const { return cpu_brand_; } 124 125 private: 126 // Query the processor for CPUID information. 127 void Initialize(); 128 129 int signature_ = 0; // raw form of type, family, model, and stepping 130 int type_ = 0; // process type 131 int family_ = 0; // family of the processor 132 int model_ = 0; // model of processor 133 int stepping_ = 0; // processor revision number 134 int ext_model_ = 0; 135 int ext_family_ = 0; 136 #if defined(ARCH_CPU_X86_FAMILY) 137 bool has_mmx_ = false; 138 bool has_sse_ = false; 139 bool has_sse2_ = false; 140 bool has_sse3_ = false; 141 bool has_ssse3_ = false; 142 bool has_sse41_ = false; 143 bool has_sse42_ = false; 144 bool has_popcnt_ = false; 145 bool has_avx_ = false; 146 bool has_fma3_ = false; 147 bool has_avx2_ = false; 148 bool has_avx_vnni_ = false; 149 bool has_avx512_f_ = false; 150 bool has_avx512_bw_ = false; 151 bool has_avx512_vnni_ = false; 152 #endif 153 bool has_aesni_ = false; 154 #if defined(ARCH_CPU_ARM_FAMILY) 155 bool has_mte_ = false; // Armv8.5-A MTE (Memory Taggging Extension) 156 bool has_bti_ = false; // Armv8.5-A BTI (Branch Target Identification) 157 #endif 158 #if defined(ARCH_CPU_X86_FAMILY) 159 bool has_pku_ = false; 160 #endif 161 bool has_non_stop_time_stamp_counter_ = false; 162 bool is_running_in_vm_ = false; 163 164 // The CPUID instruction of the X86 instruction set returns the vendor name in 165 // 3 32bit registers, which make 12 characters. See "Intel® 64 and IA-32 166 // Architectures Software Developer’s Manual - Volume 2". 167 static constexpr size_t kVendorNameSize = 12; 168 char cpu_vendor_[kVendorNameSize + 1] = "unknown"; 169 // The CPUID instruction of the X86 instruction set returns the brand name in 170 // 3*4 32bit registers, which make 48 characters. See "Intel® 64 and IA-32 171 // Architectures Software Developer’s Manual - Volume 2". 172 static constexpr size_t kBrandNameSize = 48; 173 char cpu_brand_[kBrandNameSize + 1] = "\0"; 174 }; 175 176 } // namespace base 177 178 #endif // BASE_CPU_H_ 179