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