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