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 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 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 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 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 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 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 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 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 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 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