1 /* 2 * QEMU Arm CPU -- feature test functions 3 * 4 * Copyright (c) 2023 Linaro Ltd 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef TARGET_ARM_FEATURES_H 21 #define TARGET_ARM_FEATURES_H 22 23 #include "hw/registerfields.h" 24 #include "qemu/host-utils.h" 25 #include "cpu.h" 26 27 /* 28 * Naming convention for isar_feature functions: 29 * Functions which test 32-bit ID registers should have _aa32_ in 30 * their name. Functions which test 64-bit ID registers should have 31 * _aa64_ in their name. These must only be used in code where we 32 * know for certain that the CPU has AArch32 or AArch64 respectively 33 * or where the correct answer for a CPU which doesn't implement that 34 * CPU state is "false" (eg when generating A32 or A64 code, if adding 35 * system registers that are specific to that CPU state, for "should 36 * we let this system register bit be set" tests where the 32-bit 37 * flavour of the register doesn't have the bit, and so on). 38 * Functions which simply ask "does this feature exist at all" have 39 * _any_ in their name, and always return the logical OR of the _aa64_ 40 * and the _aa32_ function. 41 */ 42 43 /* 44 * 32-bit feature tests via id registers. 45 */ 46 static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id) 47 { 48 return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0; 49 } 50 51 static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id) 52 { 53 return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1; 54 } 55 56 static inline bool isar_feature_aa32_lob(const ARMISARegisters *id) 57 { 58 /* (M-profile) low-overhead loops and branch future */ 59 return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3; 60 } 61 62 static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id) 63 { 64 return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0; 65 } 66 67 static inline bool isar_feature_aa32_aes(const ARMISARegisters *id) 68 { 69 return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) != 0; 70 } 71 72 static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id) 73 { 74 return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) > 1; 75 } 76 77 static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id) 78 { 79 return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA1) != 0; 80 } 81 82 static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id) 83 { 84 return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA2) != 0; 85 } 86 87 static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id) 88 { 89 return FIELD_EX32(id->id_isar5, ID_ISAR5, CRC32) != 0; 90 } 91 92 static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id) 93 { 94 return FIELD_EX32(id->id_isar5, ID_ISAR5, RDM) != 0; 95 } 96 97 static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id) 98 { 99 return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0; 100 } 101 102 static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id) 103 { 104 return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0; 105 } 106 107 static inline bool isar_feature_aa32_dp(const ARMISARegisters *id) 108 { 109 return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0; 110 } 111 112 static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id) 113 { 114 return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0; 115 } 116 117 static inline bool isar_feature_aa32_sb(const ARMISARegisters *id) 118 { 119 return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0; 120 } 121 122 static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) 123 { 124 return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; 125 } 126 127 static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id) 128 { 129 return FIELD_EX32(id->id_isar6, ID_ISAR6, BF16) != 0; 130 } 131 132 static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id) 133 { 134 return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0; 135 } 136 137 static inline bool isar_feature_aa32_ras(const ARMISARegisters *id) 138 { 139 return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0; 140 } 141 142 static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id) 143 { 144 return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0; 145 } 146 147 static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) 148 { 149 /* 150 * Return true if M-profile state handling insns 151 * (VSCCLRM, CLRM, FPCTX access insns) are implemented 152 */ 153 return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3; 154 } 155 156 static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) 157 { 158 /* Sadly this is encoded differently for A-profile and M-profile */ 159 if (isar_feature_aa32_mprofile(id)) { 160 return FIELD_EX32(id->mvfr1, MVFR1, FP16) > 0; 161 } else { 162 return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3; 163 } 164 } 165 166 static inline bool isar_feature_aa32_mve(const ARMISARegisters *id) 167 { 168 /* 169 * Return true if MVE is supported (either integer or floating point). 170 * We must check for M-profile as the MVFR1 field means something 171 * else for A-profile. 172 */ 173 return isar_feature_aa32_mprofile(id) && 174 FIELD_EX32(id->mvfr1, MVFR1, MVE) > 0; 175 } 176 177 static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id) 178 { 179 /* 180 * Return true if MVE is supported (either integer or floating point). 181 * We must check for M-profile as the MVFR1 field means something 182 * else for A-profile. 183 */ 184 return isar_feature_aa32_mprofile(id) && 185 FIELD_EX32(id->mvfr1, MVFR1, MVE) >= 2; 186 } 187 188 static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) 189 { 190 /* 191 * Return true if either VFP or SIMD is implemented. 192 * In this case, a minimum of VFP w/ D0-D15. 193 */ 194 return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0; 195 } 196 197 static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id) 198 { 199 /* Return true if D16-D31 are implemented */ 200 return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2; 201 } 202 203 static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id) 204 { 205 return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0; 206 } 207 208 static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id) 209 { 210 /* Return true if CPU supports single precision floating point, VFPv2 */ 211 return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0; 212 } 213 214 static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id) 215 { 216 /* Return true if CPU supports single precision floating point, VFPv3 */ 217 return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2; 218 } 219 220 static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id) 221 { 222 /* Return true if CPU supports double precision floating point, VFPv2 */ 223 return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0; 224 } 225 226 static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id) 227 { 228 /* Return true if CPU supports double precision floating point, VFPv3 */ 229 return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2; 230 } 231 232 static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id) 233 { 234 return isar_feature_aa32_fpsp_v2(id) || isar_feature_aa32_fpdp_v2(id); 235 } 236 237 /* 238 * We always set the FP and SIMD FP16 fields to indicate identical 239 * levels of support (assuming SIMD is implemented at all), so 240 * we only need one set of accessors. 241 */ 242 static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id) 243 { 244 return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0; 245 } 246 247 static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) 248 { 249 return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1; 250 } 251 252 /* 253 * Note that this ID register field covers both VFP and Neon FMAC, 254 * so should usually be tested in combination with some other 255 * check that confirms the presence of whichever of VFP or Neon is 256 * relevant, to avoid accidentally enabling a Neon feature on 257 * a VFP-no-Neon core or vice-versa. 258 */ 259 static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id) 260 { 261 return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0; 262 } 263 264 static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id) 265 { 266 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1; 267 } 268 269 static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id) 270 { 271 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2; 272 } 273 274 static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id) 275 { 276 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3; 277 } 278 279 static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) 280 { 281 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4; 282 } 283 284 static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id) 285 { 286 return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4; 287 } 288 289 static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) 290 { 291 return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0; 292 } 293 294 static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id) 295 { 296 return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2; 297 } 298 299 static inline bool isar_feature_aa32_pmuv3p1(const ARMISARegisters *id) 300 { 301 /* 0xf means "non-standard IMPDEF PMU" */ 302 return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 4 && 303 FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; 304 } 305 306 static inline bool isar_feature_aa32_pmuv3p4(const ARMISARegisters *id) 307 { 308 /* 0xf means "non-standard IMPDEF PMU" */ 309 return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 && 310 FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; 311 } 312 313 static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id) 314 { 315 /* 0xf means "non-standard IMPDEF PMU" */ 316 return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 6 && 317 FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; 318 } 319 320 static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id) 321 { 322 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0; 323 } 324 325 static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id) 326 { 327 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0; 328 } 329 330 static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id) 331 { 332 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0; 333 } 334 335 static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id) 336 { 337 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0; 338 } 339 340 static inline bool isar_feature_aa32_half_evt(const ARMISARegisters *id) 341 { 342 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 1; 343 } 344 345 static inline bool isar_feature_aa32_evt(const ARMISARegisters *id) 346 { 347 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 2; 348 } 349 350 static inline bool isar_feature_aa32_dit(const ARMISARegisters *id) 351 { 352 return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0; 353 } 354 355 static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) 356 { 357 return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0; 358 } 359 360 static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id) 361 { 362 return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 5; 363 } 364 365 static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id) 366 { 367 return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8; 368 } 369 370 static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id) 371 { 372 return FIELD_EX32(id->dbgdevid, DBGDEVID, DOUBLELOCK) > 0; 373 } 374 375 /* 376 * 64-bit feature tests via id registers. 377 */ 378 static inline bool isar_feature_aa64_aes(const ARMISARegisters *id) 379 { 380 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) != 0; 381 } 382 383 static inline bool isar_feature_aa64_pmull(const ARMISARegisters *id) 384 { 385 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) > 1; 386 } 387 388 static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id) 389 { 390 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA1) != 0; 391 } 392 393 static inline bool isar_feature_aa64_sha256(const ARMISARegisters *id) 394 { 395 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) != 0; 396 } 397 398 static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id) 399 { 400 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) > 1; 401 } 402 403 static inline bool isar_feature_aa64_crc32(const ARMISARegisters *id) 404 { 405 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, CRC32) != 0; 406 } 407 408 static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id) 409 { 410 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, ATOMIC) != 0; 411 } 412 413 static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id) 414 { 415 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RDM) != 0; 416 } 417 418 static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id) 419 { 420 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA3) != 0; 421 } 422 423 static inline bool isar_feature_aa64_sm3(const ARMISARegisters *id) 424 { 425 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM3) != 0; 426 } 427 428 static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id) 429 { 430 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM4) != 0; 431 } 432 433 static inline bool isar_feature_aa64_dp(const ARMISARegisters *id) 434 { 435 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0; 436 } 437 438 static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id) 439 { 440 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0; 441 } 442 443 static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id) 444 { 445 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0; 446 } 447 448 static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id) 449 { 450 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2; 451 } 452 453 static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id) 454 { 455 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0; 456 } 457 458 static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id) 459 { 460 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2; 461 } 462 463 static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id) 464 { 465 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0; 466 } 467 468 static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) 469 { 470 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0; 471 } 472 473 static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id) 474 { 475 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0; 476 } 477 478 static inline bool isar_feature_aa64_xs(const ARMISARegisters *id) 479 { 480 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, XS) != 0; 481 } 482 483 /* 484 * These are the values from APA/API/APA3. 485 * In general these must be compared '>=', per the normal Arm ARM 486 * treatment of fields in ID registers. 487 */ 488 typedef enum { 489 PauthFeat_None = 0, 490 PauthFeat_1 = 1, 491 PauthFeat_EPAC = 2, 492 PauthFeat_2 = 3, 493 PauthFeat_FPAC = 4, 494 PauthFeat_FPACCOMBINED = 5, 495 } ARMPauthFeature; 496 497 static inline ARMPauthFeature 498 isar_feature_pauth_feature(const ARMISARegisters *id) 499 { 500 /* 501 * Architecturally, only one of {APA,API,APA3} may be active (non-zero) 502 * and the other two must be zero. Thus we may avoid conditionals. 503 */ 504 return (FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) | 505 FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, API) | 506 FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3)); 507 } 508 509 static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) 510 { 511 /* 512 * Return true if any form of pauth is enabled, as this 513 * predicate controls migration of the 128-bit keys. 514 */ 515 return isar_feature_pauth_feature(id) != PauthFeat_None; 516 } 517 518 static inline bool isar_feature_aa64_pauth_qarma5(const ARMISARegisters *id) 519 { 520 /* 521 * Return true if pauth is enabled with the architected QARMA5 algorithm. 522 * QEMU will always enable or disable both APA and GPA. 523 */ 524 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0; 525 } 526 527 static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id) 528 { 529 /* 530 * Return true if pauth is enabled with the architected QARMA3 algorithm. 531 * QEMU will always enable or disable both APA3 and GPA3. 532 */ 533 return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3) != 0; 534 } 535 536 static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) 537 { 538 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0; 539 } 540 541 static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id) 542 { 543 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0; 544 } 545 546 static inline bool isar_feature_aa64_frint(const ARMISARegisters *id) 547 { 548 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0; 549 } 550 551 static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id) 552 { 553 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0; 554 } 555 556 static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id) 557 { 558 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2; 559 } 560 561 static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id) 562 { 563 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) != 0; 564 } 565 566 static inline bool isar_feature_aa64_ebf16(const ARMISARegisters *id) 567 { 568 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) > 1; 569 } 570 571 static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id) 572 { 573 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0; 574 } 575 576 static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id) 577 { 578 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2; 579 } 580 581 static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) 582 { 583 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; 584 } 585 586 static inline bool isar_feature_aa64_wfxt(const ARMISARegisters *id) 587 { 588 return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, WFXT) >= 2; 589 } 590 591 static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id) 592 { 593 return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0; 594 } 595 596 static inline bool isar_feature_aa64_mops(const ARMISARegisters *id) 597 { 598 return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS); 599 } 600 601 static inline bool isar_feature_aa64_rpres(const ARMISARegisters *id) 602 { 603 return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, RPRES); 604 } 605 606 static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id) 607 { 608 /* We always set the AdvSIMD and FP fields identically. */ 609 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf; 610 } 611 612 static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id) 613 { 614 /* We always set the AdvSIMD and FP fields identically wrt FP16. */ 615 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; 616 } 617 618 static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id) 619 { 620 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2; 621 } 622 623 static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id) 624 { 625 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2; 626 } 627 628 static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id) 629 { 630 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2; 631 } 632 633 static inline bool isar_feature_aa64_ras(const ARMISARegisters *id) 634 { 635 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0; 636 } 637 638 static inline bool isar_feature_aa64_doublefault(const ARMISARegisters *id) 639 { 640 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) >= 2; 641 } 642 643 static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) 644 { 645 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; 646 } 647 648 static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id) 649 { 650 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0; 651 } 652 653 static inline bool isar_feature_aa64_rme(const ARMISARegisters *id) 654 { 655 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0; 656 } 657 658 static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) 659 { 660 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; 661 } 662 663 static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id) 664 { 665 int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2); 666 if (key >= 2) { 667 return true; /* FEAT_CSV2_2 */ 668 } 669 if (key == 1) { 670 key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC); 671 return key >= 2; /* FEAT_CSV2_1p2 */ 672 } 673 return false; 674 } 675 676 static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id) 677 { 678 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0; 679 } 680 681 static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) 682 { 683 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; 684 } 685 686 static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id) 687 { 688 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0; 689 } 690 691 static inline bool isar_feature_aa64_mte(const ARMISARegisters *id) 692 { 693 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2; 694 } 695 696 static inline bool isar_feature_aa64_mte3(const ARMISARegisters *id) 697 { 698 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 3; 699 } 700 701 static inline bool isar_feature_aa64_sme(const ARMISARegisters *id) 702 { 703 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0; 704 } 705 706 static inline bool isar_feature_aa64_nmi(const ARMISARegisters *id) 707 { 708 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, NMI) != 0; 709 } 710 711 static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) 712 { 713 return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1; 714 } 715 716 static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id) 717 { 718 unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); 719 return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id)); 720 } 721 722 static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id) 723 { 724 return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2; 725 } 726 727 static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id) 728 { 729 unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); 730 return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id)); 731 } 732 733 static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id) 734 { 735 return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0; 736 } 737 738 static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id) 739 { 740 return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1; 741 } 742 743 static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id) 744 { 745 return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0; 746 } 747 748 static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id) 749 { 750 unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); 751 return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id)); 752 } 753 754 static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id) 755 { 756 unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); 757 return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id)); 758 } 759 760 static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id) 761 { 762 unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2); 763 return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id)); 764 } 765 766 static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id) 767 { 768 return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0; 769 } 770 771 static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id) 772 { 773 return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0; 774 } 775 776 static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id) 777 { 778 return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1; 779 } 780 781 static inline bool isar_feature_aa64_vh(const ARMISARegisters *id) 782 { 783 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0; 784 } 785 786 static inline bool isar_feature_aa64_lor(const ARMISARegisters *id) 787 { 788 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0; 789 } 790 791 static inline bool isar_feature_aa64_pan(const ARMISARegisters *id) 792 { 793 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0; 794 } 795 796 static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id) 797 { 798 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2; 799 } 800 801 static inline bool isar_feature_aa64_pan3(const ARMISARegisters *id) 802 { 803 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 3; 804 } 805 806 static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id) 807 { 808 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0; 809 } 810 811 static inline bool isar_feature_aa64_afp(const ARMISARegisters *id) 812 { 813 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, AFP) != 0; 814 } 815 816 static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id) 817 { 818 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, TIDCP1) != 0; 819 } 820 821 static inline bool isar_feature_aa64_cmow(const ARMISARegisters *id) 822 { 823 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, CMOW) != 0; 824 } 825 826 static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id) 827 { 828 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0; 829 } 830 831 static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id) 832 { 833 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) >= 2; 834 } 835 836 static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) 837 { 838 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; 839 } 840 841 static inline bool isar_feature_aa64_uao(const ARMISARegisters *id) 842 { 843 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0; 844 } 845 846 static inline bool isar_feature_aa64_st(const ARMISARegisters *id) 847 { 848 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0; 849 } 850 851 static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id) 852 { 853 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, AT) != 0; 854 } 855 856 static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id) 857 { 858 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, FWB) != 0; 859 } 860 861 static inline bool isar_feature_aa64_ids(const ARMISARegisters *id) 862 { 863 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, IDS) != 0; 864 } 865 866 static inline bool isar_feature_aa64_half_evt(const ARMISARegisters *id) 867 { 868 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 1; 869 } 870 871 static inline bool isar_feature_aa64_evt(const ARMISARegisters *id) 872 { 873 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 2; 874 } 875 876 static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) 877 { 878 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; 879 } 880 881 static inline bool isar_feature_aa64_lva(const ARMISARegisters *id) 882 { 883 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0; 884 } 885 886 static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id) 887 { 888 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0; 889 } 890 891 static inline bool isar_feature_aa64_nv(const ARMISARegisters *id) 892 { 893 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, NV) != 0; 894 } 895 896 static inline bool isar_feature_aa64_nv2(const ARMISARegisters *id) 897 { 898 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, NV) >= 2; 899 } 900 901 static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id) 902 { 903 return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && 904 FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; 905 } 906 907 static inline bool isar_feature_aa64_pmuv3p4(const ARMISARegisters *id) 908 { 909 return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 && 910 FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; 911 } 912 913 static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id) 914 { 915 return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 6 && 916 FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; 917 } 918 919 static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id) 920 { 921 return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8; 922 } 923 924 static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id) 925 { 926 return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0; 927 } 928 929 static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id) 930 { 931 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0; 932 } 933 934 static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id) 935 { 936 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) != 0; 937 } 938 939 static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id) 940 { 941 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) >= 2; 942 } 943 944 static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id) 945 { 946 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BITPERM) != 0; 947 } 948 949 static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id) 950 { 951 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BFLOAT16) != 0; 952 } 953 954 static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id) 955 { 956 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SHA3) != 0; 957 } 958 959 static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id) 960 { 961 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SM4) != 0; 962 } 963 964 static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) 965 { 966 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, I8MM) != 0; 967 } 968 969 static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id) 970 { 971 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F32MM) != 0; 972 } 973 974 static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id) 975 { 976 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F64MM) != 0; 977 } 978 979 static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id) 980 { 981 return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, F64F64); 982 } 983 984 static inline bool isar_feature_aa64_sme_i16i64(const ARMISARegisters *id) 985 { 986 return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, I16I64) == 0xf; 987 } 988 989 static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id) 990 { 991 return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, FA64); 992 } 993 994 /* 995 * Feature tests for "does this exist in either 32-bit or 64-bit?" 996 */ 997 static inline bool isar_feature_any_fp16(const ARMISARegisters *id) 998 { 999 return isar_feature_aa64_fp16(id) || isar_feature_aa32_fp16_arith(id); 1000 } 1001 1002 static inline bool isar_feature_any_predinv(const ARMISARegisters *id) 1003 { 1004 return isar_feature_aa64_predinv(id) || isar_feature_aa32_predinv(id); 1005 } 1006 1007 static inline bool isar_feature_any_pmuv3p1(const ARMISARegisters *id) 1008 { 1009 return isar_feature_aa64_pmuv3p1(id) || isar_feature_aa32_pmuv3p1(id); 1010 } 1011 1012 static inline bool isar_feature_any_pmuv3p4(const ARMISARegisters *id) 1013 { 1014 return isar_feature_aa64_pmuv3p4(id) || isar_feature_aa32_pmuv3p4(id); 1015 } 1016 1017 static inline bool isar_feature_any_pmuv3p5(const ARMISARegisters *id) 1018 { 1019 return isar_feature_aa64_pmuv3p5(id) || isar_feature_aa32_pmuv3p5(id); 1020 } 1021 1022 static inline bool isar_feature_any_ccidx(const ARMISARegisters *id) 1023 { 1024 return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id); 1025 } 1026 1027 static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id) 1028 { 1029 return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id); 1030 } 1031 1032 static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id) 1033 { 1034 return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id); 1035 } 1036 1037 static inline bool isar_feature_any_ras(const ARMISARegisters *id) 1038 { 1039 return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id); 1040 } 1041 1042 static inline bool isar_feature_any_half_evt(const ARMISARegisters *id) 1043 { 1044 return isar_feature_aa64_half_evt(id) || isar_feature_aa32_half_evt(id); 1045 } 1046 1047 static inline bool isar_feature_any_evt(const ARMISARegisters *id) 1048 { 1049 return isar_feature_aa64_evt(id) || isar_feature_aa32_evt(id); 1050 } 1051 1052 typedef enum { 1053 CCSIDR_FORMAT_LEGACY, 1054 CCSIDR_FORMAT_CCIDX, 1055 } CCSIDRFormat; 1056 1057 static inline uint64_t make_ccsidr(CCSIDRFormat format, unsigned assoc, 1058 unsigned linesize, unsigned cachesize, 1059 uint8_t flags) 1060 { 1061 unsigned lg_linesize = ctz32(linesize); 1062 unsigned sets; 1063 uint64_t ccsidr = 0; 1064 1065 assert(assoc != 0); 1066 assert(is_power_of_2(linesize)); 1067 assert(lg_linesize >= 4 && lg_linesize <= 7 + 4); 1068 1069 /* sets * associativity * linesize == cachesize. */ 1070 sets = cachesize / (assoc * linesize); 1071 assert(cachesize % (assoc * linesize) == 0); 1072 1073 if (format == CCSIDR_FORMAT_LEGACY) { 1074 /* 1075 * The 32-bit CCSIDR format is: 1076 * [27:13] number of sets - 1 1077 * [12:3] associativity - 1 1078 * [2:0] log2(linesize) - 4 1079 * so 0 == 16 bytes, 1 == 32 bytes, 2 == 64 bytes, etc 1080 */ 1081 ccsidr = deposit32(ccsidr, 28, 4, flags); 1082 ccsidr = deposit32(ccsidr, 13, 15, sets - 1); 1083 ccsidr = deposit32(ccsidr, 3, 10, assoc - 1); 1084 ccsidr = deposit32(ccsidr, 0, 3, lg_linesize - 4); 1085 } else { 1086 /* 1087 * The 64-bit CCSIDR_EL1 format is: 1088 * [55:32] number of sets - 1 1089 * [23:3] associativity - 1 1090 * [2:0] log2(linesize) - 4 1091 * so 0 == 16 bytes, 1 == 32 bytes, 2 == 64 bytes, etc 1092 */ 1093 ccsidr = deposit64(ccsidr, 32, 24, sets - 1); 1094 ccsidr = deposit64(ccsidr, 3, 21, assoc - 1); 1095 ccsidr = deposit64(ccsidr, 0, 3, lg_linesize - 4); 1096 } 1097 1098 return ccsidr; 1099 } 1100 1101 /* 1102 * Forward to the above feature tests given an ARMCPU pointer. 1103 */ 1104 #define cpu_isar_feature(name, cpu) \ 1105 ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); }) 1106 1107 #endif 1108