diff --git a/qemu/target-arm/helper.c b/qemu/target-arm/helper.c index bc840500..eb4c937c 100644 --- a/qemu/target-arm/helper.c +++ b/qemu/target-arm/helper.c @@ -1592,6 +1592,14 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) A32_BANKED_CURRENT_REG_SET(env, par, par64); } +static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri) +{ + if (arm_current_el(env) == 3 && !(env->cp15.scr_el3 & SCR_NS)) { + return CP_ACCESS_TRAP; + } + return CP_ACCESS_OK; +} + static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -1619,10 +1627,10 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0; break; case 4: /* AT S12E1R, AT S12E1W */ - mmu_idx = ARMMMUIdx_S12NSE1; + mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S12NSE1; break; case 6: /* AT S12E0R, AT S12E0W */ - mmu_idx = ARMMMUIdx_S12NSE0; + mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S12NSE0; break; default: g_assert_not_reached(); @@ -2394,6 +2402,25 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { { "AT_S1E0W", 0,7,8, 1,0,3, ARM_CP_STATE_AA64, ARM_CP_NO_RAW, PL1_W, 0, NULL, 0, 0, {0, 0}, NULL, NULL, ats_write64 }, + { "AT_S12E1R", 0,7,8, 1,0,4, ARM_CP_STATE_AA64, ARM_CP_NO_RAW, + PL2_W, 0, NULL, 0, 0, {0, 0}, + NULL, NULL, ats_write64 }, + { "AT_S12E1W", 0,7,8, 1,0,5, ARM_CP_STATE_AA64, ARM_CP_NO_RAW, + PL2_W, 0, NULL, 0, 0, {0, 0}, + NULL, NULL, ats_write64 }, + { "AT_S12E0R", 0,7,8, 1,0,6, ARM_CP_STATE_AA64, ARM_CP_NO_RAW, + PL2_W, 0, NULL, 0, 0, {0, 0}, + NULL, NULL, ats_write64 }, + { "AT_S12E0W", 0,7,8, 1,0,7, ARM_CP_STATE_AA64, ARM_CP_NO_RAW, + PL2_W, 0, NULL, 0, 0, {0, 0}, + NULL, NULL, ats_write64 }, + /* AT S1E2* are elsewhere as they UNDEF from EL3 if EL2 is not present */ + { "AT_S1E3R", 0,7,8, 1,6,0, ARM_CP_STATE_AA64, ARM_CP_NO_RAW, + PL3_W, 0, NULL, 0, 0, {0, 0}, + NULL, NULL, ats_write64 }, + { "AT_S1E3W", 0,7,8, 1,6,1, ARM_CP_STATE_AA64, ARM_CP_NO_RAW, + PL3_W, 0, NULL, 0, 0, {0, 0}, + NULL, NULL, ats_write64 }, #endif /* TLB invalidate last level of translation table walk */ { "TLBIMVALIS", 15,8,3, 0,0,5, 0, @@ -2593,6 +2620,16 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { PL2_W, 0, NULL, 0, 0, {0, 0}, NULL, NULL, tlbi_aa64_vaa_write }, #ifndef CONFIG_USER_ONLY + /* Unlike the other EL2-related AT operations, these must + * UNDEF from EL3 if EL2 is not implemented, which is why we + * define them here rather than with the rest of the AT ops. + */ + { "AT_S1E2R", 0,7,8, 1,4,0, ARM_CP_STATE_AA64, ARM_CP_NO_RAW, + PL2_W, 0, NULL, 0, 0, {0, 0}, + at_s1e2_access, NULL, ats_write64 }, + { "AT_S1E2W", 0,7,8, 1,4,1, ARM_CP_STATE_AA64, ARM_CP_NO_RAW, + PL2_W, 0, NULL, 0, 0, {0, 0}, + at_s1e2_access, NULL, ats_write64 }, /* ARMv7 requires bit 0 and 1 to reset to 1. ARMv8 defines the * reset values as IMPDEF. We choose to reset to 3 to comply with * both ARMv7 and ARMv8.