summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2015-09-27 09:11:12 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2015-09-27 09:11:12 +0000
commit966e7350f8c07b33900038be562b3476b9ef901e (patch)
tree3f1f88bd4663c39a034839cbb36565dc063e9163 /sys
parentd5ed9666bcc654146baaddb7c1d6fef143d8d4a2 (diff)
On R8000, make trap() behave closer to interrupt() when servicing a real
interrupt by not invoking refreshcreds(), but closer to itsa() when servicing a trap-reported-as-interrupt by invoking userret() in that case. No change on !defined(CPU_R8000) kernels.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/mips64/mips64/trap.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/sys/arch/mips64/mips64/trap.c b/sys/arch/mips64/mips64/trap.c
index 65bc612da84..f05a6e7c5ab 100644
--- a/sys/arch/mips64/mips64/trap.c
+++ b/sys/arch/mips64/mips64/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.109 2015/08/19 16:40:10 visa Exp $ */
+/* $OpenBSD: trap.c,v 1.110 2015/09/27 09:11:11 miod Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -206,9 +206,6 @@ trap(struct trap_frame *trapframe)
break;
}
- if (type & T_USER)
- refreshcreds(p);
-
#ifdef CPU_R8000
/*
* Some exception causes on R8000 are actually detected by external
@@ -218,34 +215,47 @@ trap(struct trap_frame *trapframe)
* as if they were triggered as regular exceptions.
*/
if ((type & ~T_USER) == T_INT) {
- /*
- * Similar reality check as done in interrupt(), in case
- * an interrupt occured between a write to COP_0_STATUS_REG
- * and it taking effect.
- */
- if (!ISSET(trapframe->sr, SR_INT_ENAB))
- return;
-
if (trapframe->cause & CR_VCE) {
#ifndef DEBUG_INTERRUPT
trapdebug_enter(ci, trapframe, -1);
#endif
panic("VCE or TLBX");
}
+
if (trapframe->cause & CR_FPE) {
#ifndef DEBUG_INTERRUPT
trapdebug_enter(ci, trapframe, -1);
#endif
+ atomic_inc_int(&uvmexp.traps);
+ if (type & T_USER)
+ refreshcreds(p);
itsa(trapframe, ci, p, T_FPE | (type & T_USER));
cp0_reset_cause(CR_FPE);
}
- if (trapframe->cause & CR_INT_MASK)
- interrupt(trapframe);
- return; /* no userret */
- } else
+ if (trapframe->cause & CR_INT_MASK) {
+ /*
+ * Similar reality check as done in interrupt(), in
+ * case an interrupt occured between a write to
+ * COP_0_STATUS_REG and it taking effect.
+ * (I have never seen this occuring on R8000 but
+ * this is cheap)
+ */
+ if (ISSET(trapframe->sr, SR_INT_ENAB))
+ interrupt(trapframe);
+ }
+
+ if ((trapframe->cause & CR_FPE) && (type & T_USER))
+ userret(p);
+
+ return;
+ }
#endif
- itsa(trapframe, ci, p, type);
+
+ if (type & T_USER)
+ refreshcreds(p);
+
+ itsa(trapframe, ci, p, type);
if (type & T_USER)
userret(p);