xref: /qemu/target/arm/tcg/tlb-insns.c (revision 1e32ee23cdc5405a5b575286bbfa705d78da410c)
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