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