Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2012 The Chromium Authors |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 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 | |
Bruno Pitrus | 75c57b5 | 2023-06-05 21:22:55 | [diff] [blame] | 8 | #include <cstdint> |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 9 | #include <string> |
| 10 | |
[email protected] | 0bea725 | 2011-08-05 15:34:00 | [diff] [blame] | 11 | #include "base/base_export.h" |
Gabriel Marin | 8fdd777 | 2019-08-17 00:28:09 | [diff] [blame] | 12 | #include "build/build_config.h" |
[email protected] | 90509cb | 2011-03-25 18:46:38 | [diff] [blame] | 13 | |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 14 | namespace base { |
| 15 | |
Gabriel Marin | 8fdd777 | 2019-08-17 00:28:09 | [diff] [blame] | 16 | #if defined(ARCH_CPU_X86_FAMILY) |
| 17 | namespace internal { |
| 18 | |
Lei Zhang | 1b1116c5 | 2021-05-14 22:54:38 | [diff] [blame] | 19 | struct X86ModelInfo { |
| 20 | int family; |
| 21 | int model; |
| 22 | int ext_family; |
| 23 | int ext_model; |
| 24 | }; |
| 25 | |
Gabriel Marin | 8fdd777 | 2019-08-17 00:28:09 | [diff] [blame] | 26 | // Compute the CPU family and model based on the vendor and CPUID signature. |
Lei Zhang | 1b1116c5 | 2021-05-14 22:54:38 | [diff] [blame] | 27 | BASE_EXPORT X86ModelInfo ComputeX86FamilyAndModel(const std::string& vendor, |
| 28 | int signature); |
Gabriel Marin | 8fdd777 | 2019-08-17 00:28:09 | [diff] [blame] | 29 | |
| 30 | } // namespace internal |
| 31 | #endif // defined(ARCH_CPU_X86_FAMILY) |
| 32 | |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 33 | // Query information about the processor. |
Thiago Farina | ba7d2a42 | 2017-06-17 00:18:49 | [diff] [blame] | 34 | class BASE_EXPORT CPU final { |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 35 | public: |
Richard Townsend | 66bf8b7 | 2021-02-18 23:39:57 | [diff] [blame] | 36 | CPU(); |
| 37 | CPU(CPU&&); |
| 38 | CPU(const CPU&) = delete; |
André Kempe | 6026911 | 2021-09-17 13:14:11 | [diff] [blame] | 39 | |
| 40 | // Get a preallocated instance of CPU. |
André Kempe | 1994caac | 2024-04-05 15:01:39 | [diff] [blame] | 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. |
André Kempe | 6026911 | 2021-09-17 13:14:11 | [diff] [blame] | 51 | static const CPU& GetInstanceNoAllocation(); |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 52 | |
[email protected] | 5016a9dd | 2013-02-02 01:10:02 | [diff] [blame] | 53 | enum IntelMicroArchitecture { |
Ng Zhi An | 03baf5e | 2021-10-04 22:56:52 | [diff] [blame] | 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, |
James Zern | 8a904ed | 2024-05-08 23:28:27 | [diff] [blame] | 64 | AVX_VNNI = 10, |
| 65 | AVX512F = 11, |
| 66 | AVX512BW = 12, |
| 67 | AVX512_VNNI = 13, |
| 68 | MAX_INTEL_MICRO_ARCHITECTURE = 14 |
[email protected] | 5016a9dd | 2013-02-02 01:10:02 | [diff] [blame] | 69 | }; |
| 70 | |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 71 | // Accessors for CPU information. |
Lei Zhang | 2c986d5 | 2024-04-30 22:12:30 | [diff] [blame] | 72 | // TODO(crbug.com/335001230): Most if not all of these should be x86-only. |
André Kempe | 1994caac | 2024-04-05 15:01:39 | [diff] [blame] | 73 | std::string vendor_name() const { return cpu_vendor_; } |
[email protected] | 5c8f89f69 | 2013-07-18 11:13:28 | [diff] [blame] | 74 | int signature() const { return signature_; } |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 75 | int stepping() const { return stepping_; } |
| 76 | int model() const { return model_; } |
| 77 | int family() const { return family_; } |
| 78 | int type() const { return type_; } |
| 79 | int extended_model() const { return ext_model_; } |
| 80 | int extended_family() const { return ext_family_; } |
Lei Zhang | 9fc2f7b | 2024-04-30 23:20:12 | [diff] [blame] | 81 | #if defined(ARCH_CPU_X86_FAMILY) |
[email protected] | 55508c4 | 2012-06-12 08:29:32 | [diff] [blame] | 82 | bool has_mmx() const { return has_mmx_; } |
| 83 | bool has_sse() const { return has_sse_; } |
| 84 | bool has_sse2() const { return has_sse2_; } |
| 85 | bool has_sse3() const { return has_sse3_; } |
| 86 | bool has_ssse3() const { return has_ssse3_; } |
| 87 | bool has_sse41() const { return has_sse41_; } |
| 88 | bool has_sse42() const { return has_sse42_; } |
ilevy | b7d2f408 | 2016-10-30 20:46:57 | [diff] [blame] | 89 | bool has_popcnt() const { return has_popcnt_; } |
[email protected] | 5016a9dd | 2013-02-02 01:10:02 | [diff] [blame] | 90 | bool has_avx() const { return has_avx_; } |
Ng Zhi An | 03baf5e | 2021-10-04 22:56:52 | [diff] [blame] | 91 | bool has_fma3() const { return has_fma3_; } |
fbarchard | 0ce41ae | 2015-10-02 03:23:19 | [diff] [blame] | 92 | bool has_avx2() const { return has_avx2_; } |
James Zern | 8a904ed | 2024-05-08 23:28:27 | [diff] [blame] | 93 | bool has_avx_vnni() const { return has_avx_vnni_; } |
| 94 | bool has_avx512_f() const { return has_avx512_f_; } |
| 95 | bool has_avx512_bw() const { return has_avx512_bw_; } |
| 96 | bool has_avx512_vnni() const { return has_avx512_vnni_; } |
Steinar H. Gunderson | abf09a0 | 2025-05-12 14:00:33 | [diff] [blame] | 97 | // NOTE: This does not include 256-bit PCLMUL, which is |
| 98 | // a separate feature flag. |
| 99 | bool has_pclmul() const { return has_pclmul_; } |
Lei Zhang | 2c986d5 | 2024-04-30 22:12:30 | [diff] [blame] | 100 | #endif |
[email protected] | b54d16d | 2013-12-02 16:15:03 | [diff] [blame] | 101 | bool has_aesni() const { return has_aesni_; } |
[email protected] | aa31281 | 2013-04-30 19:46:05 | [diff] [blame] | 102 | bool has_non_stop_time_stamp_counter() const { |
| 103 | return has_non_stop_time_stamp_counter_; |
| 104 | } |
Julian Pastarmov | 6f4a318 | 2019-06-26 07:00:43 | [diff] [blame] | 105 | bool is_running_in_vm() const { return is_running_in_vm_; } |
[email protected] | c37c1a8c | 2014-08-08 08:45:24 | [diff] [blame] | 106 | |
Richard Townsend | 8cb7ba0b | 2020-11-26 23:23:22 | [diff] [blame] | 107 | // Armv8.5-A extensions for control flow and memory safety. |
André Kempe | 6026911 | 2021-09-17 13:14:11 | [diff] [blame] | 108 | #if defined(ARCH_CPU_ARM_FAMILY) |
Richard Townsend | 8cb7ba0b | 2020-11-26 23:23:22 | [diff] [blame] | 109 | bool has_mte() const { return has_mte_; } |
| 110 | bool has_bti() const { return has_bti_; } |
André Kempe | 6026911 | 2021-09-17 13:14:11 | [diff] [blame] | 111 | #else |
| 112 | constexpr bool has_mte() const { return false; } |
| 113 | constexpr bool has_bti() const { return false; } |
| 114 | #endif |
Richard Townsend | 8cb7ba0b | 2020-11-26 23:23:22 | [diff] [blame] | 115 | |
Lei Zhang | e668a1d | 2022-01-04 21:06:33 | [diff] [blame] | 116 | #if defined(ARCH_CPU_X86_FAMILY) |
Stephen Roettger | 6f1a424 | 2022-10-07 10:04:25 | [diff] [blame] | 117 | // Memory protection key support for user-mode pages |
| 118 | bool has_pku() const { return has_pku_; } |
| 119 | #else |
| 120 | constexpr bool has_pku() const { return false; } |
| 121 | #endif |
| 122 | |
| 123 | #if defined(ARCH_CPU_X86_FAMILY) |
[email protected] | 5016a9dd | 2013-02-02 01:10:02 | [diff] [blame] | 124 | IntelMicroArchitecture GetIntelMicroArchitecture() const; |
Lei Zhang | e668a1d | 2022-01-04 21:06:33 | [diff] [blame] | 125 | #endif |
André Kempe | 1994caac | 2024-04-05 15:01:39 | [diff] [blame] | 126 | std::string cpu_brand() const { return cpu_brand_; } |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 127 | |
| 128 | private: |
| 129 | // Query the processor for CPUID information. |
Peter Boström | 20a6e68 | 2024-09-30 22:10:11 | [diff] [blame] | 130 | void Initialize(); |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 131 | |
Richard Townsend | 8cb7ba0b | 2020-11-26 23:23:22 | [diff] [blame] | 132 | int signature_ = 0; // raw form of type, family, model, and stepping |
| 133 | int type_ = 0; // process type |
| 134 | int family_ = 0; // family of the processor |
| 135 | int model_ = 0; // model of processor |
| 136 | int stepping_ = 0; // processor revision number |
| 137 | int ext_model_ = 0; |
| 138 | int ext_family_ = 0; |
Lei Zhang | 9fc2f7b | 2024-04-30 23:20:12 | [diff] [blame] | 139 | #if defined(ARCH_CPU_X86_FAMILY) |
Richard Townsend | 8cb7ba0b | 2020-11-26 23:23:22 | [diff] [blame] | 140 | bool has_mmx_ = false; |
| 141 | bool has_sse_ = false; |
| 142 | bool has_sse2_ = false; |
| 143 | bool has_sse3_ = false; |
| 144 | bool has_ssse3_ = false; |
| 145 | bool has_sse41_ = false; |
| 146 | bool has_sse42_ = false; |
| 147 | bool has_popcnt_ = false; |
| 148 | bool has_avx_ = false; |
Ng Zhi An | 03baf5e | 2021-10-04 22:56:52 | [diff] [blame] | 149 | bool has_fma3_ = false; |
Richard Townsend | 8cb7ba0b | 2020-11-26 23:23:22 | [diff] [blame] | 150 | bool has_avx2_ = false; |
James Zern | 8a904ed | 2024-05-08 23:28:27 | [diff] [blame] | 151 | bool has_avx_vnni_ = false; |
| 152 | bool has_avx512_f_ = false; |
| 153 | bool has_avx512_bw_ = false; |
| 154 | bool has_avx512_vnni_ = false; |
Steinar H. Gunderson | abf09a0 | 2025-05-12 14:00:33 | [diff] [blame] | 155 | bool has_pclmul_ = false; |
Lei Zhang | 2c986d5 | 2024-04-30 22:12:30 | [diff] [blame] | 156 | #endif |
Richard Townsend | 8cb7ba0b | 2020-11-26 23:23:22 | [diff] [blame] | 157 | bool has_aesni_ = false; |
André Kempe | 6026911 | 2021-09-17 13:14:11 | [diff] [blame] | 158 | #if defined(ARCH_CPU_ARM_FAMILY) |
Richard Townsend | 8cb7ba0b | 2020-11-26 23:23:22 | [diff] [blame] | 159 | bool has_mte_ = false; // Armv8.5-A MTE (Memory Taggging Extension) |
| 160 | bool has_bti_ = false; // Armv8.5-A BTI (Branch Target Identification) |
André Kempe | 6026911 | 2021-09-17 13:14:11 | [diff] [blame] | 161 | #endif |
Stephen Roettger | 6f1a424 | 2022-10-07 10:04:25 | [diff] [blame] | 162 | #if defined(ARCH_CPU_X86_FAMILY) |
| 163 | bool has_pku_ = false; |
| 164 | #endif |
Richard Townsend | 8cb7ba0b | 2020-11-26 23:23:22 | [diff] [blame] | 165 | bool has_non_stop_time_stamp_counter_ = false; |
| 166 | bool is_running_in_vm_ = false; |
André Kempe | 1994caac | 2024-04-05 15:01:39 | [diff] [blame] | 167 | |
| 168 | // The CPUID instruction of the X86 instruction set returns the vendor name in |
| 169 | // 3 32bit registers, which make 12 characters. See "Intel® 64 and IA-32 |
| 170 | // Architectures Software Developer’s Manual - Volume 2". |
| 171 | static constexpr size_t kVendorNameSize = 12; |
| 172 | char cpu_vendor_[kVendorNameSize + 1] = "unknown"; |
| 173 | // The CPUID instruction of the X86 instruction set returns the brand name in |
| 174 | // 3*4 32bit registers, which make 48 characters. See "Intel® 64 and IA-32 |
| 175 | // Architectures Software Developer’s Manual - Volume 2". |
| 176 | static constexpr size_t kBrandNameSize = 48; |
| 177 | char cpu_brand_[kBrandNameSize + 1] = "\0"; |
[email protected] | de8d2667 | 2008-09-25 22:08:44 | [diff] [blame] | 178 | }; |
| 179 | |
| 180 | } // namespace base |
| 181 | |
| 182 | #endif // BASE_CPU_H_ |