ARM v7MP deprecates use of SWP instruction and only defines it if OS explicitly requests it via setting SCTLR.SW bit. Such a request is expected to occur only once during OS init, thus only static checking for this bit and flush of all translations is done on SCTLR change.
Signed-off-by: Alexey Starikovskiy <[email protected]> --- target-arm/helper.c | 7 +++++-- target-arm/translate.c | 10 ++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 28f127b..2451eba 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1486,11 +1486,14 @@ void HELPER(set_cp15)(CPUARMState *env, uint32_t insn, uint32_t val) op2 = 0; switch (op2) { case 0: - if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0) + if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0) { env->cp15.c1_sys = val; /* ??? Lots of these bits are not implemented. */ /* This may enable/disable the MMU, so do a TLB flush. */ - tlb_flush(env, 1); + tlb_flush(env, 1); + /* This may enable/disable SWP instruction, so do TB flush too */ + tb_flush(env); + } break; case 1: /* Auxiliary control register. */ if (arm_feature(env, ARM_FEATURE_XSCALE)) { diff --git a/target-arm/translate.c b/target-arm/translate.c index 7a3c7d6..4f17fd0 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -7415,6 +7415,16 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) } tcg_temp_free(addr); } else { +/* User mode allows superset of all ARM instructions, thus disable check */ +#ifndef CONFIG_USER_ONLY + if (arm_feature(env, ARM_FEATURE_V7MP) && + !(env->cp15.c1_sys & (1 << 10))) { + /* Check if SCTLR.SW is set. Any change to SCTLR + * invalidates all translations, so we are safe. + */ + goto illegal_op; + } +#endif /* SWP instruction */ rm = (insn) & 0xf;
