1 /* 2 * Helpers for TLBI insns 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 "exec/exec-all.h" 10 #include "cpu.h" 11 #include "internals.h" 12 #include "cpu-features.h" 13 #include "cpregs.h" 14 15 /* IS variants of TLB operations must affect all cores */ 16 static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 17 uint64_t value) 18 { 19 CPUState *cs = env_cpu(env); 20 21 tlb_flush_all_cpus_synced(cs); 22 } 23 24 static void tlbiasid_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 25 uint64_t value) 26 { 27 CPUState *cs = env_cpu(env); 28 29 tlb_flush_all_cpus_synced(cs); 30 } 31 32 static void tlbimva_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 33 uint64_t value) 34 { 35 CPUState *cs = env_cpu(env); 36 37 tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK); 38 } 39 40 static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 41 uint64_t value) 42 { 43 CPUState *cs = env_cpu(env); 44 45 tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK); 46 } 47 48 static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri, 49 uint64_t value) 50 { 51 /* Invalidate all (TLBIALL) */ 52 CPUState *cs = env_cpu(env); 53 54 if (tlb_force_broadcast(env)) { 55 tlb_flush_all_cpus_synced(cs); 56 } else { 57 tlb_flush(cs); 58 } 59 } 60 61 static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri, 62 uint64_t value) 63 { 64 /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */ 65 CPUState *cs = env_cpu(env); 66 67 value &= TARGET_PAGE_MASK; 68 if (tlb_force_broadcast(env)) { 69 tlb_flush_page_all_cpus_synced(cs, value); 70 } else { 71 tlb_flush_page(cs, value); 72 } 73 } 74 75 static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri, 76 uint64_t value) 77 { 78 /* Invalidate by ASID (TLBIASID) */ 79 CPUState *cs = env_cpu(env); 80 81 if (tlb_force_broadcast(env)) { 82 tlb_flush_all_cpus_synced(cs); 83 } else { 84 tlb_flush(cs); 85 } 86 } 87 88 static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri, 89 uint64_t value) 90 { 91 /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */ 92 CPUState *cs = env_cpu(env); 93 94 value &= TARGET_PAGE_MASK; 95 if (tlb_force_broadcast(env)) { 96 tlb_flush_page_all_cpus_synced(cs, value); 97 } else { 98 tlb_flush_page(cs, value); 99 } 100 } 101 102 static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, 103 uint64_t value) 104 { 105 CPUState *cs = env_cpu(env); 106 uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12); 107 108 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2); 109 } 110 111 static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 112 uint64_t value) 113 { 114 CPUState *cs = env_cpu(env); 115 uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12); 116 117 tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, 118 ARMMMUIdxBit_E2); 119 } 120 121 static void tlbiipas2_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, 122 uint64_t value) 123 { 124 CPUState *cs = env_cpu(env); 125 uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12; 126 127 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2); 128 } 129 130 static void tlbiipas2is_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, 131 uint64_t value) 132 { 133 CPUState *cs = env_cpu(env); 134 uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12; 135 136 tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2); 137 } 138 139 static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri, 140 uint64_t value) 141 { 142 CPUState *cs = env_cpu(env); 143 144 tlb_flush_by_mmuidx(cs, alle1_tlbmask(env)); 145 } 146 147 static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 148 uint64_t value) 149 { 150 CPUState *cs = env_cpu(env); 151 152 tlb_flush_by_mmuidx_all_cpus_synced(cs, alle1_tlbmask(env)); 153 } 154 155 156 static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, 157 uint64_t value) 158 { 159 CPUState *cs = env_cpu(env); 160 161 tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2); 162 } 163 164 static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 165 uint64_t value) 166 { 167 CPUState *cs = env_cpu(env); 168 169 tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2); 170 } 171 172 static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri, 173 uint64_t value) 174 { 175 CPUState *cs = env_cpu(env); 176 int mask = vae1_tlbmask(env); 177 178 if (tlb_force_broadcast(env)) { 179 tlb_flush_by_mmuidx_all_cpus_synced(cs, mask); 180 } else { 181 tlb_flush_by_mmuidx(cs, mask); 182 } 183 } 184 185 static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri, 186 uint64_t value) 187 { 188 CPUState *cs = env_cpu(env); 189 int mask = alle1_tlbmask(env); 190 191 tlb_flush_by_mmuidx(cs, mask); 192 } 193 194 static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri, 195 uint64_t value) 196 { 197 CPUState *cs = env_cpu(env); 198 int mask = e2_tlbmask(env); 199 200 tlb_flush_by_mmuidx(cs, mask); 201 } 202 203 static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri, 204 uint64_t value) 205 { 206 ARMCPU *cpu = env_archcpu(env); 207 CPUState *cs = CPU(cpu); 208 209 tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E3); 210 } 211 212 static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri, 213 uint64_t value) 214 { 215 /* 216 * Invalidate by VA, EL2 217 * Currently handles both VAE2 and VALE2, since we don't support 218 * flush-last-level-only. 219 */ 220 CPUState *cs = env_cpu(env); 221 int mask = vae2_tlbmask(env); 222 uint64_t pageaddr = sextract64(value << 12, 0, 56); 223 int bits = vae2_tlbbits(env, pageaddr); 224 225 tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits); 226 } 227 228 static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri, 229 uint64_t value) 230 { 231 /* 232 * Invalidate by VA, EL3 233 * Currently handles both VAE3 and VALE3, since we don't support 234 * flush-last-level-only. 235 */ 236 ARMCPU *cpu = env_archcpu(env); 237 CPUState *cs = CPU(cpu); 238 uint64_t pageaddr = sextract64(value << 12, 0, 56); 239 240 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E3); 241 } 242 243 static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri, 244 uint64_t value) 245 { 246 /* 247 * Invalidate by VA, EL1&0 (AArch64 version). 248 * Currently handles all of VAE1, VAAE1, VAALE1 and VALE1, 249 * since we don't support flush-for-specific-ASID-only or 250 * flush-last-level-only. 251 */ 252 CPUState *cs = env_cpu(env); 253 int mask = vae1_tlbmask(env); 254 uint64_t pageaddr = sextract64(value << 12, 0, 56); 255 int bits = vae1_tlbbits(env, pageaddr); 256 257 if (tlb_force_broadcast(env)) { 258 tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits); 259 } else { 260 tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits); 261 } 262 } 263 264 static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri, 265 uint64_t value) 266 { 267 CPUState *cs = env_cpu(env); 268 int mask = ipas2e1_tlbmask(env, value); 269 uint64_t pageaddr = sextract64(value << 12, 0, 56); 270 271 if (tlb_force_broadcast(env)) { 272 tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); 273 } else { 274 tlb_flush_page_by_mmuidx(cs, pageaddr, mask); 275 } 276 } 277 278 static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri, 279 uint64_t value) 280 { 281 CPUState *cs = env_cpu(env); 282 int mask = ipas2e1_tlbmask(env, value); 283 uint64_t pageaddr = sextract64(value << 12, 0, 56); 284 285 tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); 286 } 287 288 static const ARMCPRegInfo tlbi_not_v7_cp_reginfo[] = { 289 /* 290 * MMU TLB control. Note that the wildcarding means we cover not just 291 * the unified TLB ops but also the dside/iside/inner-shareable variants. 292 */ 293 { .name = "TLBIALL", .cp = 15, .crn = 8, .crm = CP_ANY, 294 .opc1 = CP_ANY, .opc2 = 0, .access = PL1_W, .writefn = tlbiall_write, 295 .type = ARM_CP_NO_RAW }, 296 { .name = "TLBIMVA", .cp = 15, .crn = 8, .crm = CP_ANY, 297 .opc1 = CP_ANY, .opc2 = 1, .access = PL1_W, .writefn = tlbimva_write, 298 .type = ARM_CP_NO_RAW }, 299 { .name = "TLBIASID", .cp = 15, .crn = 8, .crm = CP_ANY, 300 .opc1 = CP_ANY, .opc2 = 2, .access = PL1_W, .writefn = tlbiasid_write, 301 .type = ARM_CP_NO_RAW }, 302 { .name = "TLBIMVAA", .cp = 15, .crn = 8, .crm = CP_ANY, 303 .opc1 = CP_ANY, .opc2 = 3, .access = PL1_W, .writefn = tlbimvaa_write, 304 .type = ARM_CP_NO_RAW }, 305 }; 306 307 static const ARMCPRegInfo tlbi_v7_cp_reginfo[] = { 308 /* 32 bit ITLB invalidates */ 309 { .name = "ITLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 0, 310 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 311 .writefn = tlbiall_write }, 312 { .name = "ITLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1, 313 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 314 .writefn = tlbimva_write }, 315 { .name = "ITLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 2, 316 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 317 .writefn = tlbiasid_write }, 318 /* 32 bit DTLB invalidates */ 319 { .name = "DTLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 0, 320 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 321 .writefn = tlbiall_write }, 322 { .name = "DTLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1, 323 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 324 .writefn = tlbimva_write }, 325 { .name = "DTLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 2, 326 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 327 .writefn = tlbiasid_write }, 328 /* 32 bit TLB invalidates */ 329 { .name = "TLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0, 330 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 331 .writefn = tlbiall_write }, 332 { .name = "TLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1, 333 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 334 .writefn = tlbimva_write }, 335 { .name = "TLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2, 336 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 337 .writefn = tlbiasid_write }, 338 { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3, 339 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 340 .writefn = tlbimvaa_write }, 341 }; 342 343 static const ARMCPRegInfo tlbi_v7mp_cp_reginfo[] = { 344 /* 32 bit TLB invalidates, Inner Shareable */ 345 { .name = "TLBIALLIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0, 346 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 347 .writefn = tlbiall_is_write }, 348 { .name = "TLBIMVAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1, 349 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 350 .writefn = tlbimva_is_write }, 351 { .name = "TLBIASIDIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2, 352 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 353 .writefn = tlbiasid_is_write }, 354 { .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3, 355 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 356 .writefn = tlbimvaa_is_write }, 357 }; 358 359 static const ARMCPRegInfo tlbi_v8_cp_reginfo[] = { 360 /* AArch32 TLB invalidate last level of translation table walk */ 361 { .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5, 362 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 363 .writefn = tlbimva_is_write }, 364 { .name = "TLBIMVAALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7, 365 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 366 .writefn = tlbimvaa_is_write }, 367 { .name = "TLBIMVAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5, 368 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 369 .writefn = tlbimva_write }, 370 { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7, 371 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 372 .writefn = tlbimvaa_write }, 373 { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5, 374 .type = ARM_CP_NO_RAW, .access = PL2_W, 375 .writefn = tlbimva_hyp_write }, 376 { .name = "TLBIMVALHIS", 377 .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5, 378 .type = ARM_CP_NO_RAW, .access = PL2_W, 379 .writefn = tlbimva_hyp_is_write }, 380 { .name = "TLBIIPAS2", 381 .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, 382 .type = ARM_CP_NO_RAW, .access = PL2_W, 383 .writefn = tlbiipas2_hyp_write }, 384 { .name = "TLBIIPAS2IS", 385 .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, 386 .type = ARM_CP_NO_RAW, .access = PL2_W, 387 .writefn = tlbiipas2is_hyp_write }, 388 { .name = "TLBIIPAS2L", 389 .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, 390 .type = ARM_CP_NO_RAW, .access = PL2_W, 391 .writefn = tlbiipas2_hyp_write }, 392 { .name = "TLBIIPAS2LIS", 393 .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, 394 .type = ARM_CP_NO_RAW, .access = PL2_W, 395 .writefn = tlbiipas2is_hyp_write }, 396 /* AArch64 TLBI operations */ 397 { .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64, 398 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0, 399 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 400 .fgt = FGT_TLBIVMALLE1IS, 401 .writefn = tlbi_aa64_vmalle1is_write }, 402 { .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64, 403 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1, 404 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 405 .fgt = FGT_TLBIVAE1IS, 406 .writefn = tlbi_aa64_vae1is_write }, 407 { .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64, 408 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2, 409 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 410 .fgt = FGT_TLBIASIDE1IS, 411 .writefn = tlbi_aa64_vmalle1is_write }, 412 { .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64, 413 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3, 414 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 415 .fgt = FGT_TLBIVAAE1IS, 416 .writefn = tlbi_aa64_vae1is_write }, 417 { .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64, 418 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5, 419 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 420 .fgt = FGT_TLBIVALE1IS, 421 .writefn = tlbi_aa64_vae1is_write }, 422 { .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64, 423 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7, 424 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 425 .fgt = FGT_TLBIVAALE1IS, 426 .writefn = tlbi_aa64_vae1is_write }, 427 { .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64, 428 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0, 429 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 430 .fgt = FGT_TLBIVMALLE1, 431 .writefn = tlbi_aa64_vmalle1_write }, 432 { .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64, 433 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1, 434 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 435 .fgt = FGT_TLBIVAE1, 436 .writefn = tlbi_aa64_vae1_write }, 437 { .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64, 438 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2, 439 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 440 .fgt = FGT_TLBIASIDE1, 441 .writefn = tlbi_aa64_vmalle1_write }, 442 { .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64, 443 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3, 444 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 445 .fgt = FGT_TLBIVAAE1, 446 .writefn = tlbi_aa64_vae1_write }, 447 { .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64, 448 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5, 449 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 450 .fgt = FGT_TLBIVALE1, 451 .writefn = tlbi_aa64_vae1_write }, 452 { .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64, 453 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7, 454 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 455 .fgt = FGT_TLBIVAALE1, 456 .writefn = tlbi_aa64_vae1_write }, 457 { .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64, 458 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, 459 .access = PL2_W, .type = ARM_CP_NO_RAW, 460 .writefn = tlbi_aa64_ipas2e1is_write }, 461 { .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64, 462 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, 463 .access = PL2_W, .type = ARM_CP_NO_RAW, 464 .writefn = tlbi_aa64_ipas2e1is_write }, 465 { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64, 466 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, 467 .access = PL2_W, .type = ARM_CP_NO_RAW, 468 .writefn = tlbi_aa64_alle1is_write }, 469 { .name = "TLBI_VMALLS12E1IS", .state = ARM_CP_STATE_AA64, 470 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 6, 471 .access = PL2_W, .type = ARM_CP_NO_RAW, 472 .writefn = tlbi_aa64_alle1is_write }, 473 { .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64, 474 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, 475 .access = PL2_W, .type = ARM_CP_NO_RAW, 476 .writefn = tlbi_aa64_ipas2e1_write }, 477 { .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64, 478 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, 479 .access = PL2_W, .type = ARM_CP_NO_RAW, 480 .writefn = tlbi_aa64_ipas2e1_write }, 481 { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64, 482 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, 483 .access = PL2_W, .type = ARM_CP_NO_RAW, 484 .writefn = tlbi_aa64_alle1_write }, 485 { .name = "TLBI_VMALLS12E1", .state = ARM_CP_STATE_AA64, 486 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 6, 487 .access = PL2_W, .type = ARM_CP_NO_RAW, 488 .writefn = tlbi_aa64_alle1is_write }, 489 }; 490 491 static const ARMCPRegInfo tlbi_el2_cp_reginfo[] = { 492 { .name = "TLBIALLNSNH", 493 .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, 494 .type = ARM_CP_NO_RAW, .access = PL2_W, 495 .writefn = tlbiall_nsnh_write }, 496 { .name = "TLBIALLNSNHIS", 497 .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, 498 .type = ARM_CP_NO_RAW, .access = PL2_W, 499 .writefn = tlbiall_nsnh_is_write }, 500 { .name = "TLBIALLH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0, 501 .type = ARM_CP_NO_RAW, .access = PL2_W, 502 .writefn = tlbiall_hyp_write }, 503 { .name = "TLBIALLHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0, 504 .type = ARM_CP_NO_RAW, .access = PL2_W, 505 .writefn = tlbiall_hyp_is_write }, 506 { .name = "TLBIMVAH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1, 507 .type = ARM_CP_NO_RAW, .access = PL2_W, 508 .writefn = tlbimva_hyp_write }, 509 { .name = "TLBIMVAHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1, 510 .type = ARM_CP_NO_RAW, .access = PL2_W, 511 .writefn = tlbimva_hyp_is_write }, 512 { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64, 513 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0, 514 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 515 .writefn = tlbi_aa64_alle2_write }, 516 { .name = "TLBI_VAE2", .state = ARM_CP_STATE_AA64, 517 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1, 518 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 519 .writefn = tlbi_aa64_vae2_write }, 520 { .name = "TLBI_VALE2", .state = ARM_CP_STATE_AA64, 521 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5, 522 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 523 .writefn = tlbi_aa64_vae2_write }, 524 { .name = "TLBI_ALLE2IS", .state = ARM_CP_STATE_AA64, 525 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0, 526 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 527 .writefn = tlbi_aa64_alle2is_write }, 528 { .name = "TLBI_VAE2IS", .state = ARM_CP_STATE_AA64, 529 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1, 530 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 531 .writefn = tlbi_aa64_vae2is_write }, 532 { .name = "TLBI_VALE2IS", .state = ARM_CP_STATE_AA64, 533 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5, 534 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 535 .writefn = tlbi_aa64_vae2is_write }, 536 }; 537 538 static const ARMCPRegInfo tlbi_el3_cp_reginfo[] = { 539 { .name = "TLBI_ALLE3IS", .state = ARM_CP_STATE_AA64, 540 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 0, 541 .access = PL3_W, .type = ARM_CP_NO_RAW, 542 .writefn = tlbi_aa64_alle3is_write }, 543 { .name = "TLBI_VAE3IS", .state = ARM_CP_STATE_AA64, 544 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 1, 545 .access = PL3_W, .type = ARM_CP_NO_RAW, 546 .writefn = tlbi_aa64_vae3is_write }, 547 { .name = "TLBI_VALE3IS", .state = ARM_CP_STATE_AA64, 548 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 5, 549 .access = PL3_W, .type = ARM_CP_NO_RAW, 550 .writefn = tlbi_aa64_vae3is_write }, 551 { .name = "TLBI_ALLE3", .state = ARM_CP_STATE_AA64, 552 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 0, 553 .access = PL3_W, .type = ARM_CP_NO_RAW, 554 .writefn = tlbi_aa64_alle3_write }, 555 { .name = "TLBI_VAE3", .state = ARM_CP_STATE_AA64, 556 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 1, 557 .access = PL3_W, .type = ARM_CP_NO_RAW, 558 .writefn = tlbi_aa64_vae3_write }, 559 { .name = "TLBI_VALE3", .state = ARM_CP_STATE_AA64, 560 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 5, 561 .access = PL3_W, .type = ARM_CP_NO_RAW, 562 .writefn = tlbi_aa64_vae3_write }, 563 }; 564 565 void define_tlb_insn_regs(ARMCPU *cpu) 566 { 567 CPUARMState *env = &cpu->env; 568 569 if (!arm_feature(env, ARM_FEATURE_V7)) { 570 define_arm_cp_regs(cpu, tlbi_not_v7_cp_reginfo); 571 } else { 572 define_arm_cp_regs(cpu, tlbi_v7_cp_reginfo); 573 } 574 if (arm_feature(env, ARM_FEATURE_V7MP) && 575 !arm_feature(env, ARM_FEATURE_PMSA)) { 576 define_arm_cp_regs(cpu, tlbi_v7mp_cp_reginfo); 577 } 578 if (arm_feature(env, ARM_FEATURE_V8)) { 579 define_arm_cp_regs(cpu, tlbi_v8_cp_reginfo); 580 } 581 /* 582 * We retain the existing logic for when to register these TLBI 583 * ops (i.e. matching the condition for el2_cp_reginfo[] in 584 * helper.c), but we will be able to simplify this later. 585 */ 586 if (arm_feature(env, ARM_FEATURE_EL2) 587 || (arm_feature(env, ARM_FEATURE_EL3) 588 && arm_feature(env, ARM_FEATURE_V8))) { 589 define_arm_cp_regs(cpu, tlbi_el2_cp_reginfo); 590 } 591 if (arm_feature(env, ARM_FEATURE_EL3)) { 592 define_arm_cp_regs(cpu, tlbi_el3_cp_reginfo); 593 } 594 } 595