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 MAX_INTEL_MICRO_ARCHITECTURE = 10 65 }; 66 67 // Accessors for CPU information. vendor_name()68 std::string vendor_name() const { return cpu_vendor_; } signature()69 int signature() const { return signature_; } stepping()70 int stepping() const { return stepping_; } model()71 int model() const { return model_; } family()72 int family() const { return family_; } type()73 int type() const { return type_; } extended_model()74 int extended_model() const { return ext_model_; } extended_family()75 int extended_family() const { return ext_family_; } has_mmx()76 bool has_mmx() const { return has_mmx_; } has_sse()77 bool has_sse() const { return has_sse_; } has_sse2()78 bool has_sse2() const { return has_sse2_; } has_sse3()79 bool has_sse3() const { return has_sse3_; } has_ssse3()80 bool has_ssse3() const { return has_ssse3_; } has_sse41()81 bool has_sse41() const { return has_sse41_; } has_sse42()82 bool has_sse42() const { return has_sse42_; } has_popcnt()83 bool has_popcnt() const { return has_popcnt_; } has_avx()84 bool has_avx() const { return has_avx_; } has_fma3()85 bool has_fma3() const { return has_fma3_; } has_avx2()86 bool has_avx2() const { return has_avx2_; } has_aesni()87 bool has_aesni() const { return has_aesni_; } has_non_stop_time_stamp_counter()88 bool has_non_stop_time_stamp_counter() const { 89 return has_non_stop_time_stamp_counter_; 90 } is_running_in_vm()91 bool is_running_in_vm() const { return is_running_in_vm_; } 92 93 #if defined(ARCH_CPU_ARM_FAMILY) 94 // The cpuinfo values for ARM cores are from the MIDR_EL1 register, a 95 // bitfield whose format is described in the core-specific manuals. E.g., 96 // ARM Cortex-A57: 97 // https://developer.arm.com/documentation/ddi0488/h/system-control/aarch64-register-descriptions/main-id-register--el1. implementer()98 uint8_t implementer() const { return implementer_; } part_number()99 uint32_t part_number() const { return part_number_; } 100 #endif 101 102 // Armv8.5-A extensions for control flow and memory safety. 103 #if defined(ARCH_CPU_ARM_FAMILY) has_mte()104 bool has_mte() const { return has_mte_; } has_bti()105 bool has_bti() const { return has_bti_; } 106 #else has_mte()107 constexpr bool has_mte() const { return false; } has_bti()108 constexpr bool has_bti() const { return false; } 109 #endif 110 111 #if defined(ARCH_CPU_X86_FAMILY) 112 // Memory protection key support for user-mode pages has_pku()113 bool has_pku() const { return has_pku_; } 114 #else has_pku()115 constexpr bool has_pku() const { return false; } 116 #endif 117 118 #if defined(ARCH_CPU_X86_FAMILY) 119 IntelMicroArchitecture GetIntelMicroArchitecture() const; 120 #endif cpu_brand()121 std::string cpu_brand() const { return cpu_brand_; } 122 123 private: 124 // Query the processor for CPUID information. 125 void Initialize(bool requires_branding); 126 explicit CPU(bool requires_branding); 127 128 int signature_ = 0; // raw form of type, family, model, and stepping 129 int type_ = 0; // process type 130 int family_ = 0; // family of the processor 131 int model_ = 0; // model of processor 132 int stepping_ = 0; // processor revision number 133 int ext_model_ = 0; 134 int ext_family_ = 0; 135 #if defined(ARCH_CPU_ARM_FAMILY) 136 uint32_t part_number_ = 0; // ARM MIDR part number 137 uint8_t implementer_ = 0; // ARM MIDR implementer identifier 138 #endif 139 bool has_mmx_ = false; 140 bool has_sse_ = false; 141 bool has_sse2_ = false; 142 bool has_sse3_ = false; 143 bool has_ssse3_ = false; 144 bool has_sse41_ = false; 145 bool has_sse42_ = false; 146 bool has_popcnt_ = false; 147 bool has_avx_ = false; 148 bool has_fma3_ = false; 149 bool has_avx2_ = false; 150 bool has_aesni_ = false; 151 #if defined(ARCH_CPU_ARM_FAMILY) 152 bool has_mte_ = false; // Armv8.5-A MTE (Memory Taggging Extension) 153 bool has_bti_ = false; // Armv8.5-A BTI (Branch Target Identification) 154 #endif 155 #if defined(ARCH_CPU_X86_FAMILY) 156 bool has_pku_ = false; 157 #endif 158 bool has_non_stop_time_stamp_counter_ = false; 159 bool is_running_in_vm_ = false; 160 161 // The CPUID instruction of the X86 instruction set returns the vendor name in 162 // 3 32bit registers, which make 12 characters. See "Intel® 64 and IA-32 163 // Architectures Software Developer’s Manual - Volume 2". 164 static constexpr size_t kVendorNameSize = 12; 165 char cpu_vendor_[kVendorNameSize + 1] = "unknown"; 166 // The CPUID instruction of the X86 instruction set returns the brand name in 167 // 3*4 32bit registers, which make 48 characters. See "Intel® 64 and IA-32 168 // Architectures Software Developer’s Manual - Volume 2". 169 static constexpr size_t kBrandNameSize = 48; 170 char cpu_brand_[kBrandNameSize + 1] = "\0"; 171 }; 172 173 } // namespace base 174 175 #endif // BASE_CPU_H_ 176