Module Name:    src
Committed By:   matt
Date:           Fri Jan  7 15:14:24 UTC 2011

Modified Files:
        src/sys/arch/powerpc/booke [matt-nb5-pq3]: trap.c

Log Message:
Add support for emulating mfpvr and lwsync.  GCC will emit lwsync but booke
doesn't lwsync (sync 1) so we "emulate" it by treating it as a noop since
the exception will have synchronized things for us.


To generate a diff of this commit:
cvs rdiff -u -r1.1.2.1 -r1.1.2.2 src/sys/arch/powerpc/booke/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.1.2.1 src/sys/arch/powerpc/booke/trap.c:1.1.2.2
--- src/sys/arch/powerpc/booke/trap.c:1.1.2.1	Fri Jan  7 01:26:19 2011
+++ src/sys/arch/powerpc/booke/trap.c	Fri Jan  7 15:14:23 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.1.2.1 2011/01/07 01:26:19 matt Exp $	*/
+/*	$NetBSD: trap.c,v 1.1.2.2 2011/01/07 15:14:23 matt Exp $	*/
 /*-
  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -39,7 +39,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.1.2.1 2011/01/07 01:26:19 matt Exp $");
+__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.1.2.2 2011/01/07 15:14:23 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -53,12 +53,14 @@
 #endif
 #include <sys/kauth.h>
 #include <sys/kmem.h>
+#include <sys/ras.h>
 
 #include <uvm/uvm_extern.h>
 
 #include <powerpc/pcb.h>
 #include <powerpc/userret.h>
 #include <powerpc/psl.h>
+#include <powerpc/instr.h>
 
 #include <powerpc/spr.h>
 #include <powerpc/booke/spr.h>
@@ -385,6 +387,26 @@
 	return rv;
 }
 
+static bool
+emulate_opcode(struct trapframe *tf, ksiginfo_t *ksi)
+{
+	uint32_t opcode;
+        if (copyin((void *)tf->tf_srr0, &opcode, sizeof(opcode)) != 0)
+		return false;
+
+	if (opcode == OPC_LWSYNC)
+		return true;
+
+	if (OPC_MFSPR_P(opcode, SPR_PVR)) {
+		__asm ("mfpvr %0" : "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)]));
+		return true;
+	}
+
+	/*
+	 * If we bothered to emulate FP, we would try to do so here.
+	 */
+	return false;
+}
 
 static int
 pgm_exception(struct trapframe *tf, ksiginfo_t *ksi)
@@ -392,21 +414,37 @@
 	struct cpu_info * const ci = curcpu();
 	int rv = EPERM;
 
-	if (rv != 0 && usertrap_p(tf)) {
-		ci->ci_ev_pgm.ev_count++;
-		KSI_INIT_TRAP(ksi);
-		ksi->ksi_signo = SIGILL;
-		ksi->ksi_trap = EXC_PGM;
-		if (tf->tf_esr & ESR_PIL)
-			ksi->ksi_code = ILL_ILLOPC;
-		else if (tf->tf_esr & ESR_PPR)
-			ksi->ksi_code = ILL_PRVOPC;
-		else if (tf->tf_esr & ESR_PTR)
-			ksi->ksi_code = ILL_ILLTRP;
-		else
-			ksi->ksi_code = 0;
-		ksi->ksi_addr = (void *)tf->tf_srr0;
+	if (!usertrap_p(tf))
+		return rv;
+
+	ci->ci_ev_pgm.ev_count++;
+
+	if (tf->tf_esr & ESR_PTR) {
+		struct proc *p = curlwp->l_proc;
+		if (p->p_raslist != NULL
+		    && ras_lookup(p, (void *)tf->tf_srr0) != (void *) -1) {
+			tf->tf_srr0 += 4;
+			return 0;
+		}
+	} else if (tf->tf_esr & (ESR_PIL|ESR_PPR)) {
+		if (emulate_opcode(tf, ksi)) {
+			tf->tf_srr0 += 4;
+			return 0;
+		}
 	}
+
+	KSI_INIT_TRAP(ksi);
+	ksi->ksi_signo = SIGILL;
+	ksi->ksi_trap = EXC_PGM;
+	if (tf->tf_esr & ESR_PIL)
+		ksi->ksi_code = ILL_ILLOPC;
+	else if (tf->tf_esr & ESR_PPR)
+		ksi->ksi_code = ILL_PRVOPC;
+	else if (tf->tf_esr & ESR_PTR)
+		ksi->ksi_code = ILL_ILLTRP;
+	else
+		ksi->ksi_code = 0;
+	ksi->ksi_addr = (void *)tf->tf_srr0;
 	return rv;
 }
 

Reply via email to