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:

Reply via email to