From patchwork Tue Jun 24 04:34:23 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 363303 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id A0CE11400B8 for ; Tue, 24 Jun 2014 14:34:54 +1000 (EST) Received: from localhost ([::1]:57428 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzIRY-00026N-Tp for incoming@patchwork.ozlabs.org; Tue, 24 Jun 2014 00:34:52 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44598) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzIRD-0001nr-RU for qemu-devel@nongnu.org; Tue, 24 Jun 2014 00:34:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WzIR7-0005GR-Li for qemu-devel@nongnu.org; Tue, 24 Jun 2014 00:34:31 -0400 Received: from zeniv.linux.org.uk ([195.92.253.2]:39524) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzIR7-0005Fr-Cm for qemu-devel@nongnu.org; Tue, 24 Jun 2014 00:34:25 -0400 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.76 #1 (Red Hat Linux)) id 1WzIR5-0001ar-RQ; Tue, 24 Jun 2014 04:34:23 +0000 Date: Tue, 24 Jun 2014 05:34:23 +0100 From: Al Viro To: Richard Henderson Message-ID: <20140624043423.GX18016@ZenIV.linux.org.uk> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.92.253.2 Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [RFC] alpha qemu arithmetic exceptions 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 First of all, kudos - with current qemu tree qemu-alpha-system is working pretty well - debian install and a *lot* of builds work just fine. As in, getting from lenny to pretty complete squeeze toolchain, including gcj, openjdk6 and a lot of crap needed to satisfy build-deps of those, plus all priority:required and most of priority:important ones. It's a _lot_ of beating and the damn thing survives - the problems had been with debian packages themselves (fstatat() bug in lenny libc, epically buggered build-deps in gcc-defaults, etc.). As it is, one core of 6-way 3.3GHz phenom II is quite capable of running a home-grown autobuilder. Feels like ~250-300MHz alpha with a very fast disk... Remaining problems, AFAICS, are around floating point traps. I've found one in glibc testsuite (math/tests-misc.c; overflow in ADDS/SU ends up with wrong results from fetestexcept() - only FE_OVERFLOW is set, while the sucker expects FE_INEXACT as well and actual hardware sets both) and another in gcc one (with -funsafe-math-optimizations CVTST/S on denorms triggers SIGFPE/FPE_FLTINV). The libc one is a bug in gen_fp_exc_raise_ignore() - the difference between ADDS/SU and ADDS/SUI is only in trapping, not storing results in FPCR.INE and friends. Both will have the same effect on those and if (ignore) { tcg_gen_andi_i32(exc, exc, ~ignore); } in gen_fp_exc_raise_ignore() leads to exc & ignore not reaching the update of env->fpcr_exc_status in helper_fp_exc_raise_s(). See 4.7.8: [quote] In addition, the FPCR gives a summary of each exception type for the exception conditions detected by all IEEE floating-point operates thus far, as well as an overall summary bit that indicates whether any of these exception conditions has been detected. The indiividual exception bits match exactly in purpose and order the exception bits found in the exception summary quadword that is pushed for arithmetic traps. However, for each instruction, these exception bits arse set independent of the trapping mode specified for the instruction. Therefore, even though trapping may be disabled for a certain exceptional condition, the fact that the exceptional condition was encountered by an instruction is still recorded in the FPCR. [end quote] And yes, on actual hardware both ADDS/SU and ADDS/SUI set FPCR.INE the same way - verified by direct experiment. While we are at it, I'm not quite sure what plain ADDS will leave in FPCR.INE if it traps on overflow. It's probably entirely academical, but it might be worth checking if ELF ABI for Alpha has anything to say about the state seen by fetestexcept() in SIGFPE handler... Not sure what's the decent way to fix that - we could, of course, follow that tcg_gen_ld8u_i32(exc, cpu_env, offsetof(CPUAlphaState, fp_status.float_exception_flags)); with generating code that would do |= into ->fpcr_exc_status, but I don't know if we'd blow the footprint to hell by doing so. Alternatively, we could do that in helpers called before we start raising exceptions, and I really wonder what happens with plain CVTQS - do we get FPCR.INE set there anyway? If so, we really have to do it at least in that helper... Comments? The gcc one comes from the fact that we never set EXC_M_SWC, whether we come from helper_fp_exc_raise() or from helper_fp_exc_raise_s(), so kernel-side do_entArith() skips if (summary & 1) { /* Software-completion summary bit is set, so try to emulate the instruction. If the processor supports precise exceptions, we don't have to search. */ if (!amask(AMASK_PRECISE_TRAP)) si_code = alpha_fp_emul(regs->pc - 4); else si_code = alpha_fp_emul_imprecise(regs, write_mask); if (si_code == 0) return; } and buggers off to raise SIGFPE. That's easy to fix, but... we also get trap PC pointing to offending instruction, not the next one after it, as 4.7.7.3 would require and as the kernel expects. I'm not sure what to do with trap PC - bumping env->pc by 4 after cpu_restore_state() in dynamic_excp() seems to work, but I'm not at all sure it's correct; I don't know qemu well enough to tell. Anyway, delta that seems to fix the gcc one (gcc.dg/pr28796-2.c from gcc-4.3 and later) follows. Again, I'm not at all sure if handling of env->pc in there is safe from qemu POV and I'd like like to get comments on that from somebody more familiar with qemu guts. diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c index d2d776c..a24535b 100644 --- a/target-alpha/fpu_helper.c +++ b/target-alpha/fpu_helper.c @@ -45,10 +45,10 @@ uint32_t helper_fp_exc_get(CPUAlphaState *env) } static inline void inline_fp_exc_raise(CPUAlphaState *env, uintptr_t retaddr, - uint32_t exc, uint32_t regno) + uint32_t exc, uint32_t regno, uint32_t sw) { if (exc) { - uint32_t hw_exc = 0; + uint32_t hw_exc = sw; if (exc & float_flag_invalid) { hw_exc |= EXC_M_INV; @@ -75,7 +75,7 @@ static inline void inline_fp_exc_raise(CPUAlphaState *env, uintptr_t retaddr, doesn't apply. */ void helper_fp_exc_raise(CPUAlphaState *env, uint32_t exc, uint32_t regno) { - inline_fp_exc_raise(env, GETPC(), exc, regno); + inline_fp_exc_raise(env, GETPC(), exc, regno, 0); } /* Raise exceptions for ieee fp insns with software completion. */ @@ -84,7 +84,7 @@ void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t exc, uint32_t regno) if (exc) { env->fpcr_exc_status |= exc; exc &= ~env->fpcr_exc_mask; - inline_fp_exc_raise(env, GETPC(), exc, regno); + inline_fp_exc_raise(env, GETPC(), exc, regno, EXC_M_SWC); } } diff --git a/target-alpha/helper.c b/target-alpha/helper.c index 7c053a3..538c6b2 100644 --- a/target-alpha/helper.c +++ b/target-alpha/helper.c @@ -527,6 +527,7 @@ void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr, env->error_code = error; if (retaddr) { cpu_restore_state(cs, retaddr); + env->pc += 4; } cpu_loop_exit(cs); }