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