1 // Copyright 2017 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //////////////////////////////////////////////////////////////////////////////// 16 // A note on Windows AArch64 implementation 17 //////////////////////////////////////////////////////////////////////////////// 18 19 // Getting cpu info via EL1 system registers is not possible, so we delegate it 20 // to the Windows API (i.e., IsProcessorFeaturePresent and GetNativeSystemInfo). 21 // The `implementer`, `variant` and `part` fields of the `Aarch64Info` struct 22 // are not used, so they are set to 0. To get `revision` we use 23 // `wProcessorRevision` from `SYSTEM_INFO`. 24 // 25 // Cryptographic Extension: 26 // ----------------------------------------------------------------------------- 27 // According to documentation Arm Architecture Reference Manual for 28 // A-profile architecture. A2.3 The Armv8 Cryptographic Extension. The Armv8.0 29 // Cryptographic Extension provides instructions for the acceleration of 30 // encryption and decryption, and includes the following features: FEAT_AES, 31 // FEAT_PMULL, FEAT_SHA1, FEAT_SHA256. 32 // see: https://developer.arm.com/documentation/ddi0487/latest 33 // 34 // We use `PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE` to detect all Armv8.0 crypto 35 // features. This value reports all features or nothing, so even if you only 36 // have support FEAT_AES and FEAT_PMULL, it will still return false. 37 // 38 // From Armv8.2, an implementation of the Armv8.0 Cryptographic Extension can 39 // include either or both of: 40 // 41 // • The AES functionality, including support for multiplication of 64-bit 42 // polynomials. The ID_AA64ISAR0_EL1.AES field indicates whether this 43 // functionality is supported. 44 // • The SHA1 and SHA2-256 functionality. The ID_AA64ISAR0_EL1.{SHA2, SHA1} 45 // fields indicate whether this functionality is supported. 46 // 47 // ID_AA64ISAR0_EL1.AES, bits [7:4]: 48 // Indicates support for AES instructions in AArch64 state. Defined values are: 49 // - 0b0000 No AES instructions implemented. 50 // - 0b0001 AESE, AESD, AESMC, and AESIMC instructions implemented. 51 // - 0b0010 As for 0b0001, plus PMULL/PMULL2 instructions operating on 64-bit 52 // data quantities. 53 // 54 // FEAT_AES implements the functionality identified by the value 0b0001. 55 // FEAT_PMULL implements the functionality identified by the value 0b0010. 56 // From Armv8, the permitted values are 0b0000 and 0b0010. 57 // 58 // ID_AA64ISAR0_EL1.SHA1, bits [11:8]: 59 // Indicates support for SHA1 instructions in AArch64 state. Defined values are: 60 // - 0b0000 No SHA1 instructions implemented. 61 // - 0b0001 SHA1C, SHA1P, SHA1M, SHA1H, SHA1SU0, and SHA1SU1 instructions 62 // implemented. 63 // 64 // FEAT_SHA1 implements the functionality identified by the value 0b0001. 65 // From Armv8, the permitted values are 0b0000 and 0b0001. 66 // If the value of ID_AA64ISAR0_EL1.SHA2 is 0b0000, this field must have the 67 // value 0b0000. 68 // 69 // ID_AA64ISAR0_EL1.SHA2, bits [15:12]: 70 // Indicates support for SHA2 instructions in AArch64 state. Defined values are: 71 // - 0b0000 No SHA2 instructions implemented. 72 // - 0b0001 Implements instructions: SHA256H, SHA256H2, SHA256SU0, and 73 // SHA256SU1. 74 // - 0b0010 Implements instructions: 75 // • SHA256H, SHA256H2, SHA256SU0, and SHA256SU1. 76 // • SHA512H, SHA512H2, SHA512SU0, and SHA512SU1. 77 // 78 // FEAT_SHA256 implements the functionality identified by the value 0b0001. 79 // FEAT_SHA512 implements the functionality identified by the value 0b0010. 80 // 81 // In Armv8, the permitted values are 0b0000 and 0b0001. 82 // From Armv8.2, the permitted values are 0b0000, 0b0001, and 0b0010. 83 // 84 // If the value of ID_AA64ISAR0_EL1.SHA1 is 0b0000, this field must have the 85 // value 0b0000. 86 // 87 // If the value of this field is 0b0010, ID_AA64ISAR0_EL1.SHA3 88 // must have the value 0b0001. 89 // 90 // Other cryptographic features that we cannot detect such as sha512, sha3, sm3, 91 // sm4, sveaes, svepmull, svesha3, svesm4 we set to 0. 92 // 93 // FP/SIMD: 94 // ----------------------------------------------------------------------------- 95 // FP/SIMD must be implemented on all Armv8.0 implementations, but 96 // implementations targeting specialized markets may support the following 97 // combinations: 98 // 99 // • No NEON or floating-point. 100 // • Full floating-point and SIMD support with exception trapping. 101 // • Full floating-point and SIMD support without exception trapping. 102 // 103 // ref: 104 // https://developer.arm.com/documentation/den0024/a/AArch64-Floating-point-and-NEON 105 // 106 // So, we use `PF_ARM_VFP_32_REGISTERS_AVAILABLE`, 107 // `PF_ARM_NEON_INSTRUCTIONS_AVAILABLE` to detect `asimd` and `fp` 108 109 #ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ 110 #define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ 111 112 #include "cpu_features_cache_info.h" 113 #include "cpu_features_macros.h" 114 115 CPU_FEATURES_START_CPP_NAMESPACE 116 117 typedef struct { 118 int fp : 1; // Floating-point. 119 int asimd : 1; // Advanced SIMD. 120 int evtstrm : 1; // Generic timer generated events. 121 int aes : 1; // Hardware-accelerated Advanced Encryption Standard. 122 int pmull : 1; // Polynomial multiply long. 123 int sha1 : 1; // Hardware-accelerated SHA1. 124 int sha2 : 1; // Hardware-accelerated SHA2-256. 125 int crc32 : 1; // Hardware-accelerated CRC-32. 126 int atomics : 1; // Armv8.1 atomic instructions. 127 int fphp : 1; // Half-precision floating point support. 128 int asimdhp : 1; // Advanced SIMD half-precision support. 129 int cpuid : 1; // Access to certain ID registers. 130 int asimdrdm : 1; // Rounding Double Multiply Accumulate/Subtract. 131 int jscvt : 1; // Support for JavaScript conversion. 132 int fcma : 1; // Floating point complex numbers. 133 int lrcpc : 1; // Support for weaker release consistency. 134 int dcpop : 1; // Data persistence writeback. 135 int sha3 : 1; // Hardware-accelerated SHA3. 136 int sm3 : 1; // Hardware-accelerated SM3. 137 int sm4 : 1; // Hardware-accelerated SM4. 138 int asimddp : 1; // Dot product instruction. 139 int sha512 : 1; // Hardware-accelerated SHA512. 140 int sve : 1; // Scalable Vector Extension. 141 int asimdfhm : 1; // Additional half-precision instructions. 142 int dit : 1; // Data independent timing. 143 int uscat : 1; // Unaligned atomics support. 144 int ilrcpc : 1; // Additional support for weaker release consistency. 145 int flagm : 1; // Flag manipulation instructions. 146 int ssbs : 1; // Speculative Store Bypass Safe PSTATE bit. 147 int sb : 1; // Speculation barrier. 148 int paca : 1; // Address authentication. 149 int pacg : 1; // Generic authentication. 150 int dcpodp : 1; // Data cache clean to point of persistence. 151 int sve2 : 1; // Scalable Vector Extension (version 2). 152 int sveaes : 1; // SVE AES instructions. 153 int svepmull : 1; // SVE polynomial multiply long instructions. 154 int svebitperm : 1; // SVE bit permute instructions. 155 int svesha3 : 1; // SVE SHA3 instructions. 156 int svesm4 : 1; // SVE SM4 instructions. 157 int flagm2 : 1; // Additional flag manipulation instructions. 158 int frint : 1; // Floating point to integer rounding. 159 int svei8mm : 1; // SVE Int8 matrix multiplication instructions. 160 int svef32mm : 1; // SVE FP32 matrix multiplication instruction. 161 int svef64mm : 1; // SVE FP64 matrix multiplication instructions. 162 int svebf16 : 1; // SVE BFloat16 instructions. 163 int i8mm : 1; // Int8 matrix multiplication instructions. 164 int bf16 : 1; // BFloat16 instructions. 165 int dgh : 1; // Data Gathering Hint instruction. 166 int rng : 1; // True random number generator support. 167 int bti : 1; // Branch target identification. 168 int mte : 1; // Memory tagging extension. 169 int ecv : 1; // Enhanced counter virtualization. 170 int afp : 1; // Alternate floating-point behaviour. 171 int rpres : 1; // 12-bit reciprocal (square root) estimate precision. 172 int mte3 : 1; // MTE asymmetric fault handling. 173 int sme : 1; // Scalable Matrix Extension. 174 int smei16i64 : 1; // 16-bit to 64-bit integer widening outer product. 175 int smef64f64 : 1; // FP64 to FP64 outer product. 176 int smei8i32 : 1; // 8-bit to 32-bit integer widening outer product. 177 int smef16f32 : 1; // FP16 to FP32 outer product. 178 int smeb16f32 : 1; // BFloat16 to FP32 outper product. 179 int smef32f32 : 1; // FP32 to FP32 outer product. 180 int smefa64 : 1; // Full A64 support for SME in streaming mode. 181 int wfxt : 1; // WFE and WFI with timeout. 182 int ebf16 : 1; // Extended BFloat16 instructions. 183 int sveebf16 : 1; // SVE BFloat16 instructions. 184 int cssc : 1; // Common short sequence compression instructions. 185 int rprfm : 1; // Range Prefetch Memory hint instruction. 186 int sve2p1 : 1; // Scalable Vector Extension (version 2.1). 187 int sme2 : 1; // Scalable Matrix Extension (version 2). 188 int sme2p1 : 1; // Scalable Matrix Extension (version 2.1). 189 int smei16i32 : 1; // 16-bit to 64-bit integer widening outer product. 190 int smebi32i32 : 1; // 1-bit binary to 32-bit integer outer product. 191 int smeb16b16 : 1; // SME2.1 BFloat16 instructions. 192 int smef16f16 : 1; // FP16 to FP16 outer product. 193 194 // Make sure to update Aarch64FeaturesEnum below if you add a field here. 195 } Aarch64Features; 196 197 typedef struct { 198 Aarch64Features features; 199 int implementer; // We set 0 for Windows. 200 int variant; // We set 0 for Windows. 201 int part; // We set 0 for Windows. 202 int revision; // We use GetNativeSystemInfo to get processor revision for 203 // Windows. 204 } Aarch64Info; 205 206 Aarch64Info GetAarch64Info(void); 207 208 //////////////////////////////////////////////////////////////////////////////// 209 // Introspection functions 210 211 typedef enum { 212 AARCH64_FP, 213 AARCH64_ASIMD, 214 AARCH64_EVTSTRM, 215 AARCH64_AES, 216 AARCH64_PMULL, 217 AARCH64_SHA1, 218 AARCH64_SHA2, 219 AARCH64_CRC32, 220 AARCH64_ATOMICS, 221 AARCH64_FPHP, 222 AARCH64_ASIMDHP, 223 AARCH64_CPUID, 224 AARCH64_ASIMDRDM, 225 AARCH64_JSCVT, 226 AARCH64_FCMA, 227 AARCH64_LRCPC, 228 AARCH64_DCPOP, 229 AARCH64_SHA3, 230 AARCH64_SM3, 231 AARCH64_SM4, 232 AARCH64_ASIMDDP, 233 AARCH64_SHA512, 234 AARCH64_SVE, 235 AARCH64_ASIMDFHM, 236 AARCH64_DIT, 237 AARCH64_USCAT, 238 AARCH64_ILRCPC, 239 AARCH64_FLAGM, 240 AARCH64_SSBS, 241 AARCH64_SB, 242 AARCH64_PACA, 243 AARCH64_PACG, 244 AARCH64_DCPODP, 245 AARCH64_SVE2, 246 AARCH64_SVEAES, 247 AARCH64_SVEPMULL, 248 AARCH64_SVEBITPERM, 249 AARCH64_SVESHA3, 250 AARCH64_SVESM4, 251 AARCH64_FLAGM2, 252 AARCH64_FRINT, 253 AARCH64_SVEI8MM, 254 AARCH64_SVEF32MM, 255 AARCH64_SVEF64MM, 256 AARCH64_SVEBF16, 257 AARCH64_I8MM, 258 AARCH64_BF16, 259 AARCH64_DGH, 260 AARCH64_RNG, 261 AARCH64_BTI, 262 AARCH64_MTE, 263 AARCH64_ECV, 264 AARCH64_AFP, 265 AARCH64_RPRES, 266 AARCH64_MTE3, 267 AARCH64_SME, 268 AARCH64_SME_I16I64, 269 AARCH64_SME_F64F64, 270 AARCH64_SME_I8I32, 271 AARCH64_SME_F16F32, 272 AARCH64_SME_B16F32, 273 AARCH64_SME_F32F32, 274 AARCH64_SME_FA64, 275 AARCH64_WFXT, 276 AARCH64_EBF16, 277 AARCH64_SVE_EBF16, 278 AARCH64_CSSC, 279 AARCH64_RPRFM, 280 AARCH64_SVE2P1, 281 AARCH64_SME2, 282 AARCH64_SME2P1, 283 AARCH64_SME_I16I32, 284 AARCH64_SME_BI32I32, 285 AARCH64_SME_B16B16, 286 AARCH64_SME_F16F16, 287 AARCH64_LAST_, 288 } Aarch64FeaturesEnum; 289 290 int GetAarch64FeaturesEnumValue(const Aarch64Features* features, 291 Aarch64FeaturesEnum value); 292 293 const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum); 294 295 CPU_FEATURES_END_CPP_NAMESPACE 296 297 #if !defined(CPU_FEATURES_ARCH_AARCH64) 298 #error "Including cpuinfo_aarch64.h from a non-aarch64 target." 299 #endif 300 301 #endif // CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ 302