From patchwork Thu Jan 10 22:50:22 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Meador Inge X-Patchwork-Id: 211162 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id CC5A22C00F4 for ; Fri, 11 Jan 2013 09:50:38 +1100 (EST) Received: from localhost ([::1]:52684 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TtQxI-0001gf-QU for incoming@patchwork.ozlabs.org; Thu, 10 Jan 2013 17:50:36 -0500 Received: from eggs.gnu.org ([208.118.235.92]:54744) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TtQxA-0001gF-2d for qemu-devel@nongnu.org; Thu, 10 Jan 2013 17:50:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TtQx8-0000vB-O6 for qemu-devel@nongnu.org; Thu, 10 Jan 2013 17:50:28 -0500 Received: from relay1.mentorg.com ([192.94.38.131]:35896) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TtQx8-0000v0-Is for qemu-devel@nongnu.org; Thu, 10 Jan 2013 17:50:26 -0500 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1TtQx5-0003QS-Um from meador_inge@mentor.com ; Thu, 10 Jan 2013 14:50:23 -0800 Received: from SVR-ORW-FEM-04.mgc.mentorg.com ([147.34.97.41]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Thu, 10 Jan 2013 14:50:23 -0800 Received: from pepper.mgc.mentorg.com (147.34.91.1) by svr-orw-fem-04.mgc.mentorg.com (147.34.97.41) with Microsoft SMTP Server id 14.1.289.1; Thu, 10 Jan 2013 14:50:22 -0800 From: Meador Inge To: Date: Thu, 10 Jan 2013 16:50:22 -0600 Message-ID: <1357858222-12268-1-git-send-email-meadori@codesourcery.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-OriginalArrivalTime: 10 Jan 2013 22:50:23.0797 (UTC) FILETIME=[E0177E50:01CDEF84] X-detected-operating-system: by eggs.gnu.org: Windows NT kernel [generic] [fuzzy] X-Received-From: 192.94.38.131 Cc: aurelien@aurel32.net Subject: [Qemu-devel] [PATCH v2] MIPS: Translate breaks and traps into the appropriate signal X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org GCC and GAS are capable of generating traps or breaks to check for division by zero. Additionally, GAS is capable of generating traps or breaks to check for overflow on certain division and multiplication operations. The Linux kernel translates these traps and breaks into signals. This patch implements the corresponding feature in QEMU. Signed-off-by: Meador Inge --- Changes since v1: * Moved the BRK_* enumerations from target-mips/cpu.h to linux-user/main.c since they are only used in main.c * Fixed some style violations found by checkpatch.pl. * Removed a superfluous break. linux-user/main.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/linux-user/main.c b/linux-user/main.c index 9ade1bf..583940c 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2182,6 +2182,33 @@ static int do_store_exclusive(CPUMIPSState *env) return segv; } +/* Break codes */ +enum { + BRK_OVERFLOW = 6, + BRK_DIVZERO = 7 +}; + +static int do_break(CPUMIPSState *env, target_siginfo_t *info, + unsigned int code) +{ + int ret = -1; + + switch (code) { + case BRK_OVERFLOW: + case BRK_DIVZERO: + info->si_signo = TARGET_SIGFPE; + info->si_errno = 0; + info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; + queue_signal(env, info->si_signo, &*info); + ret = 0; + break; + default: + break; + } + + return ret; +} + void cpu_loop(CPUMIPSState *env) { target_siginfo_t info; @@ -2297,8 +2324,55 @@ done_syscall: info.si_code = TARGET_ILL_ILLOPC; queue_signal(env, info.si_signo, &info); break; + /* The code below was inspired by the MIPS Linux kernel trap + * handling code in arch/mips/kernel/traps.c. + */ + case EXCP_BREAK: + { + abi_ulong trap_instr; + unsigned int code; + + ret = get_user_ual(trap_instr, env->active_tc.PC); + if (ret != 0) { + goto error; + } + + /* As described in the original Linux kernel code, the + * below checks on 'code' are to work around an old + * assembly bug. + */ + code = ((trap_instr >> 6) & ((1 << 20) - 1)); + if (code >= (1 << 10)) { + code >>= 10; + } + + if (do_break(env, &info, code) != 0) { + goto error; + } + } + break; + case EXCP_TRAP: + { + abi_ulong trap_instr; + unsigned int code = 0; + + ret = get_user_ual(trap_instr, env->active_tc.PC); + if (ret != 0) { + goto error; + } + + /* The immediate versions don't provide a code. */ + if (!(trap_instr & 0xFC000000)) { + code = ((trap_instr >> 6) & ((1 << 10) - 1)); + } + + if (do_break(env, &info, code) != 0) { + goto error; + } + } + break; default: - // error: +error: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); cpu_dump_state(env, stderr, fprintf, 0);