summaryrefslogtreecommitdiff
path: root/sys/arch/mips64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mips64')
-rw-r--r--sys/arch/mips64/include/cpu.h6
-rw-r--r--sys/arch/mips64/mips64/exception.S79
-rw-r--r--sys/arch/mips64/mips64/interrupt.c111
3 files changed, 121 insertions, 75 deletions
diff --git a/sys/arch/mips64/include/cpu.h b/sys/arch/mips64/include/cpu.h
index 57ac780dfc3..15b1352e2e3 100644
--- a/sys/arch/mips64/include/cpu.h
+++ b/sys/arch/mips64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.7 2004/09/21 05:51:13 miod Exp $ */
+/* $OpenBSD: cpu.h,v 1.8 2004/09/27 19:20:49 pefo Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -328,12 +328,12 @@
* Arguments to hardclock and gatherstats encapsulate the previous
* machine state in an opaque clockframe.
*/
+extern int int_nest_cntr;
#define clockframe trap_frame /* Use normal trap frame */
#define CLKF_USERMODE(framep) ((framep)->sr & SR_KSU_USER)
-#define CLKF_BASEPRI(framep) ((framep)->cpl == 0)
#define CLKF_PC(framep) ((framep)->pc)
-#define CLKF_INTR(framep) (0)
+#define CLKF_INTR(framep) (int_nest_cntr > 0)
/*
* Preempt the current process if in interrupt from user mode,
diff --git a/sys/arch/mips64/mips64/exception.S b/sys/arch/mips64/mips64/exception.S
index 1a06df4938b..65e582604b9 100644
--- a/sys/arch/mips64/mips64/exception.S
+++ b/sys/arch/mips64/mips64/exception.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: exception.S,v 1.6 2004/09/19 20:24:38 pefo Exp $ */
+/* $OpenBSD: exception.S,v 1.7 2004/09/27 19:20:49 pefo Exp $ */
/*
* Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -48,15 +48,14 @@
#include "assym.h"
-/*
- * DDB stack backtrace uses 'jr ra' to find functions starts.
- * Put this after functions which does not end with 'jr ra'.
- */
-#define DDB_BARRIER \
- jr ra; nop
-
.set mips3
+ .data
+ .globl int_nest_cntr
+int_nest_cntr:
+ .word -1
+ .text
+
k_exception_table:
PTR_VAL k_intr
PTR_VAL k_general
@@ -127,8 +126,6 @@ u_exception_table:
.set noreorder # Noreorder is default style!
-#define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
-
/*---------------------------------------------------------------- exception
* General exception handler dispatcher. This code is copied
* to the vector area and must thus be PIC and less than 128
@@ -151,7 +148,7 @@ exception:
PTR_L k1, tlbtrcptr
PTR_ADDU k1, 4*REGSZ
LI k0, 0x100
- nor k0, zero, k0
+ not k0, k0
and k1, k0
LA k0, tlbtrcptr
PTR_S k1, 0(k0)
@@ -184,7 +181,6 @@ k_exception:
.globl e_exception
e_exception:
- DDB_BARRIER
/*---------------------------------------------------------------- k_intr
* Handle an interrupt in kernel mode. This is easy since we
@@ -206,6 +202,10 @@ NNON_LEAF(k_intr, FRAMESZ(KERN_EXC_FRAME_SIZE), ra)
LA gp, _gp
and t0, a1, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
mtc0 t0, COP_0_STATUS_REG
+ LA t1, int_nest_cntr
+ lw t2, (t1)
+ addiu t2, 1
+ sw t2, (t1)
ITLBNOPFIX
PTR_S a0, 0(sp)
jal interrupt
@@ -216,6 +216,11 @@ NNON_LEAF(k_intr, FRAMESZ(KERN_EXC_FRAME_SIZE), ra)
and t0, t0, t1
mtc0 t0, COP_0_STATUS_REG
+ LA t1, int_nest_cntr
+ lw t2, (t1)
+ addiu t2, -1
+ sw t2, (t1)
+
PTR_L a0, CF_RA_OFFS + KERN_REG_SIZE(sp)
.set noat
#if 0
@@ -226,7 +231,6 @@ NNON_LEAF(k_intr, FRAMESZ(KERN_EXC_FRAME_SIZE), ra)
PTR_ADDU sp, sp, FRAMESZ(KERN_EXC_FRAME_SIZE)
sync
eret
- DDB_BARRIER
.set at
END(k_intr)
@@ -250,6 +254,10 @@ NNON_LEAF(u_intr, FRAMESZ(CF_SZ), ra)
.set at
and t0, a1, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
mtc0 t0, COP_0_STATUS_REG
+ LA t1, int_nest_cntr
+ lw t2, (t1)
+ addiu t2, 1
+ sw t2, (t1)
ITLBNOPFIX
PTR_S a0, 0(sp)
jal interrupt
@@ -316,11 +324,14 @@ NNON_LEAF(u_intr, FRAMESZ(CF_SZ), ra)
li t1, ~SR_INT_ENAB
and t0, t0, t1
mtc0 t0, COP_0_STATUS_REG
- ITLBNOPFIX
+
+ LA t1, int_nest_cntr
+ lw t2, (t1)
+ addiu t2, -1
+ sw t2, (t1)
ori t0, SR_EXL # restoring to user mode.
mtc0 t0, COP_0_STATUS_REG # must set exeption level bit.
- ITLBNOPFIX
PTR_L k0, curprocpaddr
RESTORE_REG(a3, CPL, k0, 0)
@@ -337,24 +348,39 @@ NNON_LEAF(u_intr, FRAMESZ(CF_SZ), ra)
LI k1, 0
sync
eret
- DDB_BARRIER
.set at
END(u_intr)
-/*---------------------------------------------------------------- set_sint
- * Atomic ipending update
+/*---------------------------------------------------------------- set_ipending
+ * Atomic ipending set
+ */
+LEAF(set_ipending, 0)
+ LA a1, ipending
+1:
+ ll v0, 0(a1)
+ or v1, v0, a0
+ sc v1, 0(a1)
+ beqz v1, 1b
+ nop
+ j ra
+ nop
+END(set_ipending)
+
+/*---------------------------------------------------------------- set_ipending
+ * Atomic ipending clear
*/
-LEAF(set_sint, 0)
- LA v1, ipending
+LEAF(clr_ipending, 0)
+ LA a1, ipending
+ not a0, a0
1:
- ll v0, 0(v1)
- or v0, a0
- sc v0, 0(v1)
- beqz v0, 1b
+ ll v0, 0(a1)
+ and v1, v0, a0
+ sc v1, 0(a1)
+ beqz v1, 1b
nop
j ra
nop
-END(set_sint)
+END(clr_ipending)
/*---------------------------------------------------------------- k_general
* Handle a kernel general trap. This is very much like
@@ -398,7 +424,6 @@ NNON_LEAF(k_general, FRAMESZ(KERN_EXC_FRAME_SIZE), ra)
PTR_ADDU sp, sp, FRAMESZ(KERN_EXC_FRAME_SIZE)
sync
eret
- DDB_BARRIER
.set at
END(k_general)
@@ -494,7 +519,6 @@ NNON_LEAF(u_general, FRAMESZ(CF_SZ), ra)
LI k1, 0
sync
eret
- DDB_BARRIER
.set at
END(u_general)
@@ -606,7 +630,6 @@ NNON_LEAF(u_syscall, FRAMESZ(CF_SZ), ra)
REG_L ra, UADDR+U_PCB_REGS+(RA * REGSZ)
sync
eret
- DDB_BARRIER
.set at
END(u_syscall)
#endif
diff --git a/sys/arch/mips64/mips64/interrupt.c b/sys/arch/mips64/mips64/interrupt.c
index fc1eacf6c3a..df77cd1374f 100644
--- a/sys/arch/mips64/mips64/interrupt.c
+++ b/sys/arch/mips64/mips64/interrupt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: interrupt.c,v 1.7 2004/09/24 14:22:49 deraadt Exp $ */
+/* $OpenBSD: interrupt.c,v 1.8 2004/09/27 19:20:49 pefo Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -56,6 +56,9 @@
#include <ddb/db_sym.h>
#endif
+static struct evcount soft_count;
+static int soft_irq = 0;
+
volatile intrmask_t cpl;
volatile intrmask_t ipending, astpending;
@@ -69,7 +72,9 @@ struct {
intrmask_t (*int_hand)(intrmask_t, struct trap_frame *);
} cpu_int_tab[NLOWINT];
-void_f *pending_hand;
+void dummy_do_pending_int(int);
+
+int_f *pending_hand = &dummy_do_pending_int;
int netisr;
@@ -136,7 +141,7 @@ interrupt(struct trap_frame *trapframe)
u_int32_t pending;
u_int32_t cause;
int i;
- intrmask_t pcpl;
+ intrmask_t xcpl;
/*
* Paranoic? Perhaps. But if we got here with the enable
@@ -149,22 +154,21 @@ interrupt(struct trap_frame *trapframe)
return;
}
- uvmexp.intrs++;
- pcpl = splhigh() ; /* Turn off all and get current SW mask */
-
#ifdef DEBUG_INTERRUPT
trapdebug_enter(trapframe, 0);
#endif
- pending = trapframe->cause & CR_IPEND;
-#ifdef IMASK_EXTERNAL
- pending &= idle_mask << 8;
-#else
- ipending |= (pending >> 8) & pcpl;
- pending &= ~(pcpl << 8);
-#endif
+ uvmexp.intrs++;
+
+ /* Mask out interrupts from cause that are unmasked */
+ pending = trapframe->cause & CR_IPEND & trapframe->sr;
cause = pending;
+ if (cause & SOFT_INT_MASK_0) {
+ clearsoftintr0();
+ soft_count.ec_count++;
+ }
+
if (cause & CR_INT_PERF) {
rm7k_perfintr(trapframe);
cause &= ~CR_INT_PERF;
@@ -187,19 +191,31 @@ printf("Unhandled interrupt %x:%x\n", cause, pending);
* Reenable all non served hardware levels.
*/
#if 0
- splx((trapframe->sr & ~cause & SR_INT_MASK) | SR_INT_ENAB);
+ /* XXX the following should, when req., change the IC reg as well */
+ setsr((trapframe->sr & ~pending) | SR_INT_ENAB);
#endif
- if (pending & SOFT_INT_MASK_0) {
- clearsoftintr0();
- uvmexp.softs++;
+ xcpl = splsoftnet();
+ if ((ipending & SINT_CLOCKMASK) & ~xcpl) {
+ clr_ipending(SINT_CLOCKMASK);
+ softclock();
+ }
+ if ((ipending & SINT_NETMASK) & ~xcpl) {
+ extern int netisr;
+ int isr = netisr;
+ netisr = 0;
+ clr_ipending(SINT_NETMASK);
+#define DONETISR(b,f) if (isr & (1 << (b))) f();
+#include <net/netisr_dispatch.h>
}
-#ifndef IMASK_EXTERNAL
- trapframe->sr &= ~((pcpl << 8) & SR_INT_MASK);
- trapframe->ic &= ~(pcpl & IC_INT_MASK);
+#ifdef NOTYET
+ if ((ipending & SINT_TTYMASK) & ~xcpl) {
+ clr_ipending(SINT_TTYMASK);
+ compoll(NULL);
+ }
#endif
- splx(pcpl); /* Process pendings. */
+ cpl = xcpl;
}
@@ -213,6 +229,8 @@ void
set_intr(int pri, intrmask_t mask,
intrmask_t (*int_hand)(intrmask_t, struct trap_frame *))
{
+ if (!idle_mask & (SOFT_INT_MASK >> 8))
+ evcount_attach(&soft_count, "soft", (void *)&soft_irq, &evcount_intr);
if (pri < 0 || pri >= NLOWINT) {
panic("set_intr: to high priority");
}
@@ -458,31 +476,29 @@ generic_intr_makemasks()
}
void
-generic_do_pending_int()
+generic_do_pending_int(int newcpl)
{
struct intrhand *ih;
int vector;
- intrmask_t pcpl;
intrmask_t hwpend;
struct trap_frame cf;
-static volatile int processing;
+ static volatile int processing;
- /* Don't recurse... */
- if (processing)
+ /* Don't recurse... but change the mask. */
+ if (processing) {
+ cpl = newcpl;
return;
+ }
processing = 1;
-/* XXX interrupt vulnerable when changing ipending */
- pcpl = splhigh(); /* Turn off all */
-
/* XXX Fake a trapframe for clock pendings... */
cf.pc = (int)&generic_do_pending_int;
cf.sr = 0;
- cf.cpl = pcpl;
+ cf.cpl = cpl;
- hwpend = ipending & ~pcpl; /* Do now unmasked pendings */
+ hwpend = ipending & ~newcpl; /* Do pendings being unmasked */
hwpend &= ~(SINT_ALLMASK);
- ipending &= ~hwpend;
+ clr_ipending(hwpend);
intem |= hwpend;
while (hwpend) {
vector = ffs(hwpend) - 1;
@@ -496,30 +512,36 @@ static volatile int processing;
ih = ih->ih_next;
}
}
- if ((ipending & SINT_CLOCKMASK) & ~pcpl) {
- ipending &= ~SINT_CLOCKMASK;
+ if ((ipending & SINT_CLOCKMASK) & ~newcpl) {
+ clr_ipending(SINT_CLOCKMASK);
softclock();
}
- if ((ipending & SINT_NETMASK) & ~pcpl) {
+ if ((ipending & SINT_NETMASK) & ~newcpl) {
int isr = netisr;
netisr = 0;
- ipending &= ~SINT_NETMASK;
+ clr_ipending(SINT_NETMASK);
#define DONETISR(b,f) if (isr & (1 << (b))) f();
#include <net/netisr_dispatch.h>
}
#ifdef NOTYET
- if ((ipending & SINT_TTYMASK) & ~pcpl) {
- ipending &= ~SINT_TTYMASK;
+ if ((ipending & SINT_TTYMASK) & ~newcpl) {
+ clr_ipending(SINT_TTYMASK);
compoll(NULL);
}
#endif
- cpl = pcpl; /* Don't use splx... we are here already! */
- updateimask(pcpl); /* Update CPU mask ins SR register */
+ cpl = newcpl;
+ updateimask(newcpl); /* Update CPU mask ins SR register */
processing = 0;
}
+void
+dummy_do_pending_int(int newcpl)
+{
+ /* Dummy handler */
+}
+
/*
* splinit() is special in that sense that it require us to update
* the interrupt mask in the CPU since it may be the first time we arm
@@ -553,6 +575,11 @@ generic_iointr(intrmask_t pending, struct trap_frame *cf)
catched = 0;
+ set_ipending((pending >> 8) & cpl);
+ pending &= ~(cpl << 8);
+ cf->sr &= ~((ipending << 8) & SR_INT_MASK);
+ cf->ic &= ~(ipending & IC_INT_MASK);
+
for (v = 2, vm = 0x400; pending != 0 && v < 16 ; v++, vm <<= 1) {
if (pending & vm) {
ih = intrhand[v];
@@ -582,8 +609,4 @@ splraise(int newcpl)
__asm__ (" sync\n .set reorder\n");
return (oldcpl);
}
-volatile intrmask_t cpl;
-volatile intrmask_t ipending, astpending;
-
-intrmask_t imask[NIPLS];
#endif