From owner-svn-src-head@FreeBSD.ORG Sat Mar 29 14:35:36 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DB7859F1; Sat, 29 Mar 2014 14:35:36 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id BB60C8BD; Sat, 29 Mar 2014 14:35:36 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s2TEZaXM017642; Sat, 29 Mar 2014 14:35:36 GMT (envelope-from andrew@svn.freebsd.org) Received: (from andrew@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s2TEZaPR017640; Sat, 29 Mar 2014 14:35:36 GMT (envelope-from andrew@svn.freebsd.org) Message-Id: <201403291435.s2TEZaPR017640@svn.freebsd.org> From: Andrew Turner Date: Sat, 29 Mar 2014 14:35:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r263914 - in head/sys/arm: arm include X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 29 Mar 2014 14:35:36 -0000 Author: andrew Date: Sat Mar 29 14:35:36 2014 New Revision: 263914 URL: http://svnweb.freebsd.org/changeset/base/263914 Log: VFP fixes/cleanups for ARM11: * Save the required VFP registers on context switch. If the exception bit is set we need to save and restore the FPINST register, and if the fp2v bit is also set we need to save and restore FPINST2. * Move saving and restoring the floating point control registers to C. * Clear the fpexc exception and fp2v flags on a floating-point exception. * Signal a SIGFPE if the fpexc exception flag is set on an undefined instruction. This is how the ARM core signals to software there is a floating-point exception. Modified: head/sys/arm/arm/vfp.c head/sys/arm/include/fp.h Modified: head/sys/arm/arm/vfp.c ============================================================================== --- head/sys/arm/arm/vfp.c Sat Mar 29 14:17:04 2014 (r263913) +++ head/sys/arm/arm/vfp.c Sat Mar 29 14:35:36 2014 (r263914) @@ -149,6 +149,7 @@ vfp_bounce(u_int addr, u_int insn, struc { u_int cpu, fpexc; struct pcb *curpcb; + ksiginfo_t ksi; if ((code & FAULT_USER) == 0) panic("undefined floating point instruction in supervisor mode"); @@ -162,9 +163,27 @@ vfp_bounce(u_int addr, u_int insn, struc */ fpexc = fmrx(VFPEXC); if (fpexc & VFPEXC_EN) { + /* Clear any exceptions */ + fmxr(VFPEXC, fpexc & ~(VFPEXC_EX | VFPEXC_FP2V)); + /* kill the process - we do not handle emulation */ critical_exit(); - killproc(curthread->td_proc, "vfp emulation"); + + if (fpexc & VFPEXC_EX) { + /* We have an exception, signal a SIGFPE */ + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGFPE; + if (fpexc & VFPEXC_UFC) + ksi.ksi_code = FPE_FLTUND; + else if (fpexc & VFPEXC_OFC) + ksi.ksi_code = FPE_FLTOVF; + else if (fpexc & VFPEXC_IOC) + ksi.ksi_code = FPE_FLTINV; + ksi.ksi_addr = (void *)addr; + trapsignal(curthread, &ksi); + return 0; + } + return 1; } @@ -192,15 +211,24 @@ vfp_bounce(u_int addr, u_int insn, struc static void vfp_restore(struct vfp_state *vfpsave) { - u_int vfpscr = 0; + uint32_t fpexc; + + /* On VFPv2 we may need to restore FPINST and FPINST2 */ + fpexc = vfpsave->fpexec; + if (fpexc & VFPEXC_EX) { + fmxr(VFPINST, vfpsave->fpinst); + if (fpexc & VFPEXC_FP2V) + fmxr(VFPINST2, vfpsave->fpinst2); + } + fmxr(VFPSCR, vfpsave->fpscr); - __asm __volatile("ldc p10, c0, [%1], #128\n" /* d0-d15 */ - "cmp %2, #0\n" /* -D16 or -D32? */ - LDCLNE "p11, c0, [%1], #128\n" /* d16-d31 */ - "addeq %1, %1, #128\n" /* skip missing regs */ - "ldr %0, [%1]\n" /* set old vfpscr */ - "mcr p10, 7, %0, cr1, c0, 0\n" - : "=&r" (vfpscr) : "r" (vfpsave), "r" (is_d32) : "cc"); + __asm __volatile("ldc p10, c0, [%0], #128\n" /* d0-d15 */ + "cmp %1, #0\n" /* -D16 or -D32? */ + LDCLNE "p11, c0, [%0], #128\n" /* d16-d31 */ + "addeq %0, %0, #128\n" /* skip missing regs */ + : : "r" (vfpsave), "r" (is_d32) : "cc"); + + fmxr(VFPEXC, fpexc); } /* @@ -211,20 +239,30 @@ vfp_restore(struct vfp_state *vfpsave) void vfp_store(struct vfp_state *vfpsave, boolean_t disable_vfp) { - u_int tmp, vfpscr; + uint32_t fpexc; + + fpexc = fmrx(VFPEXC); /* Is the vfp enabled? */ + if (fpexc & VFPEXC_EN) { + vfpsave->fpexec = fpexc; + vfpsave->fpscr = fmrx(VFPSCR); + + /* On VFPv2 we may need to save FPINST and FPINST2 */ + if (fpexc & VFPEXC_EX) { + vfpsave->fpinst = fmrx(VFPINST); + if (fpexc & VFPEXC_FP2V) + vfpsave->fpinst2 = fmrx(VFPINST2); + fpexc &= ~VFPEXC_EX; + } - tmp = fmrx(VFPEXC); /* Is the vfp enabled? */ - if (tmp & VFPEXC_EN) { __asm __volatile( - "stc p11, c0, [%1], #128\n" /* d0-d15 */ - "cmp %2, #0\n" /* -D16 or -D32? */ - STCLNE "p11, c0, [%1], #128\n" /* d16-d31 */ - "addeq %1, %1, #128\n" /* skip missing regs */ - "mrc p10, 7, %0, cr1, c0, 0\n" /* fmxr(VFPSCR) */ - "str %0, [%1]\n" /* save vfpscr */ - : "=&r" (vfpscr) : "r" (vfpsave), "r" (is_d32) : "cc"); + "stc p11, c0, [%0], #128\n" /* d0-d15 */ + "cmp %1, #0\n" /* -D16 or -D32? */ + STCLNE "p11, c0, [%0], #128\n" /* d16-d31 */ + "addeq %0, %0, #128\n" /* skip missing regs */ + : : "r" (vfpsave), "r" (is_d32) : "cc"); + if (disable_vfp) - fmxr(VFPEXC , tmp & ~VFPEXC_EN); + fmxr(VFPEXC , fpexc & ~VFPEXC_EN); } } Modified: head/sys/arm/include/fp.h ============================================================================== --- head/sys/arm/include/fp.h Sat Mar 29 14:17:04 2014 (r263913) +++ head/sys/arm/include/fp.h Sat Mar 29 14:35:36 2014 (r263914) @@ -69,6 +69,9 @@ typedef struct fp_extended_precision fp_ struct vfp_state { u_int64_t reg[32]; u_int32_t fpscr; + u_int32_t fpexec; + u_int32_t fpinst; + u_int32_t fpinst2; }; /*