| /* |
| * Helpers for TLBI insns |
| * |
| * This code is licensed under the GNU GPL v2 or later. |
| * |
| * SPDX-License-Identifier: GPL-2.0-or-later |
| */ |
| #include "qemu/osdep.h" |
| #include "exec/exec-all.h" |
| #include "cpu.h" |
| #include "internals.h" |
| #include "cpu-features.h" |
| #include "cpregs.h" |
| |
| /* IS variants of TLB operations must affect all cores */ |
| static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| |
| tlb_flush_all_cpus_synced(cs); |
| } |
| |
| static void tlbiasid_is_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| |
| tlb_flush_all_cpus_synced(cs); |
| } |
| |
| static void tlbimva_is_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| |
| tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK); |
| } |
| |
| static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| |
| tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK); |
| } |
| |
| static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| /* Invalidate all (TLBIALL) */ |
| CPUState *cs = env_cpu(env); |
| |
| if (tlb_force_broadcast(env)) { |
| tlb_flush_all_cpus_synced(cs); |
| } else { |
| tlb_flush(cs); |
| } |
| } |
| |
| static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */ |
| CPUState *cs = env_cpu(env); |
| |
| value &= TARGET_PAGE_MASK; |
| if (tlb_force_broadcast(env)) { |
| tlb_flush_page_all_cpus_synced(cs, value); |
| } else { |
| tlb_flush_page(cs, value); |
| } |
| } |
| |
| static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| /* Invalidate by ASID (TLBIASID) */ |
| CPUState *cs = env_cpu(env); |
| |
| if (tlb_force_broadcast(env)) { |
| tlb_flush_all_cpus_synced(cs); |
| } else { |
| tlb_flush(cs); |
| } |
| } |
| |
| static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */ |
| CPUState *cs = env_cpu(env); |
| |
| value &= TARGET_PAGE_MASK; |
| if (tlb_force_broadcast(env)) { |
| tlb_flush_page_all_cpus_synced(cs, value); |
| } else { |
| tlb_flush_page(cs, value); |
| } |
| } |
| |
| static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12); |
| |
| tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2); |
| } |
| |
| static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12); |
| |
| tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, |
| ARMMMUIdxBit_E2); |
| } |
| |
| static void tlbiipas2_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12; |
| |
| tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2); |
| } |
| |
| static void tlbiipas2is_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12; |
| |
| tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2); |
| } |
| |
| static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| |
| tlb_flush_by_mmuidx(cs, alle1_tlbmask(env)); |
| } |
| |
| static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| |
| tlb_flush_by_mmuidx_all_cpus_synced(cs, alle1_tlbmask(env)); |
| } |
| |
| |
| static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| |
| tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2); |
| } |
| |
| static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| |
| tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2); |
| } |
| |
| static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| int mask = vae1_tlbmask(env); |
| |
| if (tlb_force_broadcast(env)) { |
| tlb_flush_by_mmuidx_all_cpus_synced(cs, mask); |
| } else { |
| tlb_flush_by_mmuidx(cs, mask); |
| } |
| } |
| |
| static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| int mask = alle1_tlbmask(env); |
| |
| tlb_flush_by_mmuidx(cs, mask); |
| } |
| |
| static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| /* |
| * Invalidate by VA, EL1&0 (AArch64 version). |
| * Currently handles all of VAE1, VAAE1, VAALE1 and VALE1, |
| * since we don't support flush-for-specific-ASID-only or |
| * flush-last-level-only. |
| */ |
| CPUState *cs = env_cpu(env); |
| int mask = vae1_tlbmask(env); |
| uint64_t pageaddr = sextract64(value << 12, 0, 56); |
| int bits = vae1_tlbbits(env, pageaddr); |
| |
| if (tlb_force_broadcast(env)) { |
| tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits); |
| } else { |
| tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits); |
| } |
| } |
| |
| static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| int mask = ipas2e1_tlbmask(env, value); |
| uint64_t pageaddr = sextract64(value << 12, 0, 56); |
| |
| if (tlb_force_broadcast(env)) { |
| tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); |
| } else { |
| tlb_flush_page_by_mmuidx(cs, pageaddr, mask); |
| } |
| } |
| |
| static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| uint64_t value) |
| { |
| CPUState *cs = env_cpu(env); |
| int mask = ipas2e1_tlbmask(env, value); |
| uint64_t pageaddr = sextract64(value << 12, 0, 56); |
| |
| tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); |
| } |
| |
| static const ARMCPRegInfo tlbi_not_v7_cp_reginfo[] = { |
| /* |
| * MMU TLB control. Note that the wildcarding means we cover not just |
| * the unified TLB ops but also the dside/iside/inner-shareable variants. |
| */ |
| { .name = "TLBIALL", .cp = 15, .crn = 8, .crm = CP_ANY, |
| .opc1 = CP_ANY, .opc2 = 0, .access = PL1_W, .writefn = tlbiall_write, |
| .type = ARM_CP_NO_RAW }, |
| { .name = "TLBIMVA", .cp = 15, .crn = 8, .crm = CP_ANY, |
| .opc1 = CP_ANY, .opc2 = 1, .access = PL1_W, .writefn = tlbimva_write, |
| .type = ARM_CP_NO_RAW }, |
| { .name = "TLBIASID", .cp = 15, .crn = 8, .crm = CP_ANY, |
| .opc1 = CP_ANY, .opc2 = 2, .access = PL1_W, .writefn = tlbiasid_write, |
| .type = ARM_CP_NO_RAW }, |
| { .name = "TLBIMVAA", .cp = 15, .crn = 8, .crm = CP_ANY, |
| .opc1 = CP_ANY, .opc2 = 3, .access = PL1_W, .writefn = tlbimvaa_write, |
| .type = ARM_CP_NO_RAW }, |
| }; |
| |
| static const ARMCPRegInfo tlbi_v7_cp_reginfo[] = { |
| /* 32 bit ITLB invalidates */ |
| { .name = "ITLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 0, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbiall_write }, |
| { .name = "ITLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbimva_write }, |
| { .name = "ITLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 2, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbiasid_write }, |
| /* 32 bit DTLB invalidates */ |
| { .name = "DTLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 0, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbiall_write }, |
| { .name = "DTLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbimva_write }, |
| { .name = "DTLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 2, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbiasid_write }, |
| /* 32 bit TLB invalidates */ |
| { .name = "TLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbiall_write }, |
| { .name = "TLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbimva_write }, |
| { .name = "TLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbiasid_write }, |
| { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbimvaa_write }, |
| }; |
| |
| static const ARMCPRegInfo tlbi_v7mp_cp_reginfo[] = { |
| /* 32 bit TLB invalidates, Inner Shareable */ |
| { .name = "TLBIALLIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, |
| .writefn = tlbiall_is_write }, |
| { .name = "TLBIMVAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, |
| .writefn = tlbimva_is_write }, |
| { .name = "TLBIASIDIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, |
| .writefn = tlbiasid_is_write }, |
| { .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, |
| .writefn = tlbimvaa_is_write }, |
| }; |
| |
| static const ARMCPRegInfo tlbi_v8_cp_reginfo[] = { |
| /* AArch32 TLB invalidate last level of translation table walk */ |
| { .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, |
| .writefn = tlbimva_is_write }, |
| { .name = "TLBIMVAALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, |
| .writefn = tlbimvaa_is_write }, |
| { .name = "TLBIMVAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbimva_write }, |
| { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7, |
| .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, |
| .writefn = tlbimvaa_write }, |
| { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbimva_hyp_write }, |
| { .name = "TLBIMVALHIS", |
| .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbimva_hyp_is_write }, |
| { .name = "TLBIIPAS2", |
| .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbiipas2_hyp_write }, |
| { .name = "TLBIIPAS2IS", |
| .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbiipas2is_hyp_write }, |
| { .name = "TLBIIPAS2L", |
| .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbiipas2_hyp_write }, |
| { .name = "TLBIIPAS2LIS", |
| .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbiipas2is_hyp_write }, |
| /* AArch64 TLBI operations */ |
| { .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0, |
| .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIVMALLE1IS, |
| .writefn = tlbi_aa64_vmalle1is_write }, |
| { .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1, |
| .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIVAE1IS, |
| .writefn = tlbi_aa64_vae1is_write }, |
| { .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2, |
| .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIASIDE1IS, |
| .writefn = tlbi_aa64_vmalle1is_write }, |
| { .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3, |
| .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIVAAE1IS, |
| .writefn = tlbi_aa64_vae1is_write }, |
| { .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5, |
| .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIVALE1IS, |
| .writefn = tlbi_aa64_vae1is_write }, |
| { .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7, |
| .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIVAALE1IS, |
| .writefn = tlbi_aa64_vae1is_write }, |
| { .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0, |
| .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIVMALLE1, |
| .writefn = tlbi_aa64_vmalle1_write }, |
| { .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1, |
| .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIVAE1, |
| .writefn = tlbi_aa64_vae1_write }, |
| { .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2, |
| .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIASIDE1, |
| .writefn = tlbi_aa64_vmalle1_write }, |
| { .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3, |
| .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIVAAE1, |
| .writefn = tlbi_aa64_vae1_write }, |
| { .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5, |
| .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIVALE1, |
| .writefn = tlbi_aa64_vae1_write }, |
| { .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7, |
| .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW, |
| .fgt = FGT_TLBIVAALE1, |
| .writefn = tlbi_aa64_vae1_write }, |
| { .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, |
| .access = PL2_W, .type = ARM_CP_NO_RAW, |
| .writefn = tlbi_aa64_ipas2e1is_write }, |
| { .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, |
| .access = PL2_W, .type = ARM_CP_NO_RAW, |
| .writefn = tlbi_aa64_ipas2e1is_write }, |
| { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, |
| .access = PL2_W, .type = ARM_CP_NO_RAW, |
| .writefn = tlbi_aa64_alle1is_write }, |
| { .name = "TLBI_VMALLS12E1IS", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 6, |
| .access = PL2_W, .type = ARM_CP_NO_RAW, |
| .writefn = tlbi_aa64_alle1is_write }, |
| { .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, |
| .access = PL2_W, .type = ARM_CP_NO_RAW, |
| .writefn = tlbi_aa64_ipas2e1_write }, |
| { .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, |
| .access = PL2_W, .type = ARM_CP_NO_RAW, |
| .writefn = tlbi_aa64_ipas2e1_write }, |
| { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, |
| .access = PL2_W, .type = ARM_CP_NO_RAW, |
| .writefn = tlbi_aa64_alle1_write }, |
| { .name = "TLBI_VMALLS12E1", .state = ARM_CP_STATE_AA64, |
| .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 6, |
| .access = PL2_W, .type = ARM_CP_NO_RAW, |
| .writefn = tlbi_aa64_alle1is_write }, |
| }; |
| |
| static const ARMCPRegInfo tlbi_el2_cp_reginfo[] = { |
| { .name = "TLBIALLNSNH", |
| .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbiall_nsnh_write }, |
| { .name = "TLBIALLNSNHIS", |
| .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbiall_nsnh_is_write }, |
| { .name = "TLBIALLH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbiall_hyp_write }, |
| { .name = "TLBIALLHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbiall_hyp_is_write }, |
| { .name = "TLBIMVAH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbimva_hyp_write }, |
| { .name = "TLBIMVAHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1, |
| .type = ARM_CP_NO_RAW, .access = PL2_W, |
| .writefn = tlbimva_hyp_is_write }, |
| }; |
| |
| void define_tlb_insn_regs(ARMCPU *cpu) |
| { |
| CPUARMState *env = &cpu->env; |
| |
| if (!arm_feature(env, ARM_FEATURE_V7)) { |
| define_arm_cp_regs(cpu, tlbi_not_v7_cp_reginfo); |
| } else { |
| define_arm_cp_regs(cpu, tlbi_v7_cp_reginfo); |
| } |
| if (arm_feature(env, ARM_FEATURE_V7MP) && |
| !arm_feature(env, ARM_FEATURE_PMSA)) { |
| define_arm_cp_regs(cpu, tlbi_v7mp_cp_reginfo); |
| } |
| if (arm_feature(env, ARM_FEATURE_V8)) { |
| define_arm_cp_regs(cpu, tlbi_v8_cp_reginfo); |
| } |
| /* |
| * We retain the existing logic for when to register these TLBI |
| * ops (i.e. matching the condition for el2_cp_reginfo[] in |
| * helper.c), but we will be able to simplify this later. |
| */ |
| if (arm_feature(env, ARM_FEATURE_EL2) |
| || (arm_feature(env, ARM_FEATURE_EL3) |
| && arm_feature(env, ARM_FEATURE_V8))) { |
| define_arm_cp_regs(cpu, tlbi_el2_cp_reginfo); |
| } |
| } |