From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:44642) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RiqcD-0002OQ-6u for qemu-devel@nongnu.org; Thu, 05 Jan 2012 11:56:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Riqc8-0001Bb-W7 for qemu-devel@nongnu.org; Thu, 05 Jan 2012 11:56:33 -0500 Received: from mnementh.archaic.org.uk ([81.2.115.146]:44089) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Riqc8-0001BG-Mb for qemu-devel@nongnu.org; Thu, 05 Jan 2012 11:56:28 -0500 From: Peter Maydell Date: Thu, 5 Jan 2012 16:44:33 +0000 Message-Id: <1325781874-25327-3-git-send-email-peter.maydell@linaro.org> In-Reply-To: <1325781874-25327-1-git-send-email-peter.maydell@linaro.org> References: <1325781874-25327-1-git-send-email-peter.maydell@linaro.org> Subject: [Qemu-devel] [PATCH 2/3] target-arm: Ignore attempts to set invalid modes in CPSR List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Andrzej Zaborowski Cc: Anthony Liguori , Paul Brook , qemu-devel@nongnu.org Ignore attempts to set the CPSR mode field to an invalid value. This is UNPREDICTABLE, but we should not cpu_abort() for things a malicious guest (or a confused user on the gdbstub interface) can provoke. Signed-off-by: Peter Maydell --- target-arm/helper.c | 30 +++++++++++++++++++++++++++++- 1 files changed, 29 insertions(+), 1 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 5b994d5..261d547 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -463,6 +463,26 @@ void cpu_arm_close(CPUARMState *env) g_free(env); } +static int bad_mode_switch(CPUState *env, int mode) +{ + /* 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). + */ + switch (mode) { + case ARM_CPU_MODE_USR: + case ARM_CPU_MODE_SYS: + case ARM_CPU_MODE_SVC: + case ARM_CPU_MODE_ABT: + case ARM_CPU_MODE_UND: + case ARM_CPU_MODE_IRQ: + case ARM_CPU_MODE_FIQ: + return 0; + default: + return 1; + } +} + uint32_t cpsr_read(CPUARMState *env) { int ZF; @@ -499,7 +519,15 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) } if ((env->uncached_cpsr ^ val) & mask & CPSR_M) { - switch_mode(env, val & CPSR_M); + if (bad_mode_switch(env, val & CPSR_M)) { + /* Attempt to switch to an invalid mode: this is UNPREDICTABLE. + * We choose to ignore the attempt and leave the CPSR M field + * untouched. + */ + mask &= ~CPSR_M; + } else { + switch_mode(env, val & CPSR_M); + } } mask &= ~CACHED_CPSR_BITS; env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask); -- 1.7.1