| 1 | /* |
| 2 | * ARM hflags |
| 3 | * |
| 4 | * This code is licensed under the GNU GPL v2 or later. |
| 5 | * |
| 6 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 7 | */ |
| 8 | #include "qemu/osdep.h" |
| 9 | #include "cpu.h" |
| 10 | #include "helper.h" |
| 11 | #include "internals.h" |
| 12 | #include "cpu-features.h" |
| 13 | #include "exec/translation-block.h" |
| 14 | #include "accel/tcg/cpu-ops.h" |
| 15 | #include "cpregs.h" |
| 16 | |
| 17 | static inline bool fgt_svc(CPUARMState *env, int el) |
| 18 | { |
| 19 | /* |
| 20 | * Assuming fine-grained-traps are active, return true if we |
| 21 | * should be trapping on SVC instructions. Only AArch64 can |
| 22 | * trap on an SVC at EL1, but we don't need to special-case this |
| 23 | * because if this is AArch32 EL1 then arm_fgt_active() is false. |
| 24 | * We also know el is 0 or 1. |
| 25 | */ |
| 26 | return el == 0 ? |
| 27 | FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL0) : |
| 28 | FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL1); |
| 29 | } |
| 30 | |
| 31 | /* Return true if memory alignment should be enforced. */ |
| 32 | static bool aprofile_require_alignment(CPUARMState *env, int el, uint64_t sctlr) |
| 33 | { |
| 34 | #ifdef CONFIG_USER_ONLY |
| 35 | return false; |
| 36 | #else |
| 37 | /* Check the alignment enable bit. */ |
| 38 | if (sctlr & SCTLR_A) { |
| 39 | return true; |
| 40 | } |
| 41 | |
| 42 | /* |
| 43 | * With PMSA, when the MPU is disabled, all memory types in the |
| 44 | * default map are Normal, so don't need aligment enforcing. |
| 45 | */ |
| 46 | if (arm_feature(env, ARM_FEATURE_PMSA)) { |
| 47 | return false; |
| 48 | } |
| 49 | |
| 50 | /* |
| 51 | * Pre-v6 had a completely different model for unaligned accesses, |
| 52 | * which doesn't include taking unaligned faults for Device memory. |
| 53 | * v6 has the new model only when SCTLR.U is set. Later architecture |
| 54 | * versions repurpose the SCTLR bit for something else, so we mustn't |
| 55 | * test it except for actual v6 CPUs. |
| 56 | */ |
| 57 | if (!arm_feature(env, ARM_FEATURE_V6) || |
| 58 | (!arm_feature(env, ARM_FEATURE_V7) && !(sctlr & SCTLR_U))) { |
| 59 | return false; |
| 60 | } |
| 61 | |
| 62 | /* |
| 63 | * With VMSA, if translation is disabled, then the default memory type |
| 64 | * is Device(-nGnRnE) instead of Normal, which requires that alignment |
| 65 | * be enforced. Since this affects all ram, it is most efficient |
| 66 | * to handle this during translation. |
| 67 | */ |
| 68 | if (sctlr & SCTLR_M) { |
| 69 | /* Translation enabled: memory type in PTE via MAIR_ELx. */ |
| 70 | return false; |
| 71 | } |
| 72 | if (el < 2 && (arm_hcr_el2_eff(env) & (HCR_DC | HCR_VM))) { |
| 73 | /* Stage 2 translation enabled: memory type in PTE. */ |
| 74 | return false; |
| 75 | } |
| 76 | return true; |
| 77 | #endif |
| 78 | } |
| 79 | |
| 80 | bool access_secure_reg(CPUARMState *env) |
| 81 | { |
| 82 | bool ret = (arm_feature(env, ARM_FEATURE_EL3) && |
| 83 | !arm_el_is_aa64(env, 3) && |
| 84 | !(env->cp15.scr_el3 & SCR_NS)); |
| 85 | |
| 86 | return ret; |
| 87 | } |
| 88 | |
| 89 | static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el, |
| 90 | ARMMMUIdx mmu_idx, |
| 91 | CPUARMTBFlags flags) |
| 92 | { |
| 93 | DP_TBFLAG_ANY(flags, FPEXC_EL, fp_el); |
| 94 | DP_TBFLAG_ANY(flags, MMUIDX, arm_to_core_mmu_idx(mmu_idx)); |
| 95 | |
| 96 | if (arm_singlestep_active(env)) { |
| 97 | DP_TBFLAG_ANY(flags, SS_ACTIVE, 1); |
| 98 | } |
| 99 | |
| 100 | return flags; |
| 101 | } |
| 102 | |
| 103 | static CPUARMTBFlags rebuild_hflags_common_32(CPUARMState *env, int fp_el, |
| 104 | ARMMMUIdx mmu_idx, |
| 105 | CPUARMTBFlags flags) |
| 106 | { |
| 107 | bool sctlr_b = arm_sctlr_b(env); |
| 108 | |
| 109 | if (sctlr_b) { |
| 110 | DP_TBFLAG_A32(flags, SCTLR__B, 1); |
| 111 | } |
| 112 | if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) { |
| 113 | DP_TBFLAG_ANY(flags, BE_DATA, 1); |
| 114 | } |
| 115 | DP_TBFLAG_A32(flags, NS, !access_secure_reg(env)); |
| 116 | |
| 117 | return rebuild_hflags_common(env, fp_el, mmu_idx, flags); |
| 118 | } |
| 119 | |
| 120 | static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el, |
| 121 | ARMMMUIdx mmu_idx) |
| 122 | { |
| 123 | CPUARMTBFlags flags = {}; |
| 124 | uint32_t ccr = env->v7m.ccr[env->v7m.secure]; |
| 125 | |
| 126 | /* Without HaveMainExt, CCR.UNALIGN_TRP is RES1. */ |
| 127 | if (ccr & R_V7M_CCR_UNALIGN_TRP_MASK) { |
| 128 | DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); |
| 129 | } |
| 130 | |
| 131 | if (arm_v7m_is_handler_mode(env)) { |
| 132 | DP_TBFLAG_M32(flags, HANDLER, 1); |
| 133 | } |
| 134 | |
| 135 | /* |
| 136 | * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN |
| 137 | * is suppressing them because the requested execution priority |
| 138 | * is less than 0. |
| 139 | */ |
| 140 | if (arm_feature(env, ARM_FEATURE_V8) && |
| 141 | !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) && |
| 142 | (ccr & R_V7M_CCR_STKOFHFNMIGN_MASK))) { |
| 143 | DP_TBFLAG_M32(flags, STACKCHECK, 1); |
| 144 | } |
| 145 | |
| 146 | if (arm_feature(env, ARM_FEATURE_M_SECURITY) && env->v7m.secure) { |
| 147 | DP_TBFLAG_M32(flags, SECURE, 1); |
| 148 | } |
| 149 | |
| 150 | return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); |
| 151 | } |
| 152 | |
| 153 | /* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */ |
| 154 | static bool sme_fa64(CPUARMState *env, int el) |
| 155 | { |
| 156 | if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) { |
| 157 | return false; |
| 158 | } |
| 159 | |
| 160 | if (el <= 1 && !el_is_in_host(env, el)) { |
| 161 | if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) { |
| 162 | return false; |
| 163 | } |
| 164 | } |
| 165 | if (el <= 2 && arm_is_el2_enabled(env)) { |
| 166 | if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) { |
| 167 | return false; |
| 168 | } |
| 169 | } |
| 170 | if (arm_feature(env, ARM_FEATURE_EL3)) { |
| 171 | if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) { |
| 172 | return false; |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | return true; |
| 177 | } |
| 178 | |
| 179 | static int neon_exception_el(CPUARMState *env, int cur_el) |
| 180 | { |
| 181 | /* |
| 182 | * Return the EL to trap to for A32 Neon specific traps |
| 183 | * (CPACR.ASEDIS and HCPTR.TASE). In the pseudocode these are |
| 184 | * checked in the same function as the more general trap bits that |
| 185 | * we handle in fp_exception_el(). Fortunately it is always the |
| 186 | * case that if the trap/enable bits specify taking an exception |
| 187 | * to different ELs for the Neon-specific insns and the general fp |
| 188 | * insns then the trap to the lower of the two ELs has priority, |
| 189 | * so we can calculate the two target ELs separately and pick the |
| 190 | * right destination later. Compare AArch32_CheckAdvSIMDOrFPEnabled(). |
| 191 | * |
| 192 | * CPACR doesn't exist before v6, but neither does Neon, so we can |
| 193 | * assume that if we're here testing this then the register exists. |
| 194 | * HCPTR always exists if EL2 is present. |
| 195 | */ |
| 196 | uint64_t hcr_el2 = arm_hcr_el2_eff(env); |
| 197 | bool cpacr_asedis = FIELD_EX64(env->cp15.cpacr_el1, CPACR, ASEDIS); |
| 198 | bool hcptr_tase = FIELD_EX64(env->cp15.cptr_el[2], HCPTR, TASE); |
| 199 | bool have_aarch32_el3 = |
| 200 | arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3); |
| 201 | |
| 202 | if (!arm_feature(env, ARM_FEATURE_NEON_TRAPS)) { |
| 203 | /* This CPU doesn't implement the trap bits (Cortex-A8) */ |
| 204 | return 0; |
| 205 | } |
| 206 | |
| 207 | if (arm_feature(env, ARM_FEATURE_EL2) && arm_el_is_aa64(env, 2)) { |
| 208 | /* |
| 209 | * The AArch64 CPTR_EL2 has no equivalent to HCPTR.TASE; only |
| 210 | * an AArch32 EL2 can trap Neon specifically. |
| 211 | */ |
| 212 | hcptr_tase = false; |
| 213 | } |
| 214 | |
| 215 | /* |
| 216 | * We know we're in AArch32, but if this is EL0 and EL1 is AArch64 |
| 217 | * then CPACR_EL1 applies rather than CPACR, and it doesn't have |
| 218 | * ASEDIS (instead using the same bit for TCPAC). |
| 219 | */ |
| 220 | if (cur_el == 0 && arm_el_is_aa64(env, 1)) { |
| 221 | cpacr_asedis = false; |
| 222 | } |
| 223 | |
| 224 | /* CPACR is ignored if E2H+TGE are both set */ |
| 225 | if ((hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) { |
| 226 | cpacr_asedis = false; |
| 227 | } |
| 228 | |
| 229 | /* |
| 230 | * NSACR.NSASEDIS makes the effective values of HCPTR.TASE and |
| 231 | * CPACR.ASEDIS be 1 in NonSecure state. NSACR has no |
| 232 | * effect unless EL3 exists and is AArch32. |
| 233 | */ |
| 234 | if (have_aarch32_el3 && cur_el <= 2 && !arm_is_secure_below_el3(env)) { |
| 235 | if (FIELD_EX32(env->cp15.nsacr, NSACR, NSASEDIS)) { |
| 236 | cpacr_asedis = true; |
| 237 | hcptr_tase = true; |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | if (cpacr_asedis) { |
| 242 | if (have_aarch32_el3 && (cur_el == 3 || arm_is_secure_below_el3(env))) { |
| 243 | /* Trap from Secure PL0 or PL1 to Secure PL1 */ |
| 244 | return 3; |
| 245 | } |
| 246 | if (cur_el <= 1) { |
| 247 | /* trap from EL0 or EL1 to EL1 */ |
| 248 | return 1; |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | /* HCPTR.TASE traps to EL2, including for execution at EL2 */ |
| 253 | if (hcptr_tase && cur_el <= 2) { |
| 254 | return 2; |
| 255 | } |
| 256 | return 0; |
| 257 | } |
| 258 | |
| 259 | static bool arm_d32dis(CPUARMState *env, int cur_el) |
| 260 | { |
| 261 | bool cpacr_d32dis = FIELD_EX64(env->cp15.cpacr_el1, CPACR, D32DIS); |
| 262 | |
| 263 | if (!arm_feature(env, ARM_FEATURE_D32DIS)) { |
| 264 | return false; |
| 265 | } |
| 266 | |
| 267 | /* If NSACR.NSD32DIS is set, CPACR.D32DIS acts as 1 in NonSecure */ |
| 268 | if ((arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) && |
| 269 | cur_el <= 2 && !arm_is_secure_below_el3(env))) { |
| 270 | if (FIELD_EX32(env->cp15.nsacr, NSACR, NSD32DIS)) { |
| 271 | cpacr_d32dis = true; |
| 272 | } |
| 273 | } |
| 274 | return cpacr_d32dis; |
| 275 | } |
| 276 | |
| 277 | static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, |
| 278 | ARMMMUIdx mmu_idx) |
| 279 | { |
| 280 | CPUARMTBFlags flags = {}; |
| 281 | int el = arm_current_el(env); |
| 282 | uint64_t sctlr = arm_sctlr(env, el); |
| 283 | |
| 284 | if (aprofile_require_alignment(env, el, sctlr)) { |
| 285 | DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); |
| 286 | } |
| 287 | |
| 288 | if (arm_el_is_aa64(env, 1)) { |
| 289 | DP_TBFLAG_A32(flags, VFPEN, 1); |
| 290 | } |
| 291 | |
| 292 | if (el < 2 && env->cp15.hstr_el2 && arm_is_el2_enabled(env) && |
| 293 | (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) { |
| 294 | DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1); |
| 295 | } |
| 296 | |
| 297 | if (arm_fgt_active(env, el)) { |
| 298 | DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1); |
| 299 | if (fgt_svc(env, el)) { |
| 300 | DP_TBFLAG_ANY(flags, FGT_SVC, 1); |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | if (env->uncached_cpsr & CPSR_IL) { |
| 305 | DP_TBFLAG_ANY(flags, PSTATE__IL, 1); |
| 306 | } |
| 307 | |
| 308 | /* |
| 309 | * The SME exception we are testing for is raised via |
| 310 | * AArch64.CheckFPAdvSIMDEnabled(), as called from |
| 311 | * AArch32.CheckAdvSIMDOrFPEnabled(). |
| 312 | */ |
| 313 | if (el == 0 |
| 314 | && FIELD_EX64(env->svcr, SVCR, SM) |
| 315 | && (!arm_is_el2_enabled(env) |
| 316 | || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE))) |
| 317 | && arm_el_is_aa64(env, 1) |
| 318 | && !sme_fa64(env, el)) { |
| 319 | DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1); |
| 320 | } |
| 321 | |
| 322 | DP_TBFLAG_A32(flags, NEONEXC_EL, neon_exception_el(env, el)); |
| 323 | |
| 324 | DP_TBFLAG_A32(flags, D32DIS, arm_d32dis(env, el)); |
| 325 | |
| 326 | return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); |
| 327 | } |
| 328 | |
| 329 | /* |
| 330 | * Return the exception level to which exceptions should be taken for ZT0. |
| 331 | * C.f. the ARM pseudocode function CheckSMEZT0Enabled, after the ZA check. |
| 332 | */ |
| 333 | static int zt0_exception_el(CPUARMState *env, int el) |
| 334 | { |
| 335 | #ifndef CONFIG_USER_ONLY |
| 336 | if (el <= 1 |
| 337 | && !el_is_in_host(env, el) |
| 338 | && !FIELD_EX64(env->vfp.smcr_el[1], SMCR, EZT0)) { |
| 339 | return 1; |
| 340 | } |
| 341 | if (el <= 2 |
| 342 | && arm_is_el2_enabled(env) |
| 343 | && !FIELD_EX64(env->vfp.smcr_el[2], SMCR, EZT0)) { |
| 344 | return 2; |
| 345 | } |
| 346 | if (arm_feature(env, ARM_FEATURE_EL3) |
| 347 | && !FIELD_EX64(env->vfp.smcr_el[3], SMCR, EZT0)) { |
| 348 | return 3; |
| 349 | } |
| 350 | #endif |
| 351 | return 0; |
| 352 | } |
| 353 | |
| 354 | /* |
| 355 | * Return the exception level to which exceptions should be taken for FPMR. |
| 356 | * Compare the EnFPM bits in the "Accessing FPMR" pseudocode. Note that |
| 357 | * the floating-point enabled check will be handled separately. |
| 358 | */ |
| 359 | static int fpmr_exception_el(CPUARMState *env, int el) |
| 360 | { |
| 361 | switch (el) { |
| 362 | case 0: |
| 363 | if (el_is_in_host(env, 0)) { |
| 364 | if (!(env->cp15.sctlr_el[2] & SCTLR_EnFPM)) { |
| 365 | return 2; |
| 366 | } |
| 367 | break; |
| 368 | } |
| 369 | if (!(env->cp15.sctlr_el[1] & SCTLR_EnFPM)) { |
| 370 | return 1; |
| 371 | } |
| 372 | /* fall through */ |
| 373 | case 1: |
| 374 | if (!(arm_hcrx_el2_eff(env) & HCRX_ENFPM)) { |
| 375 | return 2; |
| 376 | } |
| 377 | break; |
| 378 | case 2: |
| 379 | break; |
| 380 | case 3: |
| 381 | return 0; |
| 382 | default: |
| 383 | g_assert_not_reached(); |
| 384 | } |
| 385 | if (arm_feature(env, ARM_FEATURE_EL3) |
| 386 | && !(env->cp15.scr_el3 & SCR_ENFPM)) { |
| 387 | return 3; |
| 388 | } |
| 389 | return 0; |
| 390 | } |
| 391 | |
| 392 | static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, |
| 393 | ARMMMUIdx mmu_idx) |
| 394 | { |
| 395 | CPUARMTBFlags flags = {}; |
| 396 | ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx); |
| 397 | uint64_t tcr = regime_tcr(env, mmu_idx); |
| 398 | uint64_t hcr = arm_hcr_el2_eff(env); |
| 399 | uint64_t sctlr; |
| 400 | int tbii, tbid, mtx; |
| 401 | |
| 402 | DP_TBFLAG_ANY(flags, AARCH64_STATE, 1); |
| 403 | |
| 404 | /* Get control bits for tagged addresses. */ |
| 405 | tbid = aa64_va_parameter_tbi(tcr, mmu_idx); |
| 406 | tbii = tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx); |
| 407 | mtx = cpu_isar_feature(aa64_mte_mtx, env_archcpu(env)) ? |
| 408 | aa64_va_parameter_mtx(tcr, mmu_idx) : |
| 409 | 0; |
| 410 | |
| 411 | DP_TBFLAG_A64(flags, TBII, tbii); |
| 412 | DP_TBFLAG_A64(flags, TBID, tbid); |
| 413 | |
| 414 | /* E2H is used by both VHE and NV2. */ |
| 415 | if (hcr & HCR_E2H) { |
| 416 | DP_TBFLAG_A64(flags, E2H, 1); |
| 417 | } |
| 418 | |
| 419 | if (cpu_isar_feature(aa64_sve, env_archcpu(env))) { |
| 420 | int sve_el = sve_exception_el(env, el); |
| 421 | |
| 422 | /* |
| 423 | * If either FP or SVE are disabled, translator does not need len. |
| 424 | * If SVE EL > FP EL, FP exception has precedence, and translator |
| 425 | * does not need SVE EL. Save potential re-translations by forcing |
| 426 | * the unneeded data to zero. |
| 427 | */ |
| 428 | if (fp_el != 0) { |
| 429 | if (sve_el > fp_el) { |
| 430 | sve_el = 0; |
| 431 | } |
| 432 | } else if (sve_el == 0) { |
| 433 | DP_TBFLAG_A64(flags, VL, sve_vqm1_for_el(env, el)); |
| 434 | } |
| 435 | DP_TBFLAG_A64(flags, SVEEXC_EL, sve_el); |
| 436 | } |
| 437 | if (cpu_isar_feature(aa64_sme, env_archcpu(env))) { |
| 438 | int sme_el = sme_exception_el(env, el); |
| 439 | bool sm = FIELD_EX64(env->svcr, SVCR, SM); |
| 440 | |
| 441 | DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el); |
| 442 | if (sme_el == 0) { |
| 443 | /* Similarly, do not compute SVL if SME is disabled. */ |
| 444 | int svl = sve_vqm1_for_el_sm(env, el, true); |
| 445 | DP_TBFLAG_A64(flags, SVL, svl); |
| 446 | if (sm) { |
| 447 | /* If SVE is disabled, we will not have set VL above. */ |
| 448 | DP_TBFLAG_A64(flags, VL, svl); |
| 449 | } |
| 450 | } |
| 451 | if (sm) { |
| 452 | DP_TBFLAG_A64(flags, PSTATE_SM, 1); |
| 453 | DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el)); |
| 454 | } |
| 455 | |
| 456 | if (FIELD_EX64(env->svcr, SVCR, ZA)) { |
| 457 | DP_TBFLAG_A64(flags, PSTATE_ZA, 1); |
| 458 | if (cpu_isar_feature(aa64_sme2, env_archcpu(env))) { |
| 459 | int zt0_el = zt0_exception_el(env, el); |
| 460 | DP_TBFLAG_A64(flags, ZT0EXC_EL, zt0_el); |
| 461 | } |
| 462 | } |
| 463 | } |
| 464 | |
| 465 | sctlr = regime_sctlr(env, stage1); |
| 466 | |
| 467 | if (aprofile_require_alignment(env, el, sctlr)) { |
| 468 | DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); |
| 469 | } |
| 470 | |
| 471 | if (arm_cpu_data_is_big_endian_a64(el, sctlr)) { |
| 472 | DP_TBFLAG_ANY(flags, BE_DATA, 1); |
| 473 | } |
| 474 | |
| 475 | if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) { |
| 476 | /* |
| 477 | * In order to save space in flags, we record only whether |
| 478 | * pauth is "inactive", meaning all insns are implemented as |
| 479 | * a nop, or "active" when some action must be performed. |
| 480 | * The decision of which action to take is left to a helper. |
| 481 | */ |
| 482 | if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) { |
| 483 | DP_TBFLAG_A64(flags, PAUTH_ACTIVE, 1); |
| 484 | } |
| 485 | } |
| 486 | |
| 487 | if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { |
| 488 | /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */ |
| 489 | if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) { |
| 490 | DP_TBFLAG_A64(flags, BT, 1); |
| 491 | } |
| 492 | } |
| 493 | |
| 494 | if (cpu_isar_feature(aa64_lse2, env_archcpu(env))) { |
| 495 | if (sctlr & SCTLR_nAA) { |
| 496 | DP_TBFLAG_A64(flags, NAA, 1); |
| 497 | } |
| 498 | } |
| 499 | |
| 500 | /* Compute the condition for using AccType_UNPRIV for LDTR et al. */ |
| 501 | if (!(env->pstate & PSTATE_UAO)) { |
| 502 | switch (mmu_idx) { |
| 503 | case ARMMMUIdx_E10_1: |
| 504 | case ARMMMUIdx_E10_1_PAN: |
| 505 | /* FEAT_NV: NV,NV1 == 1,1 means we don't do UNPRIV accesses */ |
| 506 | if ((hcr & (HCR_NV | HCR_NV1)) != (HCR_NV | HCR_NV1)) { |
| 507 | DP_TBFLAG_A64(flags, UNPRIV, 1); |
| 508 | } |
| 509 | break; |
| 510 | case ARMMMUIdx_E20_2: |
| 511 | case ARMMMUIdx_E20_2_PAN: |
| 512 | /* |
| 513 | * Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is |
| 514 | * gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR. |
| 515 | */ |
| 516 | if (env->cp15.hcr_el2 & HCR_TGE) { |
| 517 | DP_TBFLAG_A64(flags, UNPRIV, 1); |
| 518 | } |
| 519 | break; |
| 520 | default: |
| 521 | break; |
| 522 | } |
| 523 | } |
| 524 | |
| 525 | if (env->pstate & PSTATE_IL) { |
| 526 | DP_TBFLAG_ANY(flags, PSTATE__IL, 1); |
| 527 | } |
| 528 | |
| 529 | if (arm_fgt_active(env, el)) { |
| 530 | DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1); |
| 531 | if (FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, ERET)) { |
| 532 | DP_TBFLAG_A64(flags, TRAP_ERET, 1); |
| 533 | } |
| 534 | if (fgt_svc(env, el)) { |
| 535 | DP_TBFLAG_ANY(flags, FGT_SVC, 1); |
| 536 | } |
| 537 | } |
| 538 | |
| 539 | /* |
| 540 | * ERET can also be trapped for FEAT_NV. arm_hcr_el2_eff() takes care |
| 541 | * of "is EL2 enabled" and the NV bit can only be set if FEAT_NV is present. |
| 542 | */ |
| 543 | if (el == 1 && (hcr & HCR_NV)) { |
| 544 | DP_TBFLAG_A64(flags, TRAP_ERET, 1); |
| 545 | DP_TBFLAG_A64(flags, NV, 1); |
| 546 | if (hcr & HCR_NV1) { |
| 547 | DP_TBFLAG_A64(flags, NV1, 1); |
| 548 | } |
| 549 | if (hcr & HCR_NV2) { |
| 550 | DP_TBFLAG_A64(flags, NV2, 1); |
| 551 | if (env->cp15.sctlr_el[2] & SCTLR_EE) { |
| 552 | DP_TBFLAG_A64(flags, NV2_MEM_BE, 1); |
| 553 | } |
| 554 | } |
| 555 | } |
| 556 | |
| 557 | if (cpu_isar_feature(aa64_mte, env_archcpu(env))) { |
| 558 | /* |
| 559 | * Set MTE_ACTIVE if any access may be Checked, and leave clear |
| 560 | * if all accesses must be Unchecked: |
| 561 | * 1) If TBI and MTX are both unset, accesses are Unchecked. |
| 562 | * 2) If Tag Check Override, then all accesses are Unchecked, |
| 563 | * 3) If Tag Check Fail == 0, then Checked access have no effect, |
| 564 | * 4) If no Allocation Tag Access, then all accesses are Unchecked. |
| 565 | */ |
| 566 | if (allocation_tag_access_enabled(env, el, sctlr)) { |
| 567 | DP_TBFLAG_A64(flags, ATA, 1); |
| 568 | if ((tbid || mtx) |
| 569 | && !(env->pstate & PSTATE_TCO) |
| 570 | && (sctlr & (el == 0 ? SCTLR_TCF0 : SCTLR_TCF))) { |
| 571 | DP_TBFLAG_A64(flags, MTE_ACTIVE, 1); |
| 572 | if (!EX_TBFLAG_A64(flags, UNPRIV)) { |
| 573 | /* |
| 574 | * In non-unpriv contexts (eg EL0), unpriv load/stores |
| 575 | * act like normal ones; duplicate the MTE info to |
| 576 | * avoid translate-a64.c having to check UNPRIV to see |
| 577 | * whether it is OK to index into MTE_ACTIVE[]. |
| 578 | */ |
| 579 | DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1); |
| 580 | } |
| 581 | /* |
| 582 | * Repeat for MTE_STORE_ONLY |
| 583 | */ |
| 584 | if ((el == 0 ? SCTLR_TCSO0 : SCTLR_TCSO) & sctlr) { |
| 585 | DP_TBFLAG_A64(flags, MTE_STORE_ONLY, 1); |
| 586 | if (!EX_TBFLAG_A64(flags, UNPRIV)) { |
| 587 | DP_TBFLAG_A64(flags, MTE0_STORE_ONLY, 1); |
| 588 | } |
| 589 | } |
| 590 | } |
| 591 | } |
| 592 | /* And again for unprivileged accesses, if required. */ |
| 593 | if (EX_TBFLAG_A64(flags, UNPRIV) |
| 594 | && (tbid || mtx) |
| 595 | && !(env->pstate & PSTATE_TCO) |
| 596 | && (sctlr & SCTLR_TCF0) |
| 597 | && allocation_tag_access_enabled(env, 0, sctlr)) { |
| 598 | DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1); |
| 599 | if (SCTLR_TCSO0 & sctlr) { |
| 600 | DP_TBFLAG_A64(flags, MTE0_STORE_ONLY, 1); |
| 601 | } |
| 602 | } |
| 603 | /* |
| 604 | * For unpriv tag-setting accesses we also need ATA0. Again, in |
| 605 | * contexts where unpriv and normal insns are the same we |
| 606 | * duplicate the ATA bit to save effort for translate-a64.c. |
| 607 | */ |
| 608 | if (EX_TBFLAG_A64(flags, UNPRIV)) { |
| 609 | if (allocation_tag_access_enabled(env, 0, sctlr)) { |
| 610 | DP_TBFLAG_A64(flags, ATA0, 1); |
| 611 | } |
| 612 | } else { |
| 613 | DP_TBFLAG_A64(flags, ATA0, EX_TBFLAG_A64(flags, ATA)); |
| 614 | } |
| 615 | /* Cache TCMA as well as TBI. */ |
| 616 | DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx)); |
| 617 | /* Cache MTX. */ |
| 618 | DP_TBFLAG_A64(flags, MTX, mtx); |
| 619 | } |
| 620 | |
| 621 | if (cpu_isar_feature(aa64_gcs, env_archcpu(env))) { |
| 622 | /* C.f. GCSEnabled */ |
| 623 | if (env->cp15.gcscr_el[el] & GCSCR_PCRSEL) { |
| 624 | switch (el) { |
| 625 | default: |
| 626 | if (!el_is_in_host(env, el) |
| 627 | && !(arm_hcrx_el2_eff(env) & HCRX_GCSEN)) { |
| 628 | break; |
| 629 | } |
| 630 | /* fall through */ |
| 631 | case 2: |
| 632 | if (arm_feature(env, ARM_FEATURE_EL3) |
| 633 | && !(env->cp15.scr_el3 & SCR_GCSEN)) { |
| 634 | break; |
| 635 | } |
| 636 | /* fall through */ |
| 637 | case 3: |
| 638 | DP_TBFLAG_A64(flags, GCS_EN, 1); |
| 639 | break; |
| 640 | } |
| 641 | } |
| 642 | |
| 643 | /* C.f. GCSReturnValueCheckEnabled */ |
| 644 | if (env->cp15.gcscr_el[el] & GCSCR_RVCHKEN) { |
| 645 | DP_TBFLAG_A64(flags, GCS_RVCEN, 1); |
| 646 | } |
| 647 | |
| 648 | /* C.f. CheckGCSSTREnabled */ |
| 649 | if (!(env->cp15.gcscr_el[el] & GCSCR_STREN)) { |
| 650 | DP_TBFLAG_A64(flags, GCSSTR_EL, el ? el : 1); |
| 651 | } else if (el == 1 |
| 652 | && EX_TBFLAG_ANY(flags, FGT_ACTIVE) |
| 653 | && !FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], |
| 654 | HFGITR_EL2, NGCSSTR_EL1)) { |
| 655 | DP_TBFLAG_A64(flags, GCSSTR_EL, 2); |
| 656 | } |
| 657 | } |
| 658 | |
| 659 | if (env->vfp.fpcr & FPCR_AH) { |
| 660 | DP_TBFLAG_A64(flags, AH, 1); |
| 661 | } |
| 662 | if (env->vfp.fpcr & FPCR_NEP) { |
| 663 | /* |
| 664 | * In streaming-SVE without FA64, NEP behaves as if zero; |
| 665 | * compare pseudocode IsMerging() |
| 666 | */ |
| 667 | if (!(EX_TBFLAG_A64(flags, PSTATE_SM) && !sme_fa64(env, el))) { |
| 668 | DP_TBFLAG_A64(flags, NEP, 1); |
| 669 | } |
| 670 | } |
| 671 | |
| 672 | if (cpu_isar_feature(aa64_fpmr, env_archcpu(env))) { |
| 673 | DP_TBFLAG_A64(flags, FPMR_EL, fpmr_exception_el(env, el)); |
| 674 | } |
| 675 | |
| 676 | return rebuild_hflags_common(env, fp_el, mmu_idx, flags); |
| 677 | } |
| 678 | |
| 679 | static CPUARMTBFlags rebuild_hflags_internal(CPUARMState *env) |
| 680 | { |
| 681 | int el = arm_current_el(env); |
| 682 | int fp_el = fp_exception_el(env, el); |
| 683 | ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); |
| 684 | |
| 685 | if (is_a64(env)) { |
| 686 | return rebuild_hflags_a64(env, el, fp_el, mmu_idx); |
| 687 | } else if (arm_feature(env, ARM_FEATURE_M)) { |
| 688 | return rebuild_hflags_m32(env, fp_el, mmu_idx); |
| 689 | } else { |
| 690 | return rebuild_hflags_a32(env, fp_el, mmu_idx); |
| 691 | } |
| 692 | } |
| 693 | |
| 694 | void arm_rebuild_hflags(CPUARMState *env) |
| 695 | { |
| 696 | env->hflags = rebuild_hflags_internal(env); |
| 697 | } |
| 698 | |
| 699 | /* |
| 700 | * If we have triggered a EL state change we can't rely on the |
| 701 | * translator having passed it to us, we need to recompute. |
| 702 | */ |
| 703 | void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env) |
| 704 | { |
| 705 | int el = arm_current_el(env); |
| 706 | int fp_el = fp_exception_el(env, el); |
| 707 | ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); |
| 708 | |
| 709 | env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx); |
| 710 | } |
| 711 | |
| 712 | void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el) |
| 713 | { |
| 714 | int fp_el = fp_exception_el(env, el); |
| 715 | ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); |
| 716 | |
| 717 | env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx); |
| 718 | } |
| 719 | |
| 720 | /* |
| 721 | * If we have triggered a EL state change we can't rely on the |
| 722 | * translator having passed it to us, we need to recompute. |
| 723 | */ |
| 724 | void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env) |
| 725 | { |
| 726 | int el = arm_current_el(env); |
| 727 | int fp_el = fp_exception_el(env, el); |
| 728 | ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); |
| 729 | env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx); |
| 730 | } |
| 731 | |
| 732 | void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el) |
| 733 | { |
| 734 | int fp_el = fp_exception_el(env, el); |
| 735 | ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); |
| 736 | |
| 737 | env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx); |
| 738 | } |
| 739 | |
| 740 | void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el) |
| 741 | { |
| 742 | int fp_el = fp_exception_el(env, el); |
| 743 | ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el); |
| 744 | |
| 745 | env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx); |
| 746 | } |
| 747 | |
| 748 | static void assert_hflags_rebuild_correctly(CPUARMState *env) |
| 749 | { |
| 750 | #ifdef CONFIG_DEBUG_TCG |
| 751 | CPUARMTBFlags c = env->hflags; |
| 752 | CPUARMTBFlags r = rebuild_hflags_internal(env); |
| 753 | |
| 754 | if (unlikely(c.flags != r.flags || c.flags2 != r.flags2)) { |
| 755 | fprintf(stderr, "TCG hflags mismatch " |
| 756 | "(current:(0x%08x,0x%016" PRIx64 ")" |
| 757 | " rebuilt:(0x%08x,0x%016" PRIx64 ")\n", |
| 758 | c.flags, c.flags2, r.flags, r.flags2); |
| 759 | abort(); |
| 760 | } |
| 761 | #endif |
| 762 | } |
| 763 | |
| 764 | static bool mve_no_pred(CPUARMState *env) |
| 765 | { |
| 766 | /* |
| 767 | * Return true if there is definitely no predication of MVE |
| 768 | * instructions by VPR or LTPSIZE. (Returning false even if there |
| 769 | * isn't any predication is OK; generated code will just be |
| 770 | * a little worse.) |
| 771 | * If the CPU does not implement MVE then this TB flag is always 0. |
| 772 | * |
| 773 | * NOTE: if you change this logic, the "recalculate s->mve_no_pred" |
| 774 | * logic in gen_update_fp_context() needs to be updated to match. |
| 775 | * |
| 776 | * We do not include the effect of the ECI bits here -- they are |
| 777 | * tracked in other TB flags. This simplifies the logic for |
| 778 | * "when did we emit code that changes the MVE_NO_PRED TB flag |
| 779 | * and thus need to end the TB?". |
| 780 | */ |
| 781 | if (cpu_isar_feature(aa32_mve, env_archcpu(env))) { |
| 782 | return false; |
| 783 | } |
| 784 | if (env->v7m.vpr) { |
| 785 | return false; |
| 786 | } |
| 787 | if (env->v7m.ltpsize < 4) { |
| 788 | return false; |
| 789 | } |
| 790 | return true; |
| 791 | } |
| 792 | |
| 793 | TCGTBCPUState arm_get_tb_cpu_state(CPUState *cs) |
| 794 | { |
| 795 | CPUARMState *env = cpu_env(cs); |
| 796 | CPUARMTBFlags flags; |
| 797 | vaddr pc; |
| 798 | |
| 799 | assert_hflags_rebuild_correctly(env); |
| 800 | flags = env->hflags; |
| 801 | |
| 802 | if (EX_TBFLAG_ANY(flags, AARCH64_STATE)) { |
| 803 | pc = env->pc; |
| 804 | if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { |
| 805 | DP_TBFLAG_A64(flags, BTYPE, env->btype); |
| 806 | } |
| 807 | } else { |
| 808 | pc = env->regs[15]; |
| 809 | |
| 810 | if (arm_feature(env, ARM_FEATURE_M)) { |
| 811 | if (arm_feature(env, ARM_FEATURE_M_SECURITY) && |
| 812 | FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) |
| 813 | != env->v7m.secure) { |
| 814 | DP_TBFLAG_M32(flags, FPCCR_S_WRONG, 1); |
| 815 | } |
| 816 | |
| 817 | if ((env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) && |
| 818 | (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) || |
| 819 | (env->v7m.secure && |
| 820 | !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) { |
| 821 | /* |
| 822 | * ASPEN is set, but FPCA/SFPA indicate that there is no |
| 823 | * active FP context; we must create a new FP context before |
| 824 | * executing any FP insn. |
| 825 | */ |
| 826 | DP_TBFLAG_M32(flags, NEW_FP_CTXT_NEEDED, 1); |
| 827 | } |
| 828 | |
| 829 | bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK; |
| 830 | if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) { |
| 831 | DP_TBFLAG_M32(flags, LSPACT, 1); |
| 832 | } |
| 833 | |
| 834 | if (mve_no_pred(env)) { |
| 835 | DP_TBFLAG_M32(flags, MVE_NO_PRED, 1); |
| 836 | } |
| 837 | } else { |
| 838 | /* Note that VECLEN+VECSTRIDE are RES0 for M-profile. */ |
| 839 | DP_TBFLAG_A32(flags, VECLEN, env->vfp.vec_len); |
| 840 | DP_TBFLAG_A32(flags, VECSTRIDE, env->vfp.vec_stride); |
| 841 | if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) { |
| 842 | DP_TBFLAG_A32(flags, VFPEN, 1); |
| 843 | } |
| 844 | } |
| 845 | |
| 846 | DP_TBFLAG_AM32(flags, THUMB, env->thumb); |
| 847 | DP_TBFLAG_AM32(flags, CONDEXEC, env->condexec_bits); |
| 848 | } |
| 849 | |
| 850 | /* |
| 851 | * The SS_ACTIVE and PSTATE_SS bits correspond to the state machine |
| 852 | * states defined in the ARM ARM for software singlestep: |
| 853 | * SS_ACTIVE PSTATE.SS State |
| 854 | * 0 x Inactive (the TB flag for SS is always 0) |
| 855 | * 1 0 Active-pending |
| 856 | * 1 1 Active-not-pending |
| 857 | * SS_ACTIVE is set in hflags; PSTATE__SS is computed every TB. |
| 858 | */ |
| 859 | if (EX_TBFLAG_ANY(flags, SS_ACTIVE) && (env->pstate & PSTATE_SS)) { |
| 860 | DP_TBFLAG_ANY(flags, PSTATE__SS, 1); |
| 861 | } |
| 862 | |
| 863 | return (TCGTBCPUState){ |
| 864 | .pc = pc, |
| 865 | .flags = flags.flags, |
| 866 | .cs_base = flags.flags2, |
| 867 | }; |
| 868 | } |