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