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_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri, 204 uint64_t value) 205 { 206 /* 207 * Invalidate by VA, EL2 208 * Currently handles both VAE2 and VALE2, since we don't support 209 * flush-last-level-only. 210 */ 211 CPUState *cs = env_cpu(env); 212 int mask = vae2_tlbmask(env); 213 uint64_t pageaddr = sextract64(value << 12, 0, 56); 214 int bits = vae2_tlbbits(env, pageaddr); 215 216 tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits); 217 } 218 219 static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri, 220 uint64_t value) 221 { 222 /* 223 * Invalidate by VA, EL1&0 (AArch64 version). 224 * Currently handles all of VAE1, VAAE1, VAALE1 and VALE1, 225 * since we don't support flush-for-specific-ASID-only or 226 * flush-last-level-only. 227 */ 228 CPUState *cs = env_cpu(env); 229 int mask = vae1_tlbmask(env); 230 uint64_t pageaddr = sextract64(value << 12, 0, 56); 231 int bits = vae1_tlbbits(env, pageaddr); 232 233 if (tlb_force_broadcast(env)) { 234 tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits); 235 } else { 236 tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits); 237 } 238 } 239 240 static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri, 241 uint64_t value) 242 { 243 CPUState *cs = env_cpu(env); 244 int mask = ipas2e1_tlbmask(env, value); 245 uint64_t pageaddr = sextract64(value << 12, 0, 56); 246 247 if (tlb_force_broadcast(env)) { 248 tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); 249 } else { 250 tlb_flush_page_by_mmuidx(cs, pageaddr, mask); 251 } 252 } 253 254 static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri, 255 uint64_t value) 256 { 257 CPUState *cs = env_cpu(env); 258 int mask = ipas2e1_tlbmask(env, value); 259 uint64_t pageaddr = sextract64(value << 12, 0, 56); 260 261 tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); 262 } 263 264 static const ARMCPRegInfo tlbi_not_v7_cp_reginfo[] = { 265 /* 266 * MMU TLB control. Note that the wildcarding means we cover not just 267 * the unified TLB ops but also the dside/iside/inner-shareable variants. 268 */ 269 { .name = "TLBIALL", .cp = 15, .crn = 8, .crm = CP_ANY, 270 .opc1 = CP_ANY, .opc2 = 0, .access = PL1_W, .writefn = tlbiall_write, 271 .type = ARM_CP_NO_RAW }, 272 { .name = "TLBIMVA", .cp = 15, .crn = 8, .crm = CP_ANY, 273 .opc1 = CP_ANY, .opc2 = 1, .access = PL1_W, .writefn = tlbimva_write, 274 .type = ARM_CP_NO_RAW }, 275 { .name = "TLBIASID", .cp = 15, .crn = 8, .crm = CP_ANY, 276 .opc1 = CP_ANY, .opc2 = 2, .access = PL1_W, .writefn = tlbiasid_write, 277 .type = ARM_CP_NO_RAW }, 278 { .name = "TLBIMVAA", .cp = 15, .crn = 8, .crm = CP_ANY, 279 .opc1 = CP_ANY, .opc2 = 3, .access = PL1_W, .writefn = tlbimvaa_write, 280 .type = ARM_CP_NO_RAW }, 281 }; 282 283 static const ARMCPRegInfo tlbi_v7_cp_reginfo[] = { 284 /* 32 bit ITLB invalidates */ 285 { .name = "ITLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 0, 286 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 287 .writefn = tlbiall_write }, 288 { .name = "ITLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1, 289 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 290 .writefn = tlbimva_write }, 291 { .name = "ITLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 2, 292 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 293 .writefn = tlbiasid_write }, 294 /* 32 bit DTLB invalidates */ 295 { .name = "DTLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 0, 296 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 297 .writefn = tlbiall_write }, 298 { .name = "DTLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1, 299 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 300 .writefn = tlbimva_write }, 301 { .name = "DTLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 2, 302 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 303 .writefn = tlbiasid_write }, 304 /* 32 bit TLB invalidates */ 305 { .name = "TLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0, 306 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 307 .writefn = tlbiall_write }, 308 { .name = "TLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1, 309 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 310 .writefn = tlbimva_write }, 311 { .name = "TLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2, 312 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 313 .writefn = tlbiasid_write }, 314 { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3, 315 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 316 .writefn = tlbimvaa_write }, 317 }; 318 319 static const ARMCPRegInfo tlbi_v7mp_cp_reginfo[] = { 320 /* 32 bit TLB invalidates, Inner Shareable */ 321 { .name = "TLBIALLIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0, 322 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 323 .writefn = tlbiall_is_write }, 324 { .name = "TLBIMVAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1, 325 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 326 .writefn = tlbimva_is_write }, 327 { .name = "TLBIASIDIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2, 328 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 329 .writefn = tlbiasid_is_write }, 330 { .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3, 331 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 332 .writefn = tlbimvaa_is_write }, 333 }; 334 335 static const ARMCPRegInfo tlbi_v8_cp_reginfo[] = { 336 /* AArch32 TLB invalidate last level of translation table walk */ 337 { .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5, 338 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 339 .writefn = tlbimva_is_write }, 340 { .name = "TLBIMVAALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7, 341 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 342 .writefn = tlbimvaa_is_write }, 343 { .name = "TLBIMVAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5, 344 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 345 .writefn = tlbimva_write }, 346 { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7, 347 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 348 .writefn = tlbimvaa_write }, 349 { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5, 350 .type = ARM_CP_NO_RAW, .access = PL2_W, 351 .writefn = tlbimva_hyp_write }, 352 { .name = "TLBIMVALHIS", 353 .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5, 354 .type = ARM_CP_NO_RAW, .access = PL2_W, 355 .writefn = tlbimva_hyp_is_write }, 356 { .name = "TLBIIPAS2", 357 .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, 358 .type = ARM_CP_NO_RAW, .access = PL2_W, 359 .writefn = tlbiipas2_hyp_write }, 360 { .name = "TLBIIPAS2IS", 361 .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, 362 .type = ARM_CP_NO_RAW, .access = PL2_W, 363 .writefn = tlbiipas2is_hyp_write }, 364 { .name = "TLBIIPAS2L", 365 .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, 366 .type = ARM_CP_NO_RAW, .access = PL2_W, 367 .writefn = tlbiipas2_hyp_write }, 368 { .name = "TLBIIPAS2LIS", 369 .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, 370 .type = ARM_CP_NO_RAW, .access = PL2_W, 371 .writefn = tlbiipas2is_hyp_write }, 372 /* AArch64 TLBI operations */ 373 { .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64, 374 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0, 375 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 376 .fgt = FGT_TLBIVMALLE1IS, 377 .writefn = tlbi_aa64_vmalle1is_write }, 378 { .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64, 379 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1, 380 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 381 .fgt = FGT_TLBIVAE1IS, 382 .writefn = tlbi_aa64_vae1is_write }, 383 { .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64, 384 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2, 385 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 386 .fgt = FGT_TLBIASIDE1IS, 387 .writefn = tlbi_aa64_vmalle1is_write }, 388 { .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64, 389 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3, 390 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 391 .fgt = FGT_TLBIVAAE1IS, 392 .writefn = tlbi_aa64_vae1is_write }, 393 { .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64, 394 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5, 395 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 396 .fgt = FGT_TLBIVALE1IS, 397 .writefn = tlbi_aa64_vae1is_write }, 398 { .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64, 399 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7, 400 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, 401 .fgt = FGT_TLBIVAALE1IS, 402 .writefn = tlbi_aa64_vae1is_write }, 403 { .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64, 404 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0, 405 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 406 .fgt = FGT_TLBIVMALLE1, 407 .writefn = tlbi_aa64_vmalle1_write }, 408 { .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64, 409 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1, 410 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 411 .fgt = FGT_TLBIVAE1, 412 .writefn = tlbi_aa64_vae1_write }, 413 { .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64, 414 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2, 415 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 416 .fgt = FGT_TLBIASIDE1, 417 .writefn = tlbi_aa64_vmalle1_write }, 418 { .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64, 419 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3, 420 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 421 .fgt = FGT_TLBIVAAE1, 422 .writefn = tlbi_aa64_vae1_write }, 423 { .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64, 424 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5, 425 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 426 .fgt = FGT_TLBIVALE1, 427 .writefn = tlbi_aa64_vae1_write }, 428 { .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64, 429 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7, 430 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, 431 .fgt = FGT_TLBIVAALE1, 432 .writefn = tlbi_aa64_vae1_write }, 433 { .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64, 434 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, 435 .access = PL2_W, .type = ARM_CP_NO_RAW, 436 .writefn = tlbi_aa64_ipas2e1is_write }, 437 { .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64, 438 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, 439 .access = PL2_W, .type = ARM_CP_NO_RAW, 440 .writefn = tlbi_aa64_ipas2e1is_write }, 441 { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64, 442 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, 443 .access = PL2_W, .type = ARM_CP_NO_RAW, 444 .writefn = tlbi_aa64_alle1is_write }, 445 { .name = "TLBI_VMALLS12E1IS", .state = ARM_CP_STATE_AA64, 446 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 6, 447 .access = PL2_W, .type = ARM_CP_NO_RAW, 448 .writefn = tlbi_aa64_alle1is_write }, 449 { .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64, 450 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, 451 .access = PL2_W, .type = ARM_CP_NO_RAW, 452 .writefn = tlbi_aa64_ipas2e1_write }, 453 { .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64, 454 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, 455 .access = PL2_W, .type = ARM_CP_NO_RAW, 456 .writefn = tlbi_aa64_ipas2e1_write }, 457 { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64, 458 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, 459 .access = PL2_W, .type = ARM_CP_NO_RAW, 460 .writefn = tlbi_aa64_alle1_write }, 461 { .name = "TLBI_VMALLS12E1", .state = ARM_CP_STATE_AA64, 462 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 6, 463 .access = PL2_W, .type = ARM_CP_NO_RAW, 464 .writefn = tlbi_aa64_alle1is_write }, 465 }; 466 467 static const ARMCPRegInfo tlbi_el2_cp_reginfo[] = { 468 { .name = "TLBIALLNSNH", 469 .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, 470 .type = ARM_CP_NO_RAW, .access = PL2_W, 471 .writefn = tlbiall_nsnh_write }, 472 { .name = "TLBIALLNSNHIS", 473 .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, 474 .type = ARM_CP_NO_RAW, .access = PL2_W, 475 .writefn = tlbiall_nsnh_is_write }, 476 { .name = "TLBIALLH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0, 477 .type = ARM_CP_NO_RAW, .access = PL2_W, 478 .writefn = tlbiall_hyp_write }, 479 { .name = "TLBIALLHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0, 480 .type = ARM_CP_NO_RAW, .access = PL2_W, 481 .writefn = tlbiall_hyp_is_write }, 482 { .name = "TLBIMVAH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1, 483 .type = ARM_CP_NO_RAW, .access = PL2_W, 484 .writefn = tlbimva_hyp_write }, 485 { .name = "TLBIMVAHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1, 486 .type = ARM_CP_NO_RAW, .access = PL2_W, 487 .writefn = tlbimva_hyp_is_write }, 488 { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64, 489 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0, 490 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 491 .writefn = tlbi_aa64_alle2_write }, 492 { .name = "TLBI_VAE2", .state = ARM_CP_STATE_AA64, 493 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1, 494 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 495 .writefn = tlbi_aa64_vae2_write }, 496 { .name = "TLBI_VALE2", .state = ARM_CP_STATE_AA64, 497 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5, 498 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 499 .writefn = tlbi_aa64_vae2_write }, 500 { .name = "TLBI_ALLE2IS", .state = ARM_CP_STATE_AA64, 501 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0, 502 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 503 .writefn = tlbi_aa64_alle2is_write }, 504 { .name = "TLBI_VAE2IS", .state = ARM_CP_STATE_AA64, 505 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1, 506 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 507 .writefn = tlbi_aa64_vae2is_write }, 508 { .name = "TLBI_VALE2IS", .state = ARM_CP_STATE_AA64, 509 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5, 510 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, 511 .writefn = tlbi_aa64_vae2is_write }, 512 }; 513 514 void define_tlb_insn_regs(ARMCPU *cpu) 515 { 516 CPUARMState *env = &cpu->env; 517 518 if (!arm_feature(env, ARM_FEATURE_V7)) { 519 define_arm_cp_regs(cpu, tlbi_not_v7_cp_reginfo); 520 } else { 521 define_arm_cp_regs(cpu, tlbi_v7_cp_reginfo); 522 } 523 if (arm_feature(env, ARM_FEATURE_V7MP) && 524 !arm_feature(env, ARM_FEATURE_PMSA)) { 525 define_arm_cp_regs(cpu, tlbi_v7mp_cp_reginfo); 526 } 527 if (arm_feature(env, ARM_FEATURE_V8)) { 528 define_arm_cp_regs(cpu, tlbi_v8_cp_reginfo); 529 } 530 /* 531 * We retain the existing logic for when to register these TLBI 532 * ops (i.e. matching the condition for el2_cp_reginfo[] in 533 * helper.c), but we will be able to simplify this later. 534 */ 535 if (arm_feature(env, ARM_FEATURE_EL2) 536 || (arm_feature(env, ARM_FEATURE_EL3) 537 && arm_feature(env, ARM_FEATURE_V8))) { 538 define_arm_cp_regs(cpu, tlbi_el2_cp_reginfo); 539 } 540 } 541