diff mbox

[10/11] target-arm: Make mode switches from Hyp via CPS and MRS illegal

Message ID 1455556977-3644-11-git-send-email-peter.maydell@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Peter Maydell Feb. 15, 2016, 5:22 p.m. UTC
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.maydell@linaro.org>
---
 target-arm/helper.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

Comments

Sergey Fedorov Feb. 18, 2016, 5:44 p.m. UTC | #1
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.maydell@linaro.org>

Reviewed-by: Sergey Fedorov <serge.fdrv@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
diff mbox

Patch

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