On 15.02.2016 20:22, Peter Maydell wrote: > Mode switches from Hyp to any other mode via the CPS and MRS > instructions are illegal mode switches (though obviously switching > via exception return is valid). Add this check to bad_mode_switch(). > > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org>
Reviewed-by: Sergey Fedorov <serge.f...@gmail.com> > --- > target-arm/helper.c | 12 ++++++++++-- > 1 file changed, 10 insertions(+), 2 deletions(-) > > diff --git a/target-arm/helper.c b/target-arm/helper.c > index 69e93a2..e1af9d5 100644 > --- a/target-arm/helper.c > +++ b/target-arm/helper.c > @@ -5166,12 +5166,20 @@ void arm_cp_reset_ignore(CPUARMState *env, const > ARMCPRegInfo *opaque) > /* Helper coprocessor reset function for do-nothing-on-reset registers */ > } > > -static int bad_mode_switch(CPUARMState *env, int mode) > +static int bad_mode_switch(CPUARMState *env, int mode, CPSRWriteType > write_type) > { > /* Return true if it is not valid for us to switch to > * this CPU mode (ie all the UNPREDICTABLE cases in > * the ARM ARM CPSRWriteByInstr pseudocode). > */ > + > + /* Changes to or from Hyp via MSR and CPS are illegal. */ > + if (write_type == CPSRWriteByInstr && > + ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_HYP || > + mode == ARM_CPU_MODE_HYP)) { > + return 1; > + } > + > switch (mode) { > case ARM_CPU_MODE_USR: > case ARM_CPU_MODE_SYS: > @@ -5290,7 +5298,7 @@ void cpsr_write(CPUARMState *env, uint32_t val, > uint32_t mask, > if (write_type != CPSRWriteRaw && > (env->uncached_cpsr & CPSR_M) != CPSR_USER && > ((env->uncached_cpsr ^ val) & mask & CPSR_M)) { > - if (bad_mode_switch(env, val & CPSR_M)) { > + if (bad_mode_switch(env, val & CPSR_M, write_type)) { > /* Attempt to switch to an invalid mode: this is UNPREDICTABLE in > * v7, and has defined behaviour in v8: > * + leave CPSR.M untouched