Module Name: src
Committed By: matt
Date: Mon Jul 23 04:13:06 UTC 2012
Modified Files:
src/sys/arch/powerpc/booke: trap.c
src/sys/arch/powerpc/conf: files.booke
src/sys/arch/powerpc/fpu: fpu_emu.c fpu_emu.h fpu_extern.h
src/sys/arch/powerpc/ibm4xx: trap.c
Log Message:
Add support for PPC FP emulation to BookE.
Pass a ksiginfo_t to fpu_emulation so it can give more detailed
info on signals.
To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.18 src/sys/arch/powerpc/booke/trap.c
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/powerpc/conf/files.booke
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/powerpc/fpu/fpu_emu.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/powerpc/fpu/fpu_emu.h
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/powerpc/fpu/fpu_extern.h
cvs rdiff -u -r1.64 -r1.65 src/sys/arch/powerpc/ibm4xx/trap.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/powerpc/booke/trap.c
diff -u src/sys/arch/powerpc/booke/trap.c:1.17 src/sys/arch/powerpc/booke/trap.c:1.18
--- src/sys/arch/powerpc/booke/trap.c:1.17 Mon Jul 9 17:45:22 2012
+++ src/sys/arch/powerpc/booke/trap.c Mon Jul 23 04:13:06 2012
@@ -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 @@ __KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.1
#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 @@ emulate_opcode(struct trapframe *tf, ksi
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 @@ pgm_exception(struct trapframe *tf, ksig
}
}
+ 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;
Index: src/sys/arch/powerpc/conf/files.booke
diff -u src/sys/arch/powerpc/conf/files.booke:1.7 src/sys/arch/powerpc/conf/files.booke:1.8
--- src/sys/arch/powerpc/conf/files.booke:1.7 Sun Jul 22 23:46:10 2012
+++ src/sys/arch/powerpc/conf/files.booke Mon Jul 23 04:13:06 2012
@@ -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
Index: src/sys/arch/powerpc/fpu/fpu_emu.c
diff -u src/sys/arch/powerpc/fpu/fpu_emu.c:1.15 src/sys/arch/powerpc/fpu/fpu_emu.c:1.16
--- src/sys/arch/powerpc/fpu/fpu_emu.c:1.15 Tue Jan 18 01:02:53 2011
+++ src/sys/arch/powerpc/fpu/fpu_emu.c Mon Jul 23 04:13:06 2012
@@ -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 @@ fpu_dumpfpn(struct fpn *fp)
* 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 @@ fpu_emulate(struct trapframe *tf, struct
#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 @@ fpu_emulate(struct trapframe *tf, struct
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 @@ fpu_execute(struct trapframe *tf, struct
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 @@ fpu_execute(struct trapframe *tf, struct
(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,
Index: src/sys/arch/powerpc/fpu/fpu_emu.h
diff -u src/sys/arch/powerpc/fpu/fpu_emu.h:1.3 src/sys/arch/powerpc/fpu/fpu_emu.h:1.4
--- src/sys/arch/powerpc/fpu/fpu_emu.h:1.3 Sun Dec 11 12:18:42 2005
+++ src/sys/arch/powerpc/fpu/fpu_emu.h Mon Jul 23 04:13:06 2012
@@ -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 fpemu {
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 */
};
/*
Index: src/sys/arch/powerpc/fpu/fpu_extern.h
diff -u src/sys/arch/powerpc/fpu/fpu_extern.h:1.4 src/sys/arch/powerpc/fpu/fpu_extern.h:1.5
--- src/sys/arch/powerpc/fpu/fpu_extern.h:1.4 Mon Apr 28 20:23:32 2008
+++ src/sys/arch/powerpc/fpu/fpu_extern.h Mon Jul 23 04:13:06 2012
@@ -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>
+#include <sys/siginfo.h>
+
struct proc;
struct fpreg;
struct trapframe;
@@ -37,7 +43,7 @@ struct fpemu;
struct fpn;
/* fpu.c */
-int fpu_emulate(struct trapframe *, struct fpreg *);
+bool fpu_emulate(struct trapframe *, struct fpreg *, ksiginfo_t *);
int fpu_execute(struct trapframe *, struct fpemu *, union instr *);
/* fpu_add.c */
@@ -73,3 +79,5 @@ struct fpn *fpu_sqrt(struct fpemu *);
int fpu_shr(struct fpn *, int);
void fpu_norm(struct fpn *);
struct fpn *fpu_newnan(struct fpemu *);
+
+#endif /* _POWERPC_FPU_FPU_EXTERN_H_ */
Index: src/sys/arch/powerpc/ibm4xx/trap.c
diff -u src/sys/arch/powerpc/ibm4xx/trap.c:1.64 src/sys/arch/powerpc/ibm4xx/trap.c:1.65
--- src/sys/arch/powerpc/ibm4xx/trap.c:1.64 Sun Feb 19 21:06:22 2012
+++ src/sys/arch/powerpc/ibm4xx/trap.c Mon Jul 23 04:13:06 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.64 2012/02/19 21:06:22 rmind Exp $ */
+/* $NetBSD: trap.c,v 1.65 2012/07/23 04:13:06 matt Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.64 2012/02/19 21:06:22 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.65 2012/07/23 04:13:06 matt Exp $");
#include "opt_altivec.h"
#include "opt_ddb.h"
@@ -303,13 +303,17 @@ trap(struct trapframe *tf)
l->l_md.md_flags |= MDLWP_USEDFPU;
}
- if ((rv = fpu_emulate(tf, (struct fpreg *)&pcb->pcb_fpu))) {
- KSI_INIT_TRAP(&ksi);
- ksi.ksi_signo = rv;
+ if (fpu_emulate(tf, &pcb->pcb_fpu, &ksi)) {
+ if (ksi.ksi_signo == 0) /* was emulated */
+ break;
+ } else {
+ ksi.ksi_signo = SIGILL;
+ ksi.ksi_code = ILL_ILLOPC;
ksi.ksi_trap = EXC_PGM;
ksi.ksi_addr = (void *)tf->tf_srr0;
- trapsignal(l, &ksi);
}
+
+ trapsignal(l, &ksi);
break;
case EXC_MCHK: