xref: /qemu/target/arm/tcg/tlb-insns.c (revision b0f7cd357218a0697b03e009e3cbc74d22a8133b)
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 "qemu/log.h"
10 #include "exec/exec-all.h"
11 #include "cpu.h"
12 #include "internals.h"
13 #include "cpu-features.h"
14 #include "cpregs.h"
15 
16 /* IS variants of TLB operations must affect all cores */
17 static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
18                              uint64_t value)
19 {
20     CPUState *cs = env_cpu(env);
21 
22     tlb_flush_all_cpus_synced(cs);
23 }
24 
25 static void tlbiasid_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
26                              uint64_t value)
27 {
28     CPUState *cs = env_cpu(env);
29 
30     tlb_flush_all_cpus_synced(cs);
31 }
32 
33 static void tlbimva_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
34                              uint64_t value)
35 {
36     CPUState *cs = env_cpu(env);
37 
38     tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK);
39 }
40 
41 static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
42                              uint64_t value)
43 {
44     CPUState *cs = env_cpu(env);
45 
46     tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK);
47 }
48 
49 static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri,
50                           uint64_t value)
51 {
52     /* Invalidate all (TLBIALL) */
53     CPUState *cs = env_cpu(env);
54 
55     if (tlb_force_broadcast(env)) {
56         tlb_flush_all_cpus_synced(cs);
57     } else {
58         tlb_flush(cs);
59     }
60 }
61 
62 static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri,
63                           uint64_t value)
64 {
65     /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */
66     CPUState *cs = env_cpu(env);
67 
68     value &= TARGET_PAGE_MASK;
69     if (tlb_force_broadcast(env)) {
70         tlb_flush_page_all_cpus_synced(cs, value);
71     } else {
72         tlb_flush_page(cs, value);
73     }
74 }
75 
76 static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri,
77                            uint64_t value)
78 {
79     /* Invalidate by ASID (TLBIASID) */
80     CPUState *cs = env_cpu(env);
81 
82     if (tlb_force_broadcast(env)) {
83         tlb_flush_all_cpus_synced(cs);
84     } else {
85         tlb_flush(cs);
86     }
87 }
88 
89 static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
90                            uint64_t value)
91 {
92     /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */
93     CPUState *cs = env_cpu(env);
94 
95     value &= TARGET_PAGE_MASK;
96     if (tlb_force_broadcast(env)) {
97         tlb_flush_page_all_cpus_synced(cs, value);
98     } else {
99         tlb_flush_page(cs, value);
100     }
101 }
102 
103 static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
104                               uint64_t value)
105 {
106     CPUState *cs = env_cpu(env);
107     uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
108 
109     tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
110 }
111 
112 static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
113                                  uint64_t value)
114 {
115     CPUState *cs = env_cpu(env);
116     uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
117 
118     tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
119                                              ARMMMUIdxBit_E2);
120 }
121 
122 static void tlbiipas2_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
123                                 uint64_t value)
124 {
125     CPUState *cs = env_cpu(env);
126     uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12;
127 
128     tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
129 }
130 
131 static void tlbiipas2is_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
132                                 uint64_t value)
133 {
134     CPUState *cs = env_cpu(env);
135     uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12;
136 
137     tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2);
138 }
139 
140 static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
141                                uint64_t value)
142 {
143     CPUState *cs = env_cpu(env);
144 
145     tlb_flush_by_mmuidx(cs, alle1_tlbmask(env));
146 }
147 
148 static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
149                                   uint64_t value)
150 {
151     CPUState *cs = env_cpu(env);
152 
153     tlb_flush_by_mmuidx_all_cpus_synced(cs, alle1_tlbmask(env));
154 }
155 
156 
157 static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
158                               uint64_t value)
159 {
160     CPUState *cs = env_cpu(env);
161 
162     tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
163 }
164 
165 static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
166                                  uint64_t value)
167 {
168     CPUState *cs = env_cpu(env);
169 
170     tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
171 }
172 
173 static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
174                                     uint64_t value)
175 {
176     CPUState *cs = env_cpu(env);
177     int mask = vae1_tlbmask(env);
178 
179     if (tlb_force_broadcast(env)) {
180         tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
181     } else {
182         tlb_flush_by_mmuidx(cs, mask);
183     }
184 }
185 
186 static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
187                                   uint64_t value)
188 {
189     CPUState *cs = env_cpu(env);
190     int mask = alle1_tlbmask(env);
191 
192     tlb_flush_by_mmuidx(cs, mask);
193 }
194 
195 static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
196                                   uint64_t value)
197 {
198     CPUState *cs = env_cpu(env);
199     int mask = e2_tlbmask(env);
200 
201     tlb_flush_by_mmuidx(cs, mask);
202 }
203 
204 static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
205                                   uint64_t value)
206 {
207     ARMCPU *cpu = env_archcpu(env);
208     CPUState *cs = CPU(cpu);
209 
210     tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E3);
211 }
212 
213 static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
214                                  uint64_t value)
215 {
216     /*
217      * Invalidate by VA, EL2
218      * Currently handles both VAE2 and VALE2, since we don't support
219      * flush-last-level-only.
220      */
221     CPUState *cs = env_cpu(env);
222     int mask = vae2_tlbmask(env);
223     uint64_t pageaddr = sextract64(value << 12, 0, 56);
224     int bits = vae2_tlbbits(env, pageaddr);
225 
226     tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
227 }
228 
229 static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
230                                  uint64_t value)
231 {
232     /*
233      * Invalidate by VA, EL3
234      * Currently handles both VAE3 and VALE3, since we don't support
235      * flush-last-level-only.
236      */
237     ARMCPU *cpu = env_archcpu(env);
238     CPUState *cs = CPU(cpu);
239     uint64_t pageaddr = sextract64(value << 12, 0, 56);
240 
241     tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E3);
242 }
243 
244 static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
245                                  uint64_t value)
246 {
247     /*
248      * Invalidate by VA, EL1&0 (AArch64 version).
249      * Currently handles all of VAE1, VAAE1, VAALE1 and VALE1,
250      * since we don't support flush-for-specific-ASID-only or
251      * flush-last-level-only.
252      */
253     CPUState *cs = env_cpu(env);
254     int mask = vae1_tlbmask(env);
255     uint64_t pageaddr = sextract64(value << 12, 0, 56);
256     int bits = vae1_tlbbits(env, pageaddr);
257 
258     if (tlb_force_broadcast(env)) {
259         tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
260     } else {
261         tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
262     }
263 }
264 
265 static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
266                                     uint64_t value)
267 {
268     CPUState *cs = env_cpu(env);
269     int mask = ipas2e1_tlbmask(env, value);
270     uint64_t pageaddr = sextract64(value << 12, 0, 56);
271 
272     if (tlb_force_broadcast(env)) {
273         tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
274     } else {
275         tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
276     }
277 }
278 
279 static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
280                                       uint64_t value)
281 {
282     CPUState *cs = env_cpu(env);
283     int mask = ipas2e1_tlbmask(env, value);
284     uint64_t pageaddr = sextract64(value << 12, 0, 56);
285 
286     tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
287 }
288 
289 static const ARMCPRegInfo tlbi_not_v7_cp_reginfo[] = {
290     /*
291      * MMU TLB control. Note that the wildcarding means we cover not just
292      * the unified TLB ops but also the dside/iside/inner-shareable variants.
293      */
294     { .name = "TLBIALL", .cp = 15, .crn = 8, .crm = CP_ANY,
295       .opc1 = CP_ANY, .opc2 = 0, .access = PL1_W, .writefn = tlbiall_write,
296       .type = ARM_CP_NO_RAW },
297     { .name = "TLBIMVA", .cp = 15, .crn = 8, .crm = CP_ANY,
298       .opc1 = CP_ANY, .opc2 = 1, .access = PL1_W, .writefn = tlbimva_write,
299       .type = ARM_CP_NO_RAW },
300     { .name = "TLBIASID", .cp = 15, .crn = 8, .crm = CP_ANY,
301       .opc1 = CP_ANY, .opc2 = 2, .access = PL1_W, .writefn = tlbiasid_write,
302       .type = ARM_CP_NO_RAW },
303     { .name = "TLBIMVAA", .cp = 15, .crn = 8, .crm = CP_ANY,
304       .opc1 = CP_ANY, .opc2 = 3, .access = PL1_W, .writefn = tlbimvaa_write,
305       .type = ARM_CP_NO_RAW },
306 };
307 
308 static const ARMCPRegInfo tlbi_v7_cp_reginfo[] = {
309     /* 32 bit ITLB invalidates */
310     { .name = "ITLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 0,
311       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
312       .writefn = tlbiall_write },
313     { .name = "ITLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1,
314       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
315       .writefn = tlbimva_write },
316     { .name = "ITLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 2,
317       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
318       .writefn = tlbiasid_write },
319     /* 32 bit DTLB invalidates */
320     { .name = "DTLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 0,
321       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
322       .writefn = tlbiall_write },
323     { .name = "DTLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1,
324       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
325       .writefn = tlbimva_write },
326     { .name = "DTLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 2,
327       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
328       .writefn = tlbiasid_write },
329     /* 32 bit TLB invalidates */
330     { .name = "TLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
331       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
332       .writefn = tlbiall_write },
333     { .name = "TLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
334       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
335       .writefn = tlbimva_write },
336     { .name = "TLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
337       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
338       .writefn = tlbiasid_write },
339     { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
340       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
341       .writefn = tlbimvaa_write },
342 };
343 
344 static const ARMCPRegInfo tlbi_v7mp_cp_reginfo[] = {
345     /* 32 bit TLB invalidates, Inner Shareable */
346     { .name = "TLBIALLIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
347       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
348       .writefn = tlbiall_is_write },
349     { .name = "TLBIMVAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
350       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
351       .writefn = tlbimva_is_write },
352     { .name = "TLBIASIDIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
353       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
354       .writefn = tlbiasid_is_write },
355     { .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
356       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
357       .writefn = tlbimvaa_is_write },
358 };
359 
360 static const ARMCPRegInfo tlbi_v8_cp_reginfo[] = {
361     /* AArch32 TLB invalidate last level of translation table walk */
362     { .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
363       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
364       .writefn = tlbimva_is_write },
365     { .name = "TLBIMVAALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
366       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
367       .writefn = tlbimvaa_is_write },
368     { .name = "TLBIMVAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
369       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
370       .writefn = tlbimva_write },
371     { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
372       .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
373       .writefn = tlbimvaa_write },
374     { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5,
375       .type = ARM_CP_NO_RAW, .access = PL2_W,
376       .writefn = tlbimva_hyp_write },
377     { .name = "TLBIMVALHIS",
378       .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5,
379       .type = ARM_CP_NO_RAW, .access = PL2_W,
380       .writefn = tlbimva_hyp_is_write },
381     { .name = "TLBIIPAS2",
382       .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
383       .type = ARM_CP_NO_RAW, .access = PL2_W,
384       .writefn = tlbiipas2_hyp_write },
385     { .name = "TLBIIPAS2IS",
386       .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
387       .type = ARM_CP_NO_RAW, .access = PL2_W,
388       .writefn = tlbiipas2is_hyp_write },
389     { .name = "TLBIIPAS2L",
390       .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
391       .type = ARM_CP_NO_RAW, .access = PL2_W,
392       .writefn = tlbiipas2_hyp_write },
393     { .name = "TLBIIPAS2LIS",
394       .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
395       .type = ARM_CP_NO_RAW, .access = PL2_W,
396       .writefn = tlbiipas2is_hyp_write },
397     /* AArch64 TLBI operations */
398     { .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64,
399       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
400       .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
401       .fgt = FGT_TLBIVMALLE1IS,
402       .writefn = tlbi_aa64_vmalle1is_write },
403     { .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64,
404       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
405       .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
406       .fgt = FGT_TLBIVAE1IS,
407       .writefn = tlbi_aa64_vae1is_write },
408     { .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64,
409       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
410       .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
411       .fgt = FGT_TLBIASIDE1IS,
412       .writefn = tlbi_aa64_vmalle1is_write },
413     { .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64,
414       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
415       .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
416       .fgt = FGT_TLBIVAAE1IS,
417       .writefn = tlbi_aa64_vae1is_write },
418     { .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64,
419       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
420       .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
421       .fgt = FGT_TLBIVALE1IS,
422       .writefn = tlbi_aa64_vae1is_write },
423     { .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64,
424       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
425       .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
426       .fgt = FGT_TLBIVAALE1IS,
427       .writefn = tlbi_aa64_vae1is_write },
428     { .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64,
429       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
430       .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
431       .fgt = FGT_TLBIVMALLE1,
432       .writefn = tlbi_aa64_vmalle1_write },
433     { .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64,
434       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
435       .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
436       .fgt = FGT_TLBIVAE1,
437       .writefn = tlbi_aa64_vae1_write },
438     { .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64,
439       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
440       .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
441       .fgt = FGT_TLBIASIDE1,
442       .writefn = tlbi_aa64_vmalle1_write },
443     { .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64,
444       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
445       .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
446       .fgt = FGT_TLBIVAAE1,
447       .writefn = tlbi_aa64_vae1_write },
448     { .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64,
449       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
450       .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
451       .fgt = FGT_TLBIVALE1,
452       .writefn = tlbi_aa64_vae1_write },
453     { .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64,
454       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
455       .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
456       .fgt = FGT_TLBIVAALE1,
457       .writefn = tlbi_aa64_vae1_write },
458     { .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64,
459       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
460       .access = PL2_W, .type = ARM_CP_NO_RAW,
461       .writefn = tlbi_aa64_ipas2e1is_write },
462     { .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64,
463       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
464       .access = PL2_W, .type = ARM_CP_NO_RAW,
465       .writefn = tlbi_aa64_ipas2e1is_write },
466     { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64,
467       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
468       .access = PL2_W, .type = ARM_CP_NO_RAW,
469       .writefn = tlbi_aa64_alle1is_write },
470     { .name = "TLBI_VMALLS12E1IS", .state = ARM_CP_STATE_AA64,
471       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 6,
472       .access = PL2_W, .type = ARM_CP_NO_RAW,
473       .writefn = tlbi_aa64_alle1is_write },
474     { .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64,
475       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
476       .access = PL2_W, .type = ARM_CP_NO_RAW,
477       .writefn = tlbi_aa64_ipas2e1_write },
478     { .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64,
479       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
480       .access = PL2_W, .type = ARM_CP_NO_RAW,
481       .writefn = tlbi_aa64_ipas2e1_write },
482     { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64,
483       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
484       .access = PL2_W, .type = ARM_CP_NO_RAW,
485       .writefn = tlbi_aa64_alle1_write },
486     { .name = "TLBI_VMALLS12E1", .state = ARM_CP_STATE_AA64,
487       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 6,
488       .access = PL2_W, .type = ARM_CP_NO_RAW,
489       .writefn = tlbi_aa64_alle1is_write },
490 };
491 
492 static const ARMCPRegInfo tlbi_el2_cp_reginfo[] = {
493     { .name = "TLBIALLNSNH",
494       .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
495       .type = ARM_CP_NO_RAW, .access = PL2_W,
496       .writefn = tlbiall_nsnh_write },
497     { .name = "TLBIALLNSNHIS",
498       .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
499       .type = ARM_CP_NO_RAW, .access = PL2_W,
500       .writefn = tlbiall_nsnh_is_write },
501     { .name = "TLBIALLH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
502       .type = ARM_CP_NO_RAW, .access = PL2_W,
503       .writefn = tlbiall_hyp_write },
504     { .name = "TLBIALLHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0,
505       .type = ARM_CP_NO_RAW, .access = PL2_W,
506       .writefn = tlbiall_hyp_is_write },
507     { .name = "TLBIMVAH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1,
508       .type = ARM_CP_NO_RAW, .access = PL2_W,
509       .writefn = tlbimva_hyp_write },
510     { .name = "TLBIMVAHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1,
511       .type = ARM_CP_NO_RAW, .access = PL2_W,
512       .writefn = tlbimva_hyp_is_write },
513     { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64,
514       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
515       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
516       .writefn = tlbi_aa64_alle2_write },
517     { .name = "TLBI_VAE2", .state = ARM_CP_STATE_AA64,
518       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1,
519       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
520       .writefn = tlbi_aa64_vae2_write },
521     { .name = "TLBI_VALE2", .state = ARM_CP_STATE_AA64,
522       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5,
523       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
524       .writefn = tlbi_aa64_vae2_write },
525     { .name = "TLBI_ALLE2IS", .state = ARM_CP_STATE_AA64,
526       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0,
527       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
528       .writefn = tlbi_aa64_alle2is_write },
529     { .name = "TLBI_VAE2IS", .state = ARM_CP_STATE_AA64,
530       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1,
531       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
532       .writefn = tlbi_aa64_vae2is_write },
533     { .name = "TLBI_VALE2IS", .state = ARM_CP_STATE_AA64,
534       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5,
535       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
536       .writefn = tlbi_aa64_vae2is_write },
537 };
538 
539 static const ARMCPRegInfo tlbi_el3_cp_reginfo[] = {
540     { .name = "TLBI_ALLE3IS", .state = ARM_CP_STATE_AA64,
541       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 0,
542       .access = PL3_W, .type = ARM_CP_NO_RAW,
543       .writefn = tlbi_aa64_alle3is_write },
544     { .name = "TLBI_VAE3IS", .state = ARM_CP_STATE_AA64,
545       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 1,
546       .access = PL3_W, .type = ARM_CP_NO_RAW,
547       .writefn = tlbi_aa64_vae3is_write },
548     { .name = "TLBI_VALE3IS", .state = ARM_CP_STATE_AA64,
549       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 5,
550       .access = PL3_W, .type = ARM_CP_NO_RAW,
551       .writefn = tlbi_aa64_vae3is_write },
552     { .name = "TLBI_ALLE3", .state = ARM_CP_STATE_AA64,
553       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 0,
554       .access = PL3_W, .type = ARM_CP_NO_RAW,
555       .writefn = tlbi_aa64_alle3_write },
556     { .name = "TLBI_VAE3", .state = ARM_CP_STATE_AA64,
557       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 1,
558       .access = PL3_W, .type = ARM_CP_NO_RAW,
559       .writefn = tlbi_aa64_vae3_write },
560     { .name = "TLBI_VALE3", .state = ARM_CP_STATE_AA64,
561       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 5,
562       .access = PL3_W, .type = ARM_CP_NO_RAW,
563       .writefn = tlbi_aa64_vae3_write },
564 };
565 
566 #ifdef TARGET_AARCH64
567 typedef struct {
568     uint64_t base;
569     uint64_t length;
570 } TLBIRange;
571 
572 static ARMGranuleSize tlbi_range_tg_to_gran_size(int tg)
573 {
574     /*
575      * Note that the TLBI range TG field encoding differs from both
576      * TG0 and TG1 encodings.
577      */
578     switch (tg) {
579     case 1:
580         return Gran4K;
581     case 2:
582         return Gran16K;
583     case 3:
584         return Gran64K;
585     default:
586         return GranInvalid;
587     }
588 }
589 
590 static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
591                                      uint64_t value)
592 {
593     unsigned int page_size_granule, page_shift, num, scale, exponent;
594     /* Extract one bit to represent the va selector in use. */
595     uint64_t select = sextract64(value, 36, 1);
596     ARMVAParameters param = aa64_va_parameters(env, select, mmuidx, true, false);
597     TLBIRange ret = { };
598     ARMGranuleSize gran;
599 
600     page_size_granule = extract64(value, 46, 2);
601     gran = tlbi_range_tg_to_gran_size(page_size_granule);
602 
603     /* The granule encoded in value must match the granule in use. */
604     if (gran != param.gran) {
605         qemu_log_mask(LOG_GUEST_ERROR, "Invalid tlbi page size granule %d\n",
606                       page_size_granule);
607         return ret;
608     }
609 
610     page_shift = arm_granule_bits(gran);
611     num = extract64(value, 39, 5);
612     scale = extract64(value, 44, 2);
613     exponent = (5 * scale) + 1;
614 
615     ret.length = (num + 1) << (exponent + page_shift);
616 
617     if (param.select) {
618         ret.base = sextract64(value, 0, 37);
619     } else {
620         ret.base = extract64(value, 0, 37);
621     }
622     if (param.ds) {
623         /*
624          * With DS=1, BaseADDR is always shifted 16 so that it is able
625          * to address all 52 va bits.  The input address is perforce
626          * aligned on a 64k boundary regardless of translation granule.
627          */
628         page_shift = 16;
629     }
630     ret.base <<= page_shift;
631 
632     return ret;
633 }
634 
635 static void do_rvae_write(CPUARMState *env, uint64_t value,
636                           int idxmap, bool synced)
637 {
638     ARMMMUIdx one_idx = ARM_MMU_IDX_A | ctz32(idxmap);
639     TLBIRange range;
640     int bits;
641 
642     range = tlbi_aa64_get_range(env, one_idx, value);
643     bits = tlbbits_for_regime(env, one_idx, range.base);
644 
645     if (synced) {
646         tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env),
647                                                   range.base,
648                                                   range.length,
649                                                   idxmap,
650                                                   bits);
651     } else {
652         tlb_flush_range_by_mmuidx(env_cpu(env), range.base,
653                                   range.length, idxmap, bits);
654     }
655 }
656 
657 static void tlbi_aa64_rvae1_write(CPUARMState *env,
658                                   const ARMCPRegInfo *ri,
659                                   uint64_t value)
660 {
661     /*
662      * Invalidate by VA range, EL1&0.
663      * Currently handles all of RVAE1, RVAAE1, RVAALE1 and RVALE1,
664      * since we don't support flush-for-specific-ASID-only or
665      * flush-last-level-only.
666      */
667 
668     do_rvae_write(env, value, vae1_tlbmask(env),
669                   tlb_force_broadcast(env));
670 }
671 
672 static void tlbi_aa64_rvae1is_write(CPUARMState *env,
673                                     const ARMCPRegInfo *ri,
674                                     uint64_t value)
675 {
676     /*
677      * Invalidate by VA range, Inner/Outer Shareable EL1&0.
678      * Currently handles all of RVAE1IS, RVAE1OS, RVAAE1IS, RVAAE1OS,
679      * RVAALE1IS, RVAALE1OS, RVALE1IS and RVALE1OS, since we don't support
680      * flush-for-specific-ASID-only, flush-last-level-only or inner/outer
681      * shareable specific flushes.
682      */
683 
684     do_rvae_write(env, value, vae1_tlbmask(env), true);
685 }
686 
687 static void tlbi_aa64_rvae2_write(CPUARMState *env,
688                                   const ARMCPRegInfo *ri,
689                                   uint64_t value)
690 {
691     /*
692      * Invalidate by VA range, EL2.
693      * Currently handles all of RVAE2 and RVALE2,
694      * since we don't support flush-for-specific-ASID-only or
695      * flush-last-level-only.
696      */
697 
698     do_rvae_write(env, value, vae2_tlbmask(env),
699                   tlb_force_broadcast(env));
700 
701 
702 }
703 
704 static void tlbi_aa64_rvae2is_write(CPUARMState *env,
705                                     const ARMCPRegInfo *ri,
706                                     uint64_t value)
707 {
708     /*
709      * Invalidate by VA range, Inner/Outer Shareable, EL2.
710      * Currently handles all of RVAE2IS, RVAE2OS, RVALE2IS and RVALE2OS,
711      * since we don't support flush-for-specific-ASID-only,
712      * flush-last-level-only or inner/outer shareable specific flushes.
713      */
714 
715     do_rvae_write(env, value, vae2_tlbmask(env), true);
716 
717 }
718 
719 static void tlbi_aa64_rvae3_write(CPUARMState *env,
720                                   const ARMCPRegInfo *ri,
721                                   uint64_t value)
722 {
723     /*
724      * Invalidate by VA range, EL3.
725      * Currently handles all of RVAE3 and RVALE3,
726      * since we don't support flush-for-specific-ASID-only or
727      * flush-last-level-only.
728      */
729 
730     do_rvae_write(env, value, ARMMMUIdxBit_E3, tlb_force_broadcast(env));
731 }
732 
733 static void tlbi_aa64_rvae3is_write(CPUARMState *env,
734                                     const ARMCPRegInfo *ri,
735                                     uint64_t value)
736 {
737     /*
738      * Invalidate by VA range, EL3, Inner/Outer Shareable.
739      * Currently handles all of RVAE3IS, RVAE3OS, RVALE3IS and RVALE3OS,
740      * since we don't support flush-for-specific-ASID-only,
741      * flush-last-level-only or inner/outer specific flushes.
742      */
743 
744     do_rvae_write(env, value, ARMMMUIdxBit_E3, true);
745 }
746 
747 static void tlbi_aa64_ripas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
748                                      uint64_t value)
749 {
750     do_rvae_write(env, value, ipas2e1_tlbmask(env, value),
751                   tlb_force_broadcast(env));
752 }
753 
754 static void tlbi_aa64_ripas2e1is_write(CPUARMState *env,
755                                        const ARMCPRegInfo *ri,
756                                        uint64_t value)
757 {
758     do_rvae_write(env, value, ipas2e1_tlbmask(env, value), true);
759 }
760 
761 static const ARMCPRegInfo tlbirange_reginfo[] = {
762     { .name = "TLBI_RVAE1IS", .state = ARM_CP_STATE_AA64,
763       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 1,
764       .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
765       .fgt = FGT_TLBIRVAE1IS,
766       .writefn = tlbi_aa64_rvae1is_write },
767     { .name = "TLBI_RVAAE1IS", .state = ARM_CP_STATE_AA64,
768       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 3,
769       .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
770       .fgt = FGT_TLBIRVAAE1IS,
771       .writefn = tlbi_aa64_rvae1is_write },
772    { .name = "TLBI_RVALE1IS", .state = ARM_CP_STATE_AA64,
773       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 5,
774       .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
775       .fgt = FGT_TLBIRVALE1IS,
776       .writefn = tlbi_aa64_rvae1is_write },
777     { .name = "TLBI_RVAALE1IS", .state = ARM_CP_STATE_AA64,
778       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 7,
779       .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
780       .fgt = FGT_TLBIRVAALE1IS,
781       .writefn = tlbi_aa64_rvae1is_write },
782     { .name = "TLBI_RVAE1OS", .state = ARM_CP_STATE_AA64,
783       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1,
784       .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
785       .fgt = FGT_TLBIRVAE1OS,
786       .writefn = tlbi_aa64_rvae1is_write },
787     { .name = "TLBI_RVAAE1OS", .state = ARM_CP_STATE_AA64,
788       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 3,
789       .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
790       .fgt = FGT_TLBIRVAAE1OS,
791       .writefn = tlbi_aa64_rvae1is_write },
792    { .name = "TLBI_RVALE1OS", .state = ARM_CP_STATE_AA64,
793       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 5,
794       .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
795       .fgt = FGT_TLBIRVALE1OS,
796       .writefn = tlbi_aa64_rvae1is_write },
797     { .name = "TLBI_RVAALE1OS", .state = ARM_CP_STATE_AA64,
798       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 7,
799       .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
800       .fgt = FGT_TLBIRVAALE1OS,
801       .writefn = tlbi_aa64_rvae1is_write },
802     { .name = "TLBI_RVAE1", .state = ARM_CP_STATE_AA64,
803       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1,
804       .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
805       .fgt = FGT_TLBIRVAE1,
806       .writefn = tlbi_aa64_rvae1_write },
807     { .name = "TLBI_RVAAE1", .state = ARM_CP_STATE_AA64,
808       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 3,
809       .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
810       .fgt = FGT_TLBIRVAAE1,
811       .writefn = tlbi_aa64_rvae1_write },
812    { .name = "TLBI_RVALE1", .state = ARM_CP_STATE_AA64,
813       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 5,
814       .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
815       .fgt = FGT_TLBIRVALE1,
816       .writefn = tlbi_aa64_rvae1_write },
817     { .name = "TLBI_RVAALE1", .state = ARM_CP_STATE_AA64,
818       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 7,
819       .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
820       .fgt = FGT_TLBIRVAALE1,
821       .writefn = tlbi_aa64_rvae1_write },
822     { .name = "TLBI_RIPAS2E1IS", .state = ARM_CP_STATE_AA64,
823       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 2,
824       .access = PL2_W, .type = ARM_CP_NO_RAW,
825       .writefn = tlbi_aa64_ripas2e1is_write },
826     { .name = "TLBI_RIPAS2LE1IS", .state = ARM_CP_STATE_AA64,
827       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 6,
828       .access = PL2_W, .type = ARM_CP_NO_RAW,
829       .writefn = tlbi_aa64_ripas2e1is_write },
830     { .name = "TLBI_RVAE2IS", .state = ARM_CP_STATE_AA64,
831       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 2, .opc2 = 1,
832       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
833       .writefn = tlbi_aa64_rvae2is_write },
834    { .name = "TLBI_RVALE2IS", .state = ARM_CP_STATE_AA64,
835       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 2, .opc2 = 5,
836       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
837       .writefn = tlbi_aa64_rvae2is_write },
838     { .name = "TLBI_RIPAS2E1", .state = ARM_CP_STATE_AA64,
839       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 2,
840       .access = PL2_W, .type = ARM_CP_NO_RAW,
841       .writefn = tlbi_aa64_ripas2e1_write },
842     { .name = "TLBI_RIPAS2LE1", .state = ARM_CP_STATE_AA64,
843       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 6,
844       .access = PL2_W, .type = ARM_CP_NO_RAW,
845       .writefn = tlbi_aa64_ripas2e1_write },
846    { .name = "TLBI_RVAE2OS", .state = ARM_CP_STATE_AA64,
847       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 5, .opc2 = 1,
848       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
849       .writefn = tlbi_aa64_rvae2is_write },
850    { .name = "TLBI_RVALE2OS", .state = ARM_CP_STATE_AA64,
851       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 5, .opc2 = 5,
852       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
853       .writefn = tlbi_aa64_rvae2is_write },
854     { .name = "TLBI_RVAE2", .state = ARM_CP_STATE_AA64,
855       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 6, .opc2 = 1,
856       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
857       .writefn = tlbi_aa64_rvae2_write },
858    { .name = "TLBI_RVALE2", .state = ARM_CP_STATE_AA64,
859       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 6, .opc2 = 5,
860       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
861       .writefn = tlbi_aa64_rvae2_write },
862    { .name = "TLBI_RVAE3IS", .state = ARM_CP_STATE_AA64,
863       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 2, .opc2 = 1,
864       .access = PL3_W, .type = ARM_CP_NO_RAW,
865       .writefn = tlbi_aa64_rvae3is_write },
866    { .name = "TLBI_RVALE3IS", .state = ARM_CP_STATE_AA64,
867       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 2, .opc2 = 5,
868       .access = PL3_W, .type = ARM_CP_NO_RAW,
869       .writefn = tlbi_aa64_rvae3is_write },
870    { .name = "TLBI_RVAE3OS", .state = ARM_CP_STATE_AA64,
871       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 5, .opc2 = 1,
872       .access = PL3_W, .type = ARM_CP_NO_RAW,
873       .writefn = tlbi_aa64_rvae3is_write },
874    { .name = "TLBI_RVALE3OS", .state = ARM_CP_STATE_AA64,
875       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 5, .opc2 = 5,
876       .access = PL3_W, .type = ARM_CP_NO_RAW,
877       .writefn = tlbi_aa64_rvae3is_write },
878    { .name = "TLBI_RVAE3", .state = ARM_CP_STATE_AA64,
879       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 6, .opc2 = 1,
880       .access = PL3_W, .type = ARM_CP_NO_RAW,
881       .writefn = tlbi_aa64_rvae3_write },
882    { .name = "TLBI_RVALE3", .state = ARM_CP_STATE_AA64,
883       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 6, .opc2 = 5,
884       .access = PL3_W, .type = ARM_CP_NO_RAW,
885       .writefn = tlbi_aa64_rvae3_write },
886 };
887 
888 static const ARMCPRegInfo tlbios_reginfo[] = {
889     { .name = "TLBI_VMALLE1OS", .state = ARM_CP_STATE_AA64,
890       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 0,
891       .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
892       .fgt = FGT_TLBIVMALLE1OS,
893       .writefn = tlbi_aa64_vmalle1is_write },
894     { .name = "TLBI_VAE1OS", .state = ARM_CP_STATE_AA64,
895       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 1,
896       .fgt = FGT_TLBIVAE1OS,
897       .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
898       .writefn = tlbi_aa64_vae1is_write },
899     { .name = "TLBI_ASIDE1OS", .state = ARM_CP_STATE_AA64,
900       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 2,
901       .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
902       .fgt = FGT_TLBIASIDE1OS,
903       .writefn = tlbi_aa64_vmalle1is_write },
904     { .name = "TLBI_VAAE1OS", .state = ARM_CP_STATE_AA64,
905       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 3,
906       .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
907       .fgt = FGT_TLBIVAAE1OS,
908       .writefn = tlbi_aa64_vae1is_write },
909     { .name = "TLBI_VALE1OS", .state = ARM_CP_STATE_AA64,
910       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 5,
911       .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
912       .fgt = FGT_TLBIVALE1OS,
913       .writefn = tlbi_aa64_vae1is_write },
914     { .name = "TLBI_VAALE1OS", .state = ARM_CP_STATE_AA64,
915       .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 7,
916       .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
917       .fgt = FGT_TLBIVAALE1OS,
918       .writefn = tlbi_aa64_vae1is_write },
919     { .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64,
920       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0,
921       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
922       .writefn = tlbi_aa64_alle2is_write },
923     { .name = "TLBI_VAE2OS", .state = ARM_CP_STATE_AA64,
924       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 1,
925       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
926       .writefn = tlbi_aa64_vae2is_write },
927    { .name = "TLBI_ALLE1OS", .state = ARM_CP_STATE_AA64,
928       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 4,
929       .access = PL2_W, .type = ARM_CP_NO_RAW,
930       .writefn = tlbi_aa64_alle1is_write },
931     { .name = "TLBI_VALE2OS", .state = ARM_CP_STATE_AA64,
932       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 5,
933       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
934       .writefn = tlbi_aa64_vae2is_write },
935     { .name = "TLBI_VMALLS12E1OS", .state = ARM_CP_STATE_AA64,
936       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 6,
937       .access = PL2_W, .type = ARM_CP_NO_RAW,
938       .writefn = tlbi_aa64_alle1is_write },
939     { .name = "TLBI_IPAS2E1OS", .state = ARM_CP_STATE_AA64,
940       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 0,
941       .access = PL2_W, .type = ARM_CP_NOP },
942     { .name = "TLBI_RIPAS2E1OS", .state = ARM_CP_STATE_AA64,
943       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 3,
944       .access = PL2_W, .type = ARM_CP_NOP },
945     { .name = "TLBI_IPAS2LE1OS", .state = ARM_CP_STATE_AA64,
946       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 4,
947       .access = PL2_W, .type = ARM_CP_NOP },
948     { .name = "TLBI_RIPAS2LE1OS", .state = ARM_CP_STATE_AA64,
949       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 7,
950       .access = PL2_W, .type = ARM_CP_NOP },
951     { .name = "TLBI_ALLE3OS", .state = ARM_CP_STATE_AA64,
952       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 0,
953       .access = PL3_W, .type = ARM_CP_NO_RAW,
954       .writefn = tlbi_aa64_alle3is_write },
955     { .name = "TLBI_VAE3OS", .state = ARM_CP_STATE_AA64,
956       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 1,
957       .access = PL3_W, .type = ARM_CP_NO_RAW,
958       .writefn = tlbi_aa64_vae3is_write },
959     { .name = "TLBI_VALE3OS", .state = ARM_CP_STATE_AA64,
960       .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 5,
961       .access = PL3_W, .type = ARM_CP_NO_RAW,
962       .writefn = tlbi_aa64_vae3is_write },
963 };
964 #endif
965 
966 void define_tlb_insn_regs(ARMCPU *cpu)
967 {
968     CPUARMState *env = &cpu->env;
969 
970     if (!arm_feature(env, ARM_FEATURE_V7)) {
971         define_arm_cp_regs(cpu, tlbi_not_v7_cp_reginfo);
972     } else {
973         define_arm_cp_regs(cpu, tlbi_v7_cp_reginfo);
974     }
975     if (arm_feature(env, ARM_FEATURE_V7MP) &&
976         !arm_feature(env, ARM_FEATURE_PMSA)) {
977         define_arm_cp_regs(cpu, tlbi_v7mp_cp_reginfo);
978     }
979     if (arm_feature(env, ARM_FEATURE_V8)) {
980         define_arm_cp_regs(cpu, tlbi_v8_cp_reginfo);
981     }
982     /*
983      * We retain the existing logic for when to register these TLBI
984      * ops (i.e. matching the condition for el2_cp_reginfo[] in
985      * helper.c), but we will be able to simplify this later.
986      */
987     if (arm_feature(env, ARM_FEATURE_EL2)
988         || (arm_feature(env, ARM_FEATURE_EL3)
989             && arm_feature(env, ARM_FEATURE_V8))) {
990         define_arm_cp_regs(cpu, tlbi_el2_cp_reginfo);
991     }
992     if (arm_feature(env, ARM_FEATURE_EL3)) {
993         define_arm_cp_regs(cpu, tlbi_el3_cp_reginfo);
994     }
995 #ifdef TARGET_AARCH64
996     if (cpu_isar_feature(aa64_tlbirange, cpu)) {
997         define_arm_cp_regs(cpu, tlbirange_reginfo);
998     }
999     if (cpu_isar_feature(aa64_tlbios, cpu)) {
1000         define_arm_cp_regs(cpu, tlbios_reginfo);
1001     }
1002 #endif
1003 }
1004