xref: /openbmc/qemu/target/arm/tcg/cpregs-at.c (revision f0007b7f03e2d7fc33e71c3a582f2364c51a226b)
1 /*
2  * System instructions for address translation
3  * SPDX-License-Identifier: GPL-2.0-or-later
4  */
5 
6 #include "qemu/osdep.h"
7 #include "cpu.h"
8 #include "cpu-features.h"
9 #include "internals.h"
10 #include "cpregs.h"
11 
12 
13 static int par_el1_shareability(GetPhysAddrResult *res)
14 {
15     /*
16      * The PAR_EL1.SH field must be 0b10 for Device or Normal-NC
17      * memory -- see pseudocode PAREncodeShareability().
18      */
19     if (((res->cacheattrs.attrs & 0xf0) == 0) ||
20         res->cacheattrs.attrs == 0x44 || res->cacheattrs.attrs == 0x40) {
21         return 2;
22     }
23     return res->cacheattrs.shareability;
24 }
25 
26 static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
27                              unsigned prot_check, ARMMMUIdx mmu_idx,
28                              ARMSecuritySpace ss)
29 {
30     uint64_t par64;
31     bool format64 = false;
32     ARMMMUFaultInfo fi = {};
33     GetPhysAddrResult res = {};
34     bool ret = get_phys_addr_for_at(env, value, prot_check,
35                                     mmu_idx, ss, &res, &fi);
36 
37     /*
38      * ATS operations only do S1 or S1+S2 translations, so we never
39      * have to deal with the ARMCacheAttrs format for S2 only.
40      */
41     assert(!res.cacheattrs.is_s2_format);
42 
43     if (ret) {
44         /*
45          * Some kinds of translation fault must cause exceptions rather
46          * than being reported in the PAR.
47          */
48         int current_el = arm_current_el(env);
49         int target_el;
50         uint32_t syn, fsr, fsc;
51         bool take_exc = false;
52 
53         if (fi.s1ptw && current_el == 1
54             && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
55             /*
56              * Synchronous stage 2 fault on an access made as part of the
57              * translation table walk for AT S1E0* or AT S1E1* insn
58              * executed from NS EL1. If this is a synchronous external abort
59              * and SCR_EL3.EA == 1, then we take a synchronous external abort
60              * to EL3. Otherwise the fault is taken as an exception to EL2,
61              * and HPFAR_EL2 holds the faulting IPA.
62              */
63             if (fi.type == ARMFault_SyncExternalOnWalk &&
64                 (env->cp15.scr_el3 & SCR_EA)) {
65                 target_el = 3;
66             } else {
67                 env->cp15.hpfar_el2 = extract64(fi.s2addr, 12, 47) << 4;
68                 if (arm_is_secure_below_el3(env) && fi.s1ns) {
69                     env->cp15.hpfar_el2 |= HPFAR_NS;
70                 }
71                 target_el = 2;
72             }
73             take_exc = true;
74         } else if (fi.type == ARMFault_SyncExternalOnWalk) {
75             /*
76              * Synchronous external aborts during a translation table walk
77              * are taken as Data Abort exceptions.
78              */
79             if (fi.stage2) {
80                 if (current_el == 3) {
81                     target_el = 3;
82                 } else {
83                     target_el = 2;
84                 }
85             } else {
86                 target_el = exception_target_el(env);
87             }
88             take_exc = true;
89         }
90 
91         if (take_exc) {
92             /* Construct FSR and FSC using same logic as arm_deliver_fault() */
93             if (target_el == 2 || arm_el_is_aa64(env, target_el) ||
94                 arm_s1_regime_using_lpae_format(env, mmu_idx)) {
95                 fsr = arm_fi_to_lfsc(&fi);
96                 fsc = extract32(fsr, 0, 6);
97             } else {
98                 fsr = arm_fi_to_sfsc(&fi);
99                 fsc = 0x3f;
100             }
101             /*
102              * Report exception with ESR indicating a fault due to a
103              * translation table walk for a cache maintenance instruction.
104              */
105             syn = syn_data_abort_no_iss(current_el == target_el, 0,
106                                         fi.ea, 1, fi.s1ptw, 1, fsc);
107             env->exception.vaddress = value;
108             env->exception.fsr = fsr;
109             raise_exception(env, EXCP_DATA_ABORT, syn, target_el);
110         }
111     }
112 
113     if (is_a64(env)) {
114         format64 = true;
115     } else if (arm_feature(env, ARM_FEATURE_LPAE)) {
116         /*
117          * ATS1Cxx:
118          * * TTBCR.EAE determines whether the result is returned using the
119          *   32-bit or the 64-bit PAR format
120          * * Instructions executed in Hyp mode always use the 64bit format
121          *
122          * ATS1S2NSOxx uses the 64bit format if any of the following is true:
123          * * The Non-secure TTBCR.EAE bit is set to 1
124          * * The implementation includes EL2, and the value of HCR.VM is 1
125          *
126          * (Note that HCR.DC makes HCR.VM behave as if it is 1.)
127          *
128          * ATS1Hx always uses the 64bit format.
129          */
130         format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
131 
132         if (arm_feature(env, ARM_FEATURE_EL2)) {
133             if (mmu_idx == ARMMMUIdx_E10_0 ||
134                 mmu_idx == ARMMMUIdx_E10_1 ||
135                 mmu_idx == ARMMMUIdx_E10_1_PAN) {
136                 format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
137             } else {
138                 format64 |= arm_current_el(env) == 2;
139             }
140         }
141     }
142 
143     if (format64) {
144         /* Create a 64-bit PAR */
145         par64 = (1 << 11); /* LPAE bit always set */
146         if (!ret) {
147             par64 |= res.f.phys_addr & ~0xfffULL;
148             if (!res.f.attrs.secure) {
149                 par64 |= (1 << 9); /* NS */
150             }
151             par64 |= (uint64_t)res.cacheattrs.attrs << 56; /* ATTR */
152             par64 |= par_el1_shareability(&res) << 7; /* SH */
153         } else {
154             uint32_t fsr = arm_fi_to_lfsc(&fi);
155 
156             par64 |= 1; /* F */
157             par64 |= (fsr & 0x3f) << 1; /* FS */
158             if (fi.stage2) {
159                 par64 |= (1 << 9); /* S */
160             }
161             if (fi.s1ptw) {
162                 par64 |= (1 << 8); /* PTW */
163             }
164         }
165     } else {
166         /*
167          * fsr is a DFSR/IFSR value for the short descriptor
168          * translation table format (with WnR always clear).
169          * Convert it to a 32-bit PAR.
170          */
171         if (!ret) {
172             /* We do not set any attribute bits in the PAR */
173             if (res.f.lg_page_size == 24
174                 && arm_feature(env, ARM_FEATURE_V7)) {
175                 par64 = (res.f.phys_addr & 0xff000000) | (1 << 1);
176             } else {
177                 par64 = res.f.phys_addr & 0xfffff000;
178             }
179             if (!res.f.attrs.secure) {
180                 par64 |= (1 << 9); /* NS */
181             }
182         } else {
183             uint32_t fsr = arm_fi_to_sfsc(&fi);
184 
185             par64 = ((fsr & (1 << 10)) >> 5) | ((fsr & (1 << 12)) >> 6) |
186                     ((fsr & 0xf) << 1) | 1;
187         }
188     }
189     return par64;
190 }
191 
192 static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
193 {
194     unsigned access_perm = ri->opc2 & 1 ? PAGE_WRITE : PAGE_READ;
195     uint64_t par64;
196     ARMMMUIdx mmu_idx;
197     int el = arm_current_el(env);
198     ARMSecuritySpace ss = arm_security_space(env);
199 
200     switch (ri->opc2 & 6) {
201     case 0:
202         /* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP */
203         switch (el) {
204         case 3:
205             if (ri->crm == 9 && arm_pan_enabled(env)) {
206                 mmu_idx = ARMMMUIdx_E30_3_PAN;
207             } else {
208                 mmu_idx = ARMMMUIdx_E3;
209             }
210             break;
211         case 2:
212             g_assert(ss != ARMSS_Secure);  /* ARMv8.4-SecEL2 is 64-bit only */
213             /* fall through */
214         case 1:
215             if (ri->crm == 9 && arm_pan_enabled(env)) {
216                 mmu_idx = ARMMMUIdx_Stage1_E1_PAN;
217             } else {
218                 mmu_idx = ARMMMUIdx_Stage1_E1;
219             }
220             break;
221         default:
222             g_assert_not_reached();
223         }
224         break;
225     case 2:
226         /* stage 1 current state PL0: ATS1CUR, ATS1CUW */
227         switch (el) {
228         case 3:
229             mmu_idx = ARMMMUIdx_E30_0;
230             break;
231         case 2:
232             g_assert(ss != ARMSS_Secure);  /* ARMv8.4-SecEL2 is 64-bit only */
233             mmu_idx = ARMMMUIdx_Stage1_E0;
234             break;
235         case 1:
236             mmu_idx = ARMMMUIdx_Stage1_E0;
237             break;
238         default:
239             g_assert_not_reached();
240         }
241         break;
242     case 4:
243         /* stage 1+2 NonSecure PL1: ATS12NSOPR, ATS12NSOPW */
244         mmu_idx = ARMMMUIdx_E10_1;
245         ss = ARMSS_NonSecure;
246         break;
247     case 6:
248         /* stage 1+2 NonSecure PL0: ATS12NSOUR, ATS12NSOUW */
249         mmu_idx = ARMMMUIdx_E10_0;
250         ss = ARMSS_NonSecure;
251         break;
252     default:
253         g_assert_not_reached();
254     }
255 
256     par64 = do_ats_write(env, value, access_perm, mmu_idx, ss);
257 
258     A32_BANKED_CURRENT_REG_SET(env, par, par64);
259 }
260 
261 static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
262                         uint64_t value)
263 {
264     unsigned access_perm = ri->opc2 & 1 ? PAGE_WRITE : PAGE_READ;
265     uint64_t par64;
266 
267     /* There is no SecureEL2 for AArch32. */
268     par64 = do_ats_write(env, value, access_perm, ARMMMUIdx_E2,
269                          ARMSS_NonSecure);
270 
271     A32_BANKED_CURRENT_REG_SET(env, par, par64);
272 }
273 
274 static CPAccessResult at_e012_access(CPUARMState *env, const ARMCPRegInfo *ri,
275                                      bool isread)
276 {
277     /*
278      * R_NYXTL: instruction is UNDEFINED if it applies to an Exception level
279      * lower than EL3 and the combination SCR_EL3.{NSE,NS} is reserved. This can
280      * only happen when executing at EL3 because that combination also causes an
281      * illegal exception return. We don't need to check FEAT_RME either, because
282      * scr_write() ensures that the NSE bit is not set otherwise.
283      */
284     if ((env->cp15.scr_el3 & (SCR_NSE | SCR_NS)) == SCR_NSE) {
285         return CP_ACCESS_UNDEFINED;
286     }
287     return CP_ACCESS_OK;
288 }
289 
290 static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri,
291                                      bool isread)
292 {
293     if (arm_current_el(env) == 3 &&
294         !(env->cp15.scr_el3 & (SCR_NS | SCR_EEL2))) {
295         return CP_ACCESS_UNDEFINED;
296     }
297     return at_e012_access(env, ri, isread);
298 }
299 
300 static CPAccessResult at_s1e01_access(CPUARMState *env, const ARMCPRegInfo *ri,
301                                       bool isread)
302 {
303     if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_AT)) {
304         return CP_ACCESS_TRAP_EL2;
305     }
306     return at_e012_access(env, ri, isread);
307 }
308 
309 static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
310                         uint64_t value)
311 {
312     unsigned access_perm = ri->opc2 & 1 ? PAGE_WRITE : PAGE_READ;
313     ARMMMUIdx mmu_idx;
314     uint64_t hcr_el2 = arm_hcr_el2_eff(env);
315     bool regime_e20 = (hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE);
316     bool for_el3 = false;
317     ARMSecuritySpace ss;
318 
319     switch (ri->opc2 & 6) {
320     case 0:
321         switch (ri->opc1) {
322         case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */
323             if (ri->crm == 9 && arm_pan_enabled(env)) {
324                 mmu_idx = regime_e20 ?
325                           ARMMMUIdx_E20_2_PAN : ARMMMUIdx_Stage1_E1_PAN;
326             } else {
327                 mmu_idx = regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_Stage1_E1;
328             }
329             break;
330         case 4: /* AT S1E2R, AT S1E2W */
331             mmu_idx = hcr_el2 & HCR_E2H ? ARMMMUIdx_E20_2 : ARMMMUIdx_E2;
332             break;
333         case 6: /* AT S1E3R, AT S1E3W */
334             mmu_idx = ARMMMUIdx_E3;
335             for_el3 = true;
336             break;
337         default:
338             g_assert_not_reached();
339         }
340         break;
341     case 2: /* AT S1E0R, AT S1E0W */
342         mmu_idx = regime_e20 ? ARMMMUIdx_E20_0 : ARMMMUIdx_Stage1_E0;
343         break;
344     case 4: /* AT S12E1R, AT S12E1W */
345         mmu_idx = regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_E10_1;
346         break;
347     case 6: /* AT S12E0R, AT S12E0W */
348         mmu_idx = regime_e20 ? ARMMMUIdx_E20_0 : ARMMMUIdx_E10_0;
349         break;
350     default:
351         g_assert_not_reached();
352     }
353 
354     ss = for_el3 ? arm_security_space(env) : arm_security_space_below_el3(env);
355     env->cp15.par_el[1] = do_ats_write(env, value, access_perm, mmu_idx, ss);
356 }
357 
358 static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri,
359                                  bool isread)
360 {
361     if (ri->opc2 & 4) {
362         /*
363          * The ATS12NSO* operations must trap to EL3 or EL2 if executed in
364          * Secure EL1 (which can only happen if EL3 is AArch64).
365          * They are simply UNDEF if executed from NS EL1.
366          * They function normally from EL2 or EL3.
367          */
368         if (arm_current_el(env) == 1) {
369             if (arm_is_secure_below_el3(env)) {
370                 if (env->cp15.scr_el3 & SCR_EEL2) {
371                     return CP_ACCESS_TRAP_EL2;
372                 }
373                 return CP_ACCESS_TRAP_EL3;
374             }
375             return CP_ACCESS_UNDEFINED;
376         }
377     }
378     return CP_ACCESS_OK;
379 }
380 
381 static const ARMCPRegInfo vapa_ats_reginfo[] = {
382     /* This underdecoding is safe because the reginfo is NO_RAW. */
383     { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = CP_ANY,
384       .access = PL1_W, .accessfn = ats_access,
385       .writefn = ats_write, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC },
386 };
387 
388 static const ARMCPRegInfo v8_ats_reginfo[] = {
389     /* 64 bit address translation operations */
390     { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64,
391       .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 0,
392       .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
393       .fgt = FGT_ATS1E1R,
394       .accessfn = at_s1e01_access, .writefn = ats_write64 },
395     { .name = "AT_S1E1W", .state = ARM_CP_STATE_AA64,
396       .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 1,
397       .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
398       .fgt = FGT_ATS1E1W,
399       .accessfn = at_s1e01_access, .writefn = ats_write64 },
400     { .name = "AT_S1E0R", .state = ARM_CP_STATE_AA64,
401       .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 2,
402       .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
403       .fgt = FGT_ATS1E0R,
404       .accessfn = at_s1e01_access, .writefn = ats_write64 },
405     { .name = "AT_S1E0W", .state = ARM_CP_STATE_AA64,
406       .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 3,
407       .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
408       .fgt = FGT_ATS1E0W,
409       .accessfn = at_s1e01_access, .writefn = ats_write64 },
410     { .name = "AT_S12E1R", .state = ARM_CP_STATE_AA64,
411       .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 4,
412       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
413       .accessfn = at_e012_access, .writefn = ats_write64 },
414     { .name = "AT_S12E1W", .state = ARM_CP_STATE_AA64,
415       .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 5,
416       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
417       .accessfn = at_e012_access, .writefn = ats_write64 },
418     { .name = "AT_S12E0R", .state = ARM_CP_STATE_AA64,
419       .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 6,
420       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
421       .accessfn = at_e012_access, .writefn = ats_write64 },
422     { .name = "AT_S12E0W", .state = ARM_CP_STATE_AA64,
423       .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 7,
424       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
425       .accessfn = at_e012_access, .writefn = ats_write64 },
426     /* AT S1E2* are elsewhere as they UNDEF from EL3 if EL2 is not present */
427     { .name = "AT_S1E3R", .state = ARM_CP_STATE_AA64,
428       .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 0,
429       .access = PL3_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
430       .writefn = ats_write64 },
431     { .name = "AT_S1E3W", .state = ARM_CP_STATE_AA64,
432       .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 1,
433       .access = PL3_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
434       .writefn = ats_write64 },
435 };
436 
437 static const ARMCPRegInfo el2_ats_reginfo[] = {
438     /*
439      * Unlike the other EL2-related AT operations, these must
440      * UNDEF from EL3 if EL2 is not implemented, which is why we
441      * define them here rather than with the rest of the AT ops.
442      */
443     { .name = "AT_S1E2R", .state = ARM_CP_STATE_AA64,
444       .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 0,
445       .access = PL2_W, .accessfn = at_s1e2_access,
446       .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC | ARM_CP_EL3_NO_EL2_UNDEF,
447       .writefn = ats_write64 },
448     { .name = "AT_S1E2W", .state = ARM_CP_STATE_AA64,
449       .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 1,
450       .access = PL2_W, .accessfn = at_s1e2_access,
451       .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC | ARM_CP_EL3_NO_EL2_UNDEF,
452       .writefn = ats_write64 },
453     /*
454      * The AArch32 ATS1H* operations are CONSTRAINED UNPREDICTABLE
455      * if EL2 is not implemented; we choose to UNDEF. Behaviour at EL3
456      * with SCR.NS == 0 outside Monitor mode is UNPREDICTABLE; we choose
457      * to behave as if SCR.NS was 1.
458      */
459     { .name = "ATS1HR", .cp = 15, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 0,
460       .access = PL2_W,
461       .writefn = ats1h_write, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC },
462     { .name = "ATS1HW", .cp = 15, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 1,
463       .access = PL2_W,
464       .writefn = ats1h_write, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC },
465 };
466 
467 static const ARMCPRegInfo ats1e1_reginfo[] = {
468     { .name = "AT_S1E1RP", .state = ARM_CP_STATE_AA64,
469       .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
470       .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
471       .fgt = FGT_ATS1E1RP,
472       .accessfn = at_s1e01_access, .writefn = ats_write64 },
473     { .name = "AT_S1E1WP", .state = ARM_CP_STATE_AA64,
474       .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
475       .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
476       .fgt = FGT_ATS1E1WP,
477       .accessfn = at_s1e01_access, .writefn = ats_write64 },
478 };
479 
480 static const ARMCPRegInfo ats1cp_reginfo[] = {
481     { .name = "ATS1CPRP",
482       .cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
483       .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
484       .writefn = ats_write },
485     { .name = "ATS1CPWP",
486       .cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
487       .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
488       .writefn = ats_write },
489 };
490 
491 static void ats_s1e1a(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
492 {
493     uint64_t hcr_el2 = arm_hcr_el2_eff(env);
494     bool regime_e20 = (hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE);
495     ARMMMUIdx mmu_idx = regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_Stage1_E1;
496     ARMSecuritySpace ss = arm_security_space_below_el3(env);
497 
498     env->cp15.par_el[1] = do_ats_write(env, value, 0, mmu_idx, ss);
499 }
500 
501 static void ats_s1e2a(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
502 {
503     uint64_t hcr_el2 = arm_hcr_el2_eff(env);
504     ARMMMUIdx mmu_idx = hcr_el2 & HCR_E2H ? ARMMMUIdx_E20_2 : ARMMMUIdx_E2;
505     ARMSecuritySpace ss = arm_security_space_below_el3(env);
506 
507     env->cp15.par_el[1] = do_ats_write(env, value, 0, mmu_idx, ss);
508 }
509 
510 static void ats_s1e3a(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
511 {
512     env->cp15.par_el[1] = do_ats_write(env, value, 0, ARMMMUIdx_E3,
513                                        arm_security_space(env));
514 }
515 
516 static const ARMCPRegInfo ats1a_reginfo[] = {
517     { .name = "AT_S1E1A", .state = ARM_CP_STATE_AA64,
518       .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 2,
519       .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
520       .fgt = FGT_ATS1E1A,
521       .accessfn = at_s1e01_access, .writefn = ats_s1e1a },
522     { .name = "AT_S1E2A", .state = ARM_CP_STATE_AA64,
523       .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 9, .opc2 = 2,
524       .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
525       .accessfn = at_s1e2_access, .writefn = ats_s1e2a },
526     { .name = "AT_S1E3A", .state = ARM_CP_STATE_AA64,
527       .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 9, .opc2 = 2,
528       .access = PL3_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
529       .writefn = ats_s1e3a },
530 };
531 
532 void define_at_insn_regs(ARMCPU *cpu)
533 {
534     CPUARMState *env = &cpu->env;
535 
536     if (arm_feature(env, ARM_FEATURE_VAPA)) {
537         define_arm_cp_regs(cpu, vapa_ats_reginfo);
538     }
539     if (arm_feature(env, ARM_FEATURE_V8)) {
540         define_arm_cp_regs(cpu, v8_ats_reginfo);
541     }
542     if (arm_feature(env, ARM_FEATURE_EL2)
543         || (arm_feature(env, ARM_FEATURE_EL3)
544             && arm_feature(env, ARM_FEATURE_V8))) {
545         define_arm_cp_regs(cpu, el2_ats_reginfo);
546     }
547     if (cpu_isar_feature(aa64_ats1e1, cpu)) {
548         define_arm_cp_regs(cpu, ats1e1_reginfo);
549     }
550     if (cpu_isar_feature(aa32_ats1e1, cpu)) {
551         define_arm_cp_regs(cpu, ats1cp_reginfo);
552     }
553     if (cpu_isar_feature(aa64_ats1a, cpu)) {
554         define_arm_cp_regs(cpu, ats1a_reginfo);
555     }
556 }
557