Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/powerpc Add support for PPC FP emulation to BookE.



details:   https://anonhg.NetBSD.org/src/rev/271cc755eda6
branches:  trunk
changeset: 780423:271cc755eda6
user:      matt <matt%NetBSD.org@localhost>
date:      Mon Jul 23 04:13:06 2012 +0000

description:
Add support for PPC FP emulation to BookE.
Pass a ksiginfo_t to fpu_emulation so it can give more detailed
info on signals.

diffstat:

 sys/arch/powerpc/booke/trap.c     |  33 +++++++++++++++-
 sys/arch/powerpc/conf/files.booke |   4 +-
 sys/arch/powerpc/fpu/fpu_emu.c    |  78 ++++++++++++++++++++++++--------------
 sys/arch/powerpc/fpu/fpu_emu.h    |   3 +-
 sys/arch/powerpc/fpu/fpu_extern.h |  12 +++++-
 sys/arch/powerpc/ibm4xx/trap.c    |  16 +++++---
 6 files changed, 104 insertions(+), 42 deletions(-)

diffs (truncated from 360 to 300 lines):

diff -r e3b0f9151590 -r 271cc755eda6 sys/arch/powerpc/booke/trap.c
--- a/sys/arch/powerpc/booke/trap.c     Mon Jul 23 03:32:30 2012 +0000
+++ b/sys/arch/powerpc/booke/trap.c     Mon Jul 23 04:13:06 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: trap.c,v 1.17 2012/07/09 17:45:22 matt Exp $   */
+/*     $NetBSD: trap.c,v 1.18 2012/07/23 04:13:06 matt Exp $   */
 /*-
  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -38,7 +38,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.17 2012/07/09 17:45:22 matt Exp $");
+__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.18 2012/07/23 04:13:06 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -61,6 +61,8 @@
 #include <powerpc/booke/spr.h>
 #include <powerpc/booke/cpuvar.h>
 
+#include <powerpc/fpu/fpu_extern.h>
+
 #include <powerpc/db_machdep.h>
 #include <ddb/db_interface.h>
 
@@ -426,6 +428,18 @@
                return true;
        }
 
+       if (OPC_MFSPR_P(opcode, SPR_PIR)) {
+               __asm ("mfpir %0" : "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)]));
+               return true;
+       }
+
+       if (OPC_MFSPR_P(opcode, SPR_SVR)) {
+               __asm ("mfspr %0,%1"
+                   :   "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)])
+                   :   "n"(SPR_SVR));
+               return true;
+       }
+
        /*
         * If we bothered to emulate FP, we would try to do so here.
         */
@@ -465,6 +479,21 @@
                }
        }
 
+       if (tf->tf_esr & ESR_PIL) {
+               struct pcb * const pcb = lwp_getpcb(curlwp);
+               if (__predict_false(!(curlwp->l_md.md_flags & MDLWP_USEDFPU))) {
+                       memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu));
+                       curlwp->l_md.md_flags |= MDLWP_USEDFPU;
+               }
+               if (fpu_emulate(tf, &pcb->pcb_fpu, ksi)) {
+                       if (ksi->ksi_signo == 0) {
+                               ci->ci_ev_fpu.ev_count++;
+                               return 0;
+                       }
+                       return EFAULT;
+               }
+       }
+
        KSI_INIT_TRAP(ksi);
        ksi->ksi_signo = SIGILL;
        ksi->ksi_trap = EXC_PGM;
diff -r e3b0f9151590 -r 271cc755eda6 sys/arch/powerpc/conf/files.booke
--- a/sys/arch/powerpc/conf/files.booke Mon Jul 23 03:32:30 2012 +0000
+++ b/sys/arch/powerpc/conf/files.booke Mon Jul 23 04:13:06 2012 +0000
@@ -1,8 +1,8 @@
-#      $NetBSD: files.booke,v 1.7 2012/07/22 23:46:10 matt Exp $
+#      $NetBSD: files.booke,v 1.8 2012/07/23 04:13:06 matt Exp $
 #
 # PPC BookE specific configuration info
 
-#include "arch/powerpc/fpu/files.fpu"
+include "arch/powerpc/fpu/files.fpu"
 
 # Board Properties
 file   arch/powerpc/booke/board_prop.c
