1*1e32ee23SPeter Maydell /* 2*1e32ee23SPeter Maydell * Helpers for TLBI insns 3*1e32ee23SPeter Maydell * 4*1e32ee23SPeter Maydell * This code is licensed under the GNU GPL v2 or later. 5*1e32ee23SPeter Maydell * 6*1e32ee23SPeter Maydell * SPDX-License-Identifier: GPL-2.0-or-later 7*1e32ee23SPeter Maydell */ 8*1e32ee23SPeter Maydell #include "qemu/osdep.h" 9*1e32ee23SPeter Maydell #include "exec/exec-all.h" 10*1e32ee23SPeter Maydell #include "cpu.h" 11*1e32ee23SPeter Maydell #include "internals.h" 12*1e32ee23SPeter Maydell #include "cpu-features.h" 13*1e32ee23SPeter Maydell #include "cpregs.h" 14*1e32ee23SPeter Maydell 15*1e32ee23SPeter Maydell /* IS variants of TLB operations must affect all cores */ 16*1e32ee23SPeter Maydell static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 17*1e32ee23SPeter Maydell uint64_t value) 18*1e32ee23SPeter Maydell { 19*1e32ee23SPeter Maydell CPUState *cs = env_cpu(env); 20*1e32ee23SPeter Maydell 21*1e32ee23SPeter Maydell tlb_flush_all_cpus_synced(cs); 22*1e32ee23SPeter Maydell } 23*1e32ee23SPeter Maydell 24*1e32ee23SPeter Maydell static void tlbiasid_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 25*1e32ee23SPeter Maydell uint64_t value) 26*1e32ee23SPeter Maydell { 27*1e32ee23SPeter Maydell CPUState *cs = env_cpu(env); 28*1e32ee23SPeter Maydell 29*1e32ee23SPeter Maydell tlb_flush_all_cpus_synced(cs); 30*1e32ee23SPeter Maydell } 31*1e32ee23SPeter Maydell 32*1e32ee23SPeter Maydell static void tlbimva_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 33*1e32ee23SPeter Maydell uint64_t value) 34*1e32ee23SPeter Maydell { 35*1e32ee23SPeter Maydell CPUState *cs = env_cpu(env); 36*1e32ee23SPeter Maydell 37*1e32ee23SPeter Maydell tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK); 38*1e32ee23SPeter Maydell } 39*1e32ee23SPeter Maydell 40*1e32ee23SPeter Maydell static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, 41*1e32ee23SPeter Maydell uint64_t value) 42*1e32ee23SPeter Maydell { 43*1e32ee23SPeter Maydell CPUState *cs = env_cpu(env); 44*1e32ee23SPeter Maydell 45*1e32ee23SPeter Maydell tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK); 46*1e32ee23SPeter Maydell } 47*1e32ee23SPeter Maydell 48*1e32ee23SPeter Maydell static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri, 49*1e32ee23SPeter Maydell uint64_t value) 50*1e32ee23SPeter Maydell { 51*1e32ee23SPeter Maydell /* Invalidate all (TLBIALL) */ 52*1e32ee23SPeter Maydell CPUState *cs = env_cpu(env); 53*1e32ee23SPeter Maydell 54*1e32ee23SPeter Maydell if (tlb_force_broadcast(env)) { 55*1e32ee23SPeter Maydell tlb_flush_all_cpus_synced(cs); 56*1e32ee23SPeter Maydell } else { 57*1e32ee23SPeter Maydell tlb_flush(cs); 58*1e32ee23SPeter Maydell } 59*1e32ee23SPeter Maydell } 60*1e32ee23SPeter Maydell 61*1e32ee23SPeter Maydell static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri, 62*1e32ee23SPeter Maydell uint64_t value) 63*1e32ee23SPeter Maydell { 64*1e32ee23SPeter Maydell /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */ 65*1e32ee23SPeter Maydell CPUState *cs = env_cpu(env); 66*1e32ee23SPeter Maydell 67*1e32ee23SPeter Maydell value &= TARGET_PAGE_MASK; 68*1e32ee23SPeter Maydell if (tlb_force_broadcast(env)) { 69*1e32ee23SPeter Maydell tlb_flush_page_all_cpus_synced(cs, value); 70*1e32ee23SPeter Maydell } else { 71*1e32ee23SPeter Maydell tlb_flush_page(cs, value); 72*1e32ee23SPeter Maydell } 73*1e32ee23SPeter Maydell } 74*1e32ee23SPeter Maydell 75*1e32ee23SPeter Maydell static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri, 76*1e32ee23SPeter Maydell uint64_t value) 77*1e32ee23SPeter Maydell { 78*1e32ee23SPeter Maydell /* Invalidate by ASID (TLBIASID) */ 79*1e32ee23SPeter Maydell CPUState *cs = env_cpu(env); 80*1e32ee23SPeter Maydell 81*1e32ee23SPeter Maydell if (tlb_force_broadcast(env)) { 82*1e32ee23SPeter Maydell tlb_flush_all_cpus_synced(cs); 83*1e32ee23SPeter Maydell } else { 84*1e32ee23SPeter Maydell tlb_flush(cs); 85*1e32ee23SPeter Maydell } 86*1e32ee23SPeter Maydell } 87*1e32ee23SPeter Maydell 88*1e32ee23SPeter Maydell static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri, 89*1e32ee23SPeter Maydell uint64_t value) 90*1e32ee23SPeter Maydell { 91*1e32ee23SPeter Maydell /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */ 92*1e32ee23SPeter Maydell CPUState *cs = env_cpu(env); 93*1e32ee23SPeter Maydell 94*1e32ee23SPeter Maydell value &= TARGET_PAGE_MASK; 95*1e32ee23SPeter Maydell if (tlb_force_broadcast(env)) { 96*1e32ee23SPeter Maydell tlb_flush_page_all_cpus_synced(cs, value); 97*1e32ee23SPeter Maydell } else { 98*1e32ee23SPeter Maydell tlb_flush_page(cs, value); 99*1e32ee23SPeter Maydell } 100*1e32ee23SPeter Maydell } 101*1e32ee23SPeter Maydell 102*1e32ee23SPeter Maydell static void tlbiipas2_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, 103*1e32ee23SPeter Maydell uint64_t value) 104*1e32ee23SPeter Maydell { 105*1e32ee23SPeter Maydell CPUState *cs = env_cpu(env); 106*1e32ee23SPeter Maydell uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12; 107*1e32ee23SPeter Maydell 108*1e32ee23SPeter Maydell tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2); 109*1e32ee23SPeter Maydell } 110*1e32ee23SPeter Maydell 111*1e32ee23SPeter Maydell static void tlbiipas2is_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, 112*1e32ee23SPeter Maydell uint64_t value) 113*1e32ee23SPeter Maydell { 114*1e32ee23SPeter Maydell CPUState *cs = env_cpu(env); 115*1e32ee23SPeter Maydell uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12; 116*1e32ee23SPeter Maydell 117*1e32ee23SPeter Maydell tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2); 118*1e32ee23SPeter Maydell } 119*1e32ee23SPeter Maydell 120*1e32ee23SPeter Maydell static const ARMCPRegInfo tlbi_not_v7_cp_reginfo[] = { 121*1e32ee23SPeter Maydell /* 122*1e32ee23SPeter Maydell * MMU TLB control. Note that the wildcarding means we cover not just 123*1e32ee23SPeter Maydell * the unified TLB ops but also the dside/iside/inner-shareable variants. 124*1e32ee23SPeter Maydell */ 125*1e32ee23SPeter Maydell { .name = "TLBIALL", .cp = 15, .crn = 8, .crm = CP_ANY, 126*1e32ee23SPeter Maydell .opc1 = CP_ANY, .opc2 = 0, .access = PL1_W, .writefn = tlbiall_write, 127*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW }, 128*1e32ee23SPeter Maydell { .name = "TLBIMVA", .cp = 15, .crn = 8, .crm = CP_ANY, 129*1e32ee23SPeter Maydell .opc1 = CP_ANY, .opc2 = 1, .access = PL1_W, .writefn = tlbimva_write, 130*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW }, 131*1e32ee23SPeter Maydell { .name = "TLBIASID", .cp = 15, .crn = 8, .crm = CP_ANY, 132*1e32ee23SPeter Maydell .opc1 = CP_ANY, .opc2 = 2, .access = PL1_W, .writefn = tlbiasid_write, 133*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW }, 134*1e32ee23SPeter Maydell { .name = "TLBIMVAA", .cp = 15, .crn = 8, .crm = CP_ANY, 135*1e32ee23SPeter Maydell .opc1 = CP_ANY, .opc2 = 3, .access = PL1_W, .writefn = tlbimvaa_write, 136*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW }, 137*1e32ee23SPeter Maydell }; 138*1e32ee23SPeter Maydell 139*1e32ee23SPeter Maydell static const ARMCPRegInfo tlbi_v7_cp_reginfo[] = { 140*1e32ee23SPeter Maydell /* 32 bit ITLB invalidates */ 141*1e32ee23SPeter Maydell { .name = "ITLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 0, 142*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 143*1e32ee23SPeter Maydell .writefn = tlbiall_write }, 144*1e32ee23SPeter Maydell { .name = "ITLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1, 145*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 146*1e32ee23SPeter Maydell .writefn = tlbimva_write }, 147*1e32ee23SPeter Maydell { .name = "ITLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 2, 148*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 149*1e32ee23SPeter Maydell .writefn = tlbiasid_write }, 150*1e32ee23SPeter Maydell /* 32 bit DTLB invalidates */ 151*1e32ee23SPeter Maydell { .name = "DTLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 0, 152*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 153*1e32ee23SPeter Maydell .writefn = tlbiall_write }, 154*1e32ee23SPeter Maydell { .name = "DTLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1, 155*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 156*1e32ee23SPeter Maydell .writefn = tlbimva_write }, 157*1e32ee23SPeter Maydell { .name = "DTLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 2, 158*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 159*1e32ee23SPeter Maydell .writefn = tlbiasid_write }, 160*1e32ee23SPeter Maydell /* 32 bit TLB invalidates */ 161*1e32ee23SPeter Maydell { .name = "TLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0, 162*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 163*1e32ee23SPeter Maydell .writefn = tlbiall_write }, 164*1e32ee23SPeter Maydell { .name = "TLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1, 165*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 166*1e32ee23SPeter Maydell .writefn = tlbimva_write }, 167*1e32ee23SPeter Maydell { .name = "TLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2, 168*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 169*1e32ee23SPeter Maydell .writefn = tlbiasid_write }, 170*1e32ee23SPeter Maydell { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3, 171*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 172*1e32ee23SPeter Maydell .writefn = tlbimvaa_write }, 173*1e32ee23SPeter Maydell }; 174*1e32ee23SPeter Maydell 175*1e32ee23SPeter Maydell static const ARMCPRegInfo tlbi_v7mp_cp_reginfo[] = { 176*1e32ee23SPeter Maydell /* 32 bit TLB invalidates, Inner Shareable */ 177*1e32ee23SPeter Maydell { .name = "TLBIALLIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0, 178*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 179*1e32ee23SPeter Maydell .writefn = tlbiall_is_write }, 180*1e32ee23SPeter Maydell { .name = "TLBIMVAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1, 181*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 182*1e32ee23SPeter Maydell .writefn = tlbimva_is_write }, 183*1e32ee23SPeter Maydell { .name = "TLBIASIDIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2, 184*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 185*1e32ee23SPeter Maydell .writefn = tlbiasid_is_write }, 186*1e32ee23SPeter Maydell { .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3, 187*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 188*1e32ee23SPeter Maydell .writefn = tlbimvaa_is_write }, 189*1e32ee23SPeter Maydell }; 190*1e32ee23SPeter Maydell 191*1e32ee23SPeter Maydell static const ARMCPRegInfo tlbi_v8_cp_reginfo[] = { 192*1e32ee23SPeter Maydell /* AArch32 TLB invalidate last level of translation table walk */ 193*1e32ee23SPeter Maydell { .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5, 194*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 195*1e32ee23SPeter Maydell .writefn = tlbimva_is_write }, 196*1e32ee23SPeter Maydell { .name = "TLBIMVAALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7, 197*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis, 198*1e32ee23SPeter Maydell .writefn = tlbimvaa_is_write }, 199*1e32ee23SPeter Maydell { .name = "TLBIMVAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5, 200*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 201*1e32ee23SPeter Maydell .writefn = tlbimva_write }, 202*1e32ee23SPeter Maydell { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7, 203*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb, 204*1e32ee23SPeter Maydell .writefn = tlbimvaa_write }, 205*1e32ee23SPeter Maydell { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5, 206*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL2_W, 207*1e32ee23SPeter Maydell .writefn = tlbimva_hyp_write }, 208*1e32ee23SPeter Maydell { .name = "TLBIMVALHIS", 209*1e32ee23SPeter Maydell .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5, 210*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL2_W, 211*1e32ee23SPeter Maydell .writefn = tlbimva_hyp_is_write }, 212*1e32ee23SPeter Maydell { .name = "TLBIIPAS2", 213*1e32ee23SPeter Maydell .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, 214*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL2_W, 215*1e32ee23SPeter Maydell .writefn = tlbiipas2_hyp_write }, 216*1e32ee23SPeter Maydell { .name = "TLBIIPAS2IS", 217*1e32ee23SPeter Maydell .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, 218*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL2_W, 219*1e32ee23SPeter Maydell .writefn = tlbiipas2is_hyp_write }, 220*1e32ee23SPeter Maydell { .name = "TLBIIPAS2L", 221*1e32ee23SPeter Maydell .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, 222*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL2_W, 223*1e32ee23SPeter Maydell .writefn = tlbiipas2_hyp_write }, 224*1e32ee23SPeter Maydell { .name = "TLBIIPAS2LIS", 225*1e32ee23SPeter Maydell .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, 226*1e32ee23SPeter Maydell .type = ARM_CP_NO_RAW, .access = PL2_W, 227*1e32ee23SPeter Maydell .writefn = tlbiipas2is_hyp_write }, 228*1e32ee23SPeter Maydell }; 229*1e32ee23SPeter Maydell 230*1e32ee23SPeter Maydell void define_tlb_insn_regs(ARMCPU *cpu) 231*1e32ee23SPeter Maydell { 232*1e32ee23SPeter Maydell CPUARMState *env = &cpu->env; 233*1e32ee23SPeter Maydell 234*1e32ee23SPeter Maydell if (!arm_feature(env, ARM_FEATURE_V7)) { 235*1e32ee23SPeter Maydell define_arm_cp_regs(cpu, tlbi_not_v7_cp_reginfo); 236*1e32ee23SPeter Maydell } else { 237*1e32ee23SPeter Maydell define_arm_cp_regs(cpu, tlbi_v7_cp_reginfo); 238*1e32ee23SPeter Maydell } 239*1e32ee23SPeter Maydell if (arm_feature(env, ARM_FEATURE_V7MP) && 240*1e32ee23SPeter Maydell !arm_feature(env, ARM_FEATURE_PMSA)) { 241*1e32ee23SPeter Maydell define_arm_cp_regs(cpu, tlbi_v7mp_cp_reginfo); 242*1e32ee23SPeter Maydell } 243*1e32ee23SPeter Maydell if (arm_feature(env, ARM_FEATURE_V8)) { 244*1e32ee23SPeter Maydell define_arm_cp_regs(cpu, tlbi_v8_cp_reginfo); 245*1e32ee23SPeter Maydell } 246*1e32ee23SPeter Maydell } 247