diff -r e3b0f9151590 -r 271cc755eda6 sys/arch/powerpc/fpu/fpu_emu.c
--- a/sys/arch/powerpc/fpu/fpu_emu.c    Mon Jul 23 03:32:30 2012 +0000
+++ b/sys/arch/powerpc/fpu/fpu_emu.c    Mon Jul 23 04:13:06 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu_emu.c,v 1.15 2011/01/18 01:02:53 matt Exp $ */
+/*     $NetBSD: fpu_emu.c,v 1.16 2012/07/23 04:13:06 matt Exp $ */
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -76,21 +76,23 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.15 2011/01/18 01:02:53 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.16 2012/07/23 04:13:06 matt Exp $");
 
 #include "opt_ddb.h"
 
 #include <sys/param.h>
 #include <sys/proc.h>
 #include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/siginfo.h>
 #include <sys/systm.h>
 #include <sys/syslog.h>
-#include <sys/signalvar.h>
-#include <sys/device.h>                /* for evcnt */
+#include <sys/evcnt.h>
 
 #include <powerpc/instr.h>
 #include <machine/reg.h>
 #include <machine/fpu.h>
+#include <machine/trap.h>
 
 #include <powerpc/fpu/fpu_emu.h>
 #include <powerpc/fpu/fpu_extern.h>
@@ -182,13 +184,15 @@
  * Return zero for success, else signal number.
  * (Typically: zero, SIGFPE, SIGILL, SIGSEGV)
  */
-int
-fpu_emulate(struct trapframe *tf, struct fpreg *fpf)
+bool
+fpu_emulate(struct trapframe *tf, struct fpreg *fpf, ksiginfo_t *ksi)
 {
-       static union instr insn;
-       static struct fpemu fe;
-       static int lastill = 0;
-       int sig;
+       union instr insn;
+       struct fpemu fe;
+
+       KSI_INIT_TRAP(ksi);
+       ksi->ksi_signo = 0;
+       ksi->ksi_addr = (void *)tf->tf_srr0;
 
        /* initialize insn.is_datasize to tell it is *not* initialized */
        fe.fe_fpstate = fpf;
@@ -200,36 +204,46 @@
 #ifdef DEBUG
                printf("fpu_emulate: fault reading opcode\n");
 #endif
-               return SIGSEGV;
+               ksi->ksi_signo = SIGSEGV;
+               ksi->ksi_trap = EXC_ISI;
+               ksi->ksi_code = SEGV_MAPERR;
+               ksi->ksi_addr = (void *)tf->tf_srr0;
+               return true;
        }
 
        DPRINTF(FPE_EX, ("fpu_emulate: emulating insn %x at %p\n",
            insn.i_int, (void *)tf->tf_srr0));
 
-
        if ((insn.i_any.i_opcd == OPC_TWI) ||
            ((insn.i_any.i_opcd == OPC_integer_31) &&
            (insn.i_x.i_xo == OPC31_TW))) {
                /* Check for the two trap insns. */
                DPRINTF(FPE_EX, ("fpu_emulate: SIGTRAP\n"));
-               return (SIGTRAP);
+               ksi->ksi_signo = SIGTRAP;
+               ksi->ksi_trap = EXC_PGM;
+               ksi->ksi_code = TRAP_TRACE;
+               ksi->ksi_addr = (void *)tf->tf_srr0;
+               return true;
        }
-       sig = 0;
        switch (fpu_execute(tf, &fe, &insn)) {
        case 0:
                DPRINTF(FPE_EX, ("fpu_emulate: success\n"));
                tf->tf_srr0 += 4;
-               break;
+               return true;
 
        case FPE:
                DPRINTF(FPE_EX, ("fpu_emulate: SIGFPE\n"));
-               sig = SIGFPE;
-               break;
+               ksi->ksi_signo = SIGFPE;
+               ksi->ksi_trap = EXC_PGM;
+               return true;
 
        case FAULT:
                DPRINTF(FPE_EX, ("fpu_emulate: SIGSEGV\n"));
-               sig = SIGSEGV;
-               break;
+               ksi->ksi_signo = SIGSEGV;
+               ksi->ksi_trap = EXC_DSI;
+               ksi->ksi_code = SEGV_MAPERR;
+               ksi->ksi_addr = (void *)fe.fe_addr;
+               return true;
 
        case NOTFPU:
        default:
@@ -241,21 +255,19 @@
                        opc_disasm((vaddr_t)(tf->tf_srr0), insn.i_int);
                }
 #endif
+#if defined(PPC_IBM4XX) && defined(DEBUG)
                /*
                * XXXX retry an illegal insn once due to cache issues.
                */
+               static int lastill = 0;
                if (lastill == tf->tf_srr0) {
-                       sig = SIGILL;
-#ifdef DEBUG
                        if (fpe_debug & FPE_EX)
                                Debugger();
-#endif
                }
                lastill = tf->tf_srr0;
-               break;
+#endif /* PPC_IBM4XX && DEBUG */
+               return false;
        }
-
-       return (sig);
 }
 
 /*
@@ -337,8 +349,10 @@
                                DPRINTF(FPE_INSN,
                                        ("fpu_execute: Store INT %x at %p\n",
                                                a[1], (void *)addr));
-                               if (copyout(&a[1], (void *)addr, sizeof(int)))
+                               if (copyout(&a[1], (void *)addr, sizeof(int))) {
+                                       fe->fe_addr = addr;
                                        return (FAULT);
+                               }
                                return (0);
                        }
 
@@ -392,22 +406,28 @@
                                                (void *)addr));
                                fpu_explode(fe, fp = &fe->fe_f1, FTYPE_DBL, rt);
                                fpu_implode(fe, fp, type, (void *)&buf);
-                               if (copyout(&buf, (void *)addr, size))
+                               if (copyout(&buf, (void *)addr, size)) {
+                                       fe->fe_addr = addr;
                                        return (FAULT);
+                               }
                        } else {
                                DPRINTF(FPE_INSN, 
                                        ("fpu_execute: Store DBL at %p\n",
                                                (void *)addr));
-                               if (copyout(&fs->fpreg[rt], (void *)addr, size))
+                               if (copyout(&fs->fpreg[rt], (void *)addr, size)) {
+                                       fe->fe_addr = addr;
                                        return (FAULT);
+                               }
                        }
                } else {
                        /* Load */
                        FPU_EMU_EVCNT_INCR(fpload);
                        DPRINTF(FPE_INSN, ("fpu_execute: Load from %p\n",
                                (void *)addr));
-                       if (copyin((const void *)addr, &fs->fpreg[rt], size))
+                       if (copyin((const void *)addr, &fs->fpreg[rt], size)) {
+                               fe->fe_addr = addr;
                                return (FAULT);
+                       }
                        if (type != FTYPE_DBL) {
                                fpu_explode(fe, fp = &fe->fe_f1, type, rt);
                                fpu_implode(fe, fp, FTYPE_DBL, 
diff -r e3b0f9151590 -r 271cc755eda6 sys/arch/powerpc/fpu/fpu_emu.h
--- a/sys/arch/powerpc/fpu/fpu_emu.h    Mon Jul 23 03:32:30 2012 +0000
+++ b/sys/arch/powerpc/fpu/fpu_emu.h    Mon Jul 23 04:13:06 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu_emu.h,v 1.3 2005/12/11 12:18:42 christos Exp $ */
+/*     $NetBSD: fpu_emu.h,v 1.4 2012/07/23 04:13:06 matt Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -143,6 +143,7 @@
        struct  fpn fe_f1;              /* operand 1 */
        struct  fpn fe_f2;              /* operand 2, if required */
        struct  fpn fe_f3;              /* available storage for result */
+       vaddr_t fe_addr;                /* last address accessed */
 };
 
 /*
diff -r e3b0f9151590 -r 271cc755eda6 sys/arch/powerpc/fpu/fpu_extern.h
--- a/sys/arch/powerpc/fpu/fpu_extern.h Mon Jul 23 03:32:30 2012 +0000
+++ b/sys/arch/powerpc/fpu/fpu_extern.h Mon Jul 23 04:13:06 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu_extern.h,v 1.4 2008/04/28 20:23:32 martin Exp $    */
+/*     $NetBSD: fpu_extern.h,v 1.5 2012/07/23 04:13:06 matt Exp $      */
 
 /*-
  * Copyright (c) 1995 The NetBSD Foundation, Inc.
@@ -29,6 +29,12 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifndef _POWERPC_FPU_FPU_EXTERN_H_
+#define _POWERPC_FPU_FPU_EXTERN_H_
+
+#include <sys/signal.h>



Home | Main Index | Thread Index | Old Index