summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorbenno <benno@FreeBSD.org>2002-06-29 09:28:21 +0000
committerbenno <benno@FreeBSD.org>2002-06-29 09:28:21 +0000
commit6c2607ad88792b8bc1b57d0a041605e8aa64ef46 (patch)
treeb9c0a09df64c61a350b44617c4ef96ea16dc1fe3 /sys
parented94a8432d7c0a32bb7aa036d2050942d9c618b1 (diff)
downloadFreeBSD-src-6c2607ad88792b8bc1b57d0a041605e8aa64ef46.zip
FreeBSD-src-6c2607ad88792b8bc1b57d0a041605e8aa64ef46.tar.gz
Many fixes to low-level trap and interrupt handling:
- Tidy up clock code. Don't repeatedly call hardclock(). - Remove intrnames, decrnest and intrcnt from locore.s - Coalesce all trap handling into a single stub that then calls a dispatch function. Submitted by: Peter Grehan <peterg@ptree32.com.au>
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files.powerpc1
-rw-r--r--sys/powerpc/aim/clock.c14
-rw-r--r--sys/powerpc/aim/interrupt.c123
-rw-r--r--sys/powerpc/aim/locore.S30
-rw-r--r--sys/powerpc/aim/trap_subr.S225
-rw-r--r--sys/powerpc/powerpc/clock.c14
-rw-r--r--sys/powerpc/powerpc/interrupt.c123
-rw-r--r--sys/powerpc/powerpc/locore.S30
-rw-r--r--sys/powerpc/powerpc/locore.s30
-rw-r--r--sys/powerpc/powerpc/trap_subr.S225
10 files changed, 303 insertions, 512 deletions
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 1845b53..2f91ace 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -21,6 +21,7 @@ powerpc/powerpc/elf_machdep.c standard
powerpc/powerpc/extintr.c standard
powerpc/powerpc/fpu.c standard
powerpc/powerpc/fuswintr.c standard
+powerpc/powerpc/interrupt.c standard
powerpc/powerpc/machdep.c standard
powerpc/powerpc/nexus.c standard
powerpc/powerpc/ofwmagic.s standard
diff --git a/sys/powerpc/aim/clock.c b/sys/powerpc/aim/clock.c
index 3194674..5aa880f 100644
--- a/sys/powerpc/aim/clock.c
+++ b/sys/powerpc/aim/clock.c
@@ -83,7 +83,8 @@ static const char rcsid[] =
/*
* Initially we assume a processor with a bus frequency of 12.5 MHz.
*/
-static u_long ticks_per_sec = 12500000;
+u_int tickspending;
+static u_long ticks_per_sec = 12500000;
static u_long ns_per_tick = 80;
static long ticks_per_intr;
static volatile u_long lasttb;
@@ -189,28 +190,25 @@ decr_intr(struct clockframe *frame)
*/
lasttb = tb + tick - ticks_per_intr;
- /*
- * This probably needs some kind of locking.
- */
-
- intrcnt[CNT_CLOCK]++;
-
nticks += tickspending;
tickspending = 0;
/*
* Reenable interrupts
*/
+#if 0
msr = mfmsr();
mtmsr(msr | PSL_EE | PSL_RI);
-
+#endif
/*
* Do standard timer interrupt stuff.
* Do softclock stuff only on the last iteration.
*/
+#if 0
while (--nticks > 0) {
hardclock(frame);
}
+#endif
hardclock(frame);
}
diff --git a/sys/powerpc/aim/interrupt.c b/sys/powerpc/aim/interrupt.c
new file mode 100644
index 0000000..491f53d
--- /dev/null
+++ b/sys/powerpc/aim/interrupt.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2002 by Peter Grehan. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Interrupts are dispatched to here from locore asm
+ */
+
+#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+#include <sys/unistd.h>
+#include <sys/vmmeter.h>
+
+#include <machine/cpu.h>
+#include <machine/db_machdep.h>
+#include <machine/fpu.h>
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include <machine/spr.h>
+#include <machine/sr.h>
+#include <machine/interruptvar.h>
+
+void powerpc_interrupt(struct trapframe *);
+
+u_long intrcnt[1];
+u_long eintrcnt[1];
+
+char intrnames[1];
+char eintrnames[1];
+
+/*
+ * External interrupt install routines
+ */
+static void (*powerpc_extintr_handler)(void);
+
+void
+ext_intr_install(void (*new_extint)(void))
+{
+ powerpc_extintr_handler = new_extint;
+}
+
+extern void decr_intr(struct clockframe *);
+extern void trap(struct trapframe *);
+
+/*
+ * A very short dispatch, to try and maximise assembler code use
+ * between all exception types. Maybe 'true' interrupts should go
+ * here, and the trap code can come in separately
+ */
+void
+powerpc_interrupt(struct trapframe *framep)
+{
+ struct thread *td;
+ struct clockframe ckframe;
+
+ td = curthread;
+
+ switch (framep->exc) {
+ case EXC_EXI:
+ atomic_add_int(&td->td_intr_nesting_level, 1);
+ (*powerpc_extintr_handler)();
+ atomic_subtract_int(&td->td_intr_nesting_level, 1);
+ break;
+
+ case EXC_DECR:
+ atomic_add_int(&td->td_intr_nesting_level, 1);
+ ckframe.srr0 = framep->srr0;
+ ckframe.srr1 = framep->srr1;
+ decr_intr(&ckframe);
+ atomic_subtract_int(&td->td_intr_nesting_level, 1);
+ break;
+
+ default:
+ /*
+ * Re-enable interrupts and call the generic trap code
+ */
+#if 0
+ printf("powerpc_interrupt: got trap\n");
+#endif
+ mtmsr(mfmsr() | PSL_EE);
+ isync();
+ trap(framep);
+ }
+}
diff --git a/sys/powerpc/aim/locore.S b/sys/powerpc/aim/locore.S
index fa231e8..f8d0eb1 100644
--- a/sys/powerpc/aim/locore.S
+++ b/sys/powerpc/aim/locore.S
@@ -86,36 +86,6 @@ GLOBAL(proc0paddr)
.long 0 /* proc0 p_addr */
GLOBAL(PTmap)
.long 0 /* PTmap */
-GLOBAL(decrnest)
- .long 0
-
-GLOBAL(intrnames)
- .asciz "irq0", "irq1", "irq2", "irq3"
- .asciz "irq4", "irq5", "irq6", "irq7"
- .asciz "irq8", "irq9", "irq10", "irq11"
- .asciz "irq12", "irq13", "irq14", "irq15"
- .asciz "irq16", "irq17", "irq18", "irq19"
- .asciz "irq20", "irq21", "irq22", "irq23"
- .asciz "irq24", "irq25", "irq26", "irq27"
- .asciz "irq28", "irq29", "irq30", "irq31"
- .asciz "irq32", "irq33", "irq34", "irq35"
- .asciz "irq36", "irq37", "irq38", "irq39"
- .asciz "irq40", "irq41", "irq42", "irq43"
- .asciz "irq44", "irq45", "irq46", "irq47"
- .asciz "irq48", "irq49", "irq50", "irq51"
- .asciz "irq52", "irq53", "irq54", "irq55"
- .asciz "irq56", "irq57", "irq58", "irq59"
- .asciz "irq60", "irq61", "irq62", "irq63"
- .asciz "clock", "softclock", "softnet", "softserial"
-GLOBAL(eintrnames)
- .align 4
-GLOBAL(intrcnt)
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0
-GLOBAL(eintrcnt)
GLOBAL(ofmsr)
.long 0 /* msr used in Open Firmware */
diff --git a/sys/powerpc/aim/trap_subr.S b/sys/powerpc/aim/trap_subr.S
index 09b152b..0340d78 100644
--- a/sys/powerpc/aim/trap_subr.S
+++ b/sys/powerpc/aim/trap_subr.S
@@ -46,8 +46,6 @@
#define EXC_AST 0x3000
.data
.align 4
-astpending:
- .long 0
cpassert:
.asciz "attempting to return from kernel with no current pmap"
@@ -275,48 +273,6 @@ CNAME(isitrap601):
CNAME(isi601size)= .-CNAME(isitrap601)
/*
- * This one for the external interrupt handler.
- */
- .globl CNAME(extint),CNAME(extsize)
-CNAME(extint):
- mtsprg 1,1 /* save SP */
- stmw 28,tempsave(0) /* free r28-r31 */
- mflr 28 /* save LR */
- mfcr 29 /* save CR */
- mfxer 30 /* save XER */
- lis 1,intstk+INTSTK@ha /* get interrupt stack */
- addi 1,1,intstk+INTSTK@l /* this is really intr_depth! */
- lwz 31,0(1) /* were we already running on intstk? */
- addic. 31,31,1
- stw 31,0(1)
- beq 1f
- mfsprg 1,1 /* yes, get old SP */
-1:
- ba extintr
-CNAME(extsize) = .-CNAME(extint)
-
-/*
- * And this one for the decrementer interrupt handler.
- */
- .globl CNAME(decrint),CNAME(decrsize)
-CNAME(decrint):
- mtsprg 1,1 /* save SP */
- stmw 28,tempsave(0) /* free r28-r31 */
- mflr 28 /* save LR */
- mfcr 29 /* save CR */
- mfxer 30 /* save XER */
- lis 1,intstk+INTSTK@ha /* get interrupt stack */
- addi 1,1,intstk+INTSTK@l
- lwz 31,0(1) /* were we already running on intstk? */
- addic. 31,31,1
- stw 31,0(1)
- beq 1f
- mfsprg 1,1 /* yes, get old SP */
-1:
- ba decrintr
-CNAME(decrsize) = .-CNAME(decrint)
-
-/*
* Now the tlb software load for 603 processors:
* (Code essentially from the 603e User Manual, Chapter 5, but
* corrected a lot.)
@@ -579,7 +535,7 @@ CNAME(ipkdbsize) = .-CNAME(ipkdblow)
mfsrr1 31; \
stmw 30,savearea+24(0); \
mfmsr 30; \
- ori 30,30,(PSL_DR|PSL_IR); \
+ ori 30,30,(PSL_DR|PSL_IR)@l; \
mtmsr 30; \
isync; \
mfsprg 31,1; \
@@ -710,16 +666,20 @@ s_trap:
mtsr 7,31
FRAME_SETUP(tempsave)
/* Now we can recover interrupts again: */
+#if 0
mfmsr 7
ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l
mtmsr 7
isync
-/* Call C trap code: */
+#endif
+/* Call C interrupt dispatcher: */
trapagain:
addi 3,1,8
- bl CNAME(trap)
+ bl CNAME(powerpc_interrupt)
.globl CNAME(trapexit)
CNAME(trapexit):
+
+#if 0
/* Disable interrupts: */
mfmsr 3
andi. 3,3,~PSL_EE@l
@@ -728,14 +688,24 @@ CNAME(trapexit):
lwz 5,FRAME_SRR1+8(1)
mtcr 5
bc 4,17,1f /* branch if PSL_PR is false */
- lis 3,CNAME(astpending)@ha
- lwz 4,CNAME(astpending)@l(3)
- andi. 4,4,1
+
+ mfsprg 3, 0 /* get per-CPU pointer */
+ lwz 4, PC_CURTHREAD(3) /* deref to get curthread */
+ lwz 3, TD_KSE(4) /* deref to get current KSE */
+ lwz 4, KE_FLAGS(3) /* get KSE flags value */
+ andi. 4,4,KEF_ASTPENDING|KEF_NEEDRESCHED
beq 1f
- li 6,EXC_AST
+ li 6,EXC_AST /* update exception type */
stw 6,FRAME_EXC+8(1)
- b trapagain
+ mfmsr 3 /* re-enable interrupts */
+ ori 3,3,PSL_EE@l
+ mtmsr 3
+ isync
+ addi 3,1,8
+ bl CNAME(ast_test)
+ b trapexit /* test ast ret value ? */
1:
+#endif
FRAME_LEAVE(tempsave)
rfi
@@ -820,157 +790,6 @@ s_isitrap:
mfsrr0 3
b s_pte_spill /* above */
-/*
- * External interrupt second level handler
- */
-#define INTRENTER \
-/* Save non-volatile registers: */ \
- stwu 1,-IFRAMELEN(1); /* temporarily */ \
- stw 0,IFRAME_R0(1); \
- mfsprg 0,1; /* get original SP */ \
- stw 0,IFRAME_R1(1); /* and store it */ \
- stw 3,IFRAME_R3(1); \
- stw 4,IFRAME_R4(1); \
- stw 5,IFRAME_R5(1); \
- stw 6,IFRAME_R6(1); \
- stw 7,IFRAME_R7(1); \
- stw 8,IFRAME_R8(1); \
- stw 9,IFRAME_R9(1); \
- stw 10,IFRAME_R10(1); \
- stw 11,IFRAME_R11(1); \
- stw 12,IFRAME_R12(1); \
- stw 28,IFRAME_LR(1); /* saved LR */ \
- stw 29,IFRAME_CR(1); /* saved CR */ \
- stw 30,IFRAME_XER(1); /* saved XER */ \
- lmw 28,tempsave(0); /* restore r28-r31 */ \
- mfctr 6; \
- lis 5,CNAME(intr_depth)@ha; \
- lwz 5,CNAME(intr_depth)@l(5); \
- mfsrr0 4; \
- mfsrr1 3; \
- stw 6,IFRAME_CTR(1); \
- stw 5,IFRAME_INTR_DEPTH(1); \
- stw 4,IFRAME_SRR0(1); \
- stw 3,IFRAME_SRR1(1); \
- mtcr 3; \
- bc 4,17,99f; /* branch if PSL_PR is false */ \
- lis 3,EMPTY_SEGMENT@h; \
- ori 3,3,EMPTY_SEGMENT@l; \
- mtsr 0,3; /* reset SRs so BAT spills work */ \
- mtsr 1,3; \
- mtsr 2,3; \
- mtsr 3,3; \
- mtsr 4,3; \
- mtsr 5,3; \
- mtsr 6,3; \
- mtsr 7,3; \
-/* interrupts are recoverable here, and enable translation */ \
- lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \
- ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \
- mtsr KERNEL_SR,3; \
-99: mfmsr 5; \
- ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \
- mtmsr 5; \
- isync
-
- .globl CNAME(extint_call)
-extintr:
- INTRENTER
-CNAME(extint_call):
- bl CNAME(extint_call) /* to be filled in later */
-
-intr_exit:
-/* Disable interrupts (should already be disabled) and MMU here: */
- mfmsr 3
- andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l
- mtmsr 3
- isync
-/* restore possibly overwritten registers: */
- lwz 12,IFRAME_R12(1)
- lwz 11,IFRAME_R11(1)
- lwz 10,IFRAME_R10(1)
- lwz 9,IFRAME_R9(1)
- lwz 8,IFRAME_R8(1)
- lwz 7,IFRAME_R7(1)
- lwz 6,IFRAME_SRR1(1)
- lwz 5,IFRAME_SRR0(1)
- lwz 4,IFRAME_CTR(1)
- lwz 3,IFRAME_XER(1)
- mtsrr1 6
- mtsrr0 5
- mtctr 4
- mtxer 3
-/* Returning to user mode? */
- mtcr 6 /* saved SRR1 */
- bc 4,17,1f /* branch if PSL_PR is false */
- mfsprg 31,0
- lwz 3,PC_CURPMAP(31)
- lwz 4,PM_SR+0(3)
- mtsr 0,4 /* Restore SR0 */
- lwz 4,PM_SR+4(3)
- mtsr 1,4 /* Restore SR1 */
- lwz 4,PM_SR+8(3)
- mtsr 2,4 /* Restore SR2 */
- lwz 4,PM_SR+12(3)
- mtsr 3,4 /* Restore SR3 */
- lwz 4,PM_SR+16(3)
- mtsr 4,4 /* Restore SR4 */
- lwz 4,PM_SR+20(3)
- mtsr 5,4 /* Restore SR5 */
- lwz 4,PM_SR+24(3)
- mtsr 6,4 /* Restore SR6 */
- lwz 4,PM_SR+28(3)
- mtsr 7,4 /* Restore SR7 */
- lwz 3,PM_KERNELSR(3)
- mtsr KERNEL_SR,3 /* Restore kernel SR */
- lis 3,CNAME(astpending)@ha /* Test AST pending */
- lwz 4,CNAME(astpending)@l(3)
- andi. 4,4,1
- beq 1f
-/* Setup for entry to realtrap: */
- lwz 3,IFRAME_R1(1) /* get saved SP */
- mtsprg 1,3
- li 6,EXC_AST
- stmw 28,tempsave(0) /* establish tempsave again */
- mtlr 6
- lwz 28,IFRAME_LR(1) /* saved LR */
- lwz 29,IFRAME_CR(1) /* saved CR */
- lwz 6,IFRAME_R6(1)
- lwz 5,IFRAME_R5(1)
- lwz 4,IFRAME_R4(1)
- lwz 3,IFRAME_R3(1)
- lwz 0,IFRAME_R0(1)
- lis 30,CNAME(intr_depth)@ha /* adjust reentrancy count */
- lwz 31,CNAME(intr_depth)@l(30)
- addi 31,31,-1
- stw 31,CNAME(intr_depth)@l(30)
- b realtrap
-1:
-/* Here is the normal exit of extintr: */
- lwz 5,IFRAME_CR(1)
- lwz 6,IFRAME_LR(1)
- mtcr 5
- mtlr 6
- lwz 6,IFRAME_R6(1)
- lwz 5,IFRAME_R5(1)
- lis 3,CNAME(intr_depth)@ha /* adjust reentrancy count */
- lwz 4,CNAME(intr_depth)@l(3)
- addi 4,4,-1
- stw 4,CNAME(intr_depth)@l(3)
- lwz 4,IFRAME_R4(1)
- lwz 3,IFRAME_R3(1)
- lwz 0,IFRAME_R0(1)
- lwz 1,IFRAME_R1(1)
- rfi
-
-/*
- * Decrementer interrupt second level handler
- */
-decrintr:
- INTRENTER
- addi 3,1,8 /* intr frame -> clock frame */
- bl CNAME(decr_intr)
- b intr_exit
#if defined(DDB)
/*
diff --git a/sys/powerpc/powerpc/clock.c b/sys/powerpc/powerpc/clock.c
index 3194674..5aa880f 100644
--- a/sys/powerpc/powerpc/clock.c
+++ b/sys/powerpc/powerpc/clock.c
@@ -83,7 +83,8 @@ static const char rcsid[] =
/*
* Initially we assume a processor with a bus frequency of 12.5 MHz.
*/
-static u_long ticks_per_sec = 12500000;
+u_int tickspending;
+static u_long ticks_per_sec = 12500000;
static u_long ns_per_tick = 80;
static long ticks_per_intr;
static volatile u_long lasttb;
@@ -189,28 +190,25 @@ decr_intr(struct clockframe *frame)
*/
lasttb = tb + tick - ticks_per_intr;
- /*
- * This probably needs some kind of locking.
- */
-
- intrcnt[CNT_CLOCK]++;
-
nticks += tickspending;
tickspending = 0;
/*
* Reenable interrupts
*/
+#if 0
msr = mfmsr();
mtmsr(msr | PSL_EE | PSL_RI);
-
+#endif
/*
* Do standard timer interrupt stuff.
* Do softclock stuff only on the last iteration.
*/
+#if 0
while (--nticks > 0) {
hardclock(frame);
}
+#endif
hardclock(frame);
}
diff --git a/sys/powerpc/powerpc/interrupt.c b/sys/powerpc/powerpc/interrupt.c
new file mode 100644
index 0000000..491f53d
--- /dev/null
+++ b/sys/powerpc/powerpc/interrupt.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2002 by Peter Grehan. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Interrupts are dispatched to here from locore asm
+ */
+
+#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+#include <sys/unistd.h>
+#include <sys/vmmeter.h>
+
+#include <machine/cpu.h>
+#include <machine/db_machdep.h>
+#include <machine/fpu.h>
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include <machine/spr.h>
+#include <machine/sr.h>
+#include <machine/interruptvar.h>
+
+void powerpc_interrupt(struct trapframe *);
+
+u_long intrcnt[1];
+u_long eintrcnt[1];
+
+char intrnames[1];
+char eintrnames[1];
+
+/*
+ * External interrupt install routines
+ */
+static void (*powerpc_extintr_handler)(void);
+
+void
+ext_intr_install(void (*new_extint)(void))
+{
+ powerpc_extintr_handler = new_extint;
+}
+
+extern void decr_intr(struct clockframe *);
+extern void trap(struct trapframe *);
+
+/*
+ * A very short dispatch, to try and maximise assembler code use
+ * between all exception types. Maybe 'true' interrupts should go
+ * here, and the trap code can come in separately
+ */
+void
+powerpc_interrupt(struct trapframe *framep)
+{
+ struct thread *td;
+ struct clockframe ckframe;
+
+ td = curthread;
+
+ switch (framep->exc) {
+ case EXC_EXI:
+ atomic_add_int(&td->td_intr_nesting_level, 1);
+ (*powerpc_extintr_handler)();
+ atomic_subtract_int(&td->td_intr_nesting_level, 1);
+ break;
+
+ case EXC_DECR:
+ atomic_add_int(&td->td_intr_nesting_level, 1);
+ ckframe.srr0 = framep->srr0;
+ ckframe.srr1 = framep->srr1;
+ decr_intr(&ckframe);
+ atomic_subtract_int(&td->td_intr_nesting_level, 1);
+ break;
+
+ default:
+ /*
+ * Re-enable interrupts and call the generic trap code
+ */
+#if 0
+ printf("powerpc_interrupt: got trap\n");
+#endif
+ mtmsr(mfmsr() | PSL_EE);
+ isync();
+ trap(framep);
+ }
+}
diff --git a/sys/powerpc/powerpc/locore.S b/sys/powerpc/powerpc/locore.S
index fa231e8..f8d0eb1 100644
--- a/sys/powerpc/powerpc/locore.S
+++ b/sys/powerpc/powerpc/locore.S
@@ -86,36 +86,6 @@ GLOBAL(proc0paddr)
.long 0 /* proc0 p_addr */
GLOBAL(PTmap)
.long 0 /* PTmap */
-GLOBAL(decrnest)
- .long 0
-
-GLOBAL(intrnames)
- .asciz "irq0", "irq1", "irq2", "irq3"
- .asciz "irq4", "irq5", "irq6", "irq7"
- .asciz "irq8", "irq9", "irq10", "irq11"
- .asciz "irq12", "irq13", "irq14", "irq15"
- .asciz "irq16", "irq17", "irq18", "irq19"
- .asciz "irq20", "irq21", "irq22", "irq23"
- .asciz "irq24", "irq25", "irq26", "irq27"
- .asciz "irq28", "irq29", "irq30", "irq31"
- .asciz "irq32", "irq33", "irq34", "irq35"
- .asciz "irq36", "irq37", "irq38", "irq39"
- .asciz "irq40", "irq41", "irq42", "irq43"
- .asciz "irq44", "irq45", "irq46", "irq47"
- .asciz "irq48", "irq49", "irq50", "irq51"
- .asciz "irq52", "irq53", "irq54", "irq55"
- .asciz "irq56", "irq57", "irq58", "irq59"
- .asciz "irq60", "irq61", "irq62", "irq63"
- .asciz "clock", "softclock", "softnet", "softserial"
-GLOBAL(eintrnames)
- .align 4
-GLOBAL(intrcnt)
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0
-GLOBAL(eintrcnt)
GLOBAL(ofmsr)
.long 0 /* msr used in Open Firmware */
diff --git a/sys/powerpc/powerpc/locore.s b/sys/powerpc/powerpc/locore.s
index fa231e8..f8d0eb1 100644
--- a/sys/powerpc/powerpc/locore.s
+++ b/sys/powerpc/powerpc/locore.s
@@ -86,36 +86,6 @@ GLOBAL(proc0paddr)
.long 0 /* proc0 p_addr */
GLOBAL(PTmap)
.long 0 /* PTmap */
-GLOBAL(decrnest)
- .long 0
-
-GLOBAL(intrnames)
- .asciz "irq0", "irq1", "irq2", "irq3"
- .asciz "irq4", "irq5", "irq6", "irq7"
- .asciz "irq8", "irq9", "irq10", "irq11"
- .asciz "irq12", "irq13", "irq14", "irq15"
- .asciz "irq16", "irq17", "irq18", "irq19"
- .asciz "irq20", "irq21", "irq22", "irq23"
- .asciz "irq24", "irq25", "irq26", "irq27"
- .asciz "irq28", "irq29", "irq30", "irq31"
- .asciz "irq32", "irq33", "irq34", "irq35"
- .asciz "irq36", "irq37", "irq38", "irq39"
- .asciz "irq40", "irq41", "irq42", "irq43"
- .asciz "irq44", "irq45", "irq46", "irq47"
- .asciz "irq48", "irq49", "irq50", "irq51"
- .asciz "irq52", "irq53", "irq54", "irq55"
- .asciz "irq56", "irq57", "irq58", "irq59"
- .asciz "irq60", "irq61", "irq62", "irq63"
- .asciz "clock", "softclock", "softnet", "softserial"
-GLOBAL(eintrnames)
- .align 4
-GLOBAL(intrcnt)
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .long 0,0,0,0
-GLOBAL(eintrcnt)
GLOBAL(ofmsr)
.long 0 /* msr used in Open Firmware */
diff --git a/sys/powerpc/powerpc/trap_subr.S b/sys/powerpc/powerpc/trap_subr.S
index 09b152b..0340d78 100644
--- a/sys/powerpc/powerpc/trap_subr.S
+++ b/sys/powerpc/powerpc/trap_subr.S
@@ -46,8 +46,6 @@
#define EXC_AST 0x3000
.data
.align 4
-astpending:
- .long 0
cpassert:
.asciz "attempting to return from kernel with no current pmap"
@@ -275,48 +273,6 @@ CNAME(isitrap601):
CNAME(isi601size)= .-CNAME(isitrap601)
/*
- * This one for the external interrupt handler.
- */
- .globl CNAME(extint),CNAME(extsize)
-CNAME(extint):
- mtsprg 1,1 /* save SP */
- stmw 28,tempsave(0) /* free r28-r31 */
- mflr 28 /* save LR */
- mfcr 29 /* save CR */
- mfxer 30 /* save XER */
- lis 1,intstk+INTSTK@ha /* get interrupt stack */
- addi 1,1,intstk+INTSTK@l /* this is really intr_depth! */
- lwz 31,0(1) /* were we already running on intstk? */
- addic. 31,31,1
- stw 31,0(1)
- beq 1f
- mfsprg 1,1 /* yes, get old SP */
-1:
- ba extintr
-CNAME(extsize) = .-CNAME(extint)
-
-/*
- * And this one for the decrementer interrupt handler.
- */
- .globl CNAME(decrint),CNAME(decrsize)
-CNAME(decrint):
- mtsprg 1,1 /* save SP */
- stmw 28,tempsave(0) /* free r28-r31 */
- mflr 28 /* save LR */
- mfcr 29 /* save CR */
- mfxer 30 /* save XER */
- lis 1,intstk+INTSTK@ha /* get interrupt stack */
- addi 1,1,intstk+INTSTK@l
- lwz 31,0(1) /* were we already running on intstk? */
- addic. 31,31,1
- stw 31,0(1)
- beq 1f
- mfsprg 1,1 /* yes, get old SP */
-1:
- ba decrintr
-CNAME(decrsize) = .-CNAME(decrint)
-
-/*
* Now the tlb software load for 603 processors:
* (Code essentially from the 603e User Manual, Chapter 5, but
* corrected a lot.)
@@ -579,7 +535,7 @@ CNAME(ipkdbsize) = .-CNAME(ipkdblow)
mfsrr1 31; \
stmw 30,savearea+24(0); \
mfmsr 30; \
- ori 30,30,(PSL_DR|PSL_IR); \
+ ori 30,30,(PSL_DR|PSL_IR)@l; \
mtmsr 30; \
isync; \
mfsprg 31,1; \
@@ -710,16 +666,20 @@ s_trap:
mtsr 7,31
FRAME_SETUP(tempsave)
/* Now we can recover interrupts again: */
+#if 0
mfmsr 7
ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l
mtmsr 7
isync
-/* Call C trap code: */
+#endif
+/* Call C interrupt dispatcher: */
trapagain:
addi 3,1,8
- bl CNAME(trap)
+ bl CNAME(powerpc_interrupt)
.globl CNAME(trapexit)
CNAME(trapexit):
+
+#if 0
/* Disable interrupts: */
mfmsr 3
andi. 3,3,~PSL_EE@l
@@ -728,14 +688,24 @@ CNAME(trapexit):
lwz 5,FRAME_SRR1+8(1)
mtcr 5
bc 4,17,1f /* branch if PSL_PR is false */
- lis 3,CNAME(astpending)@ha
- lwz 4,CNAME(astpending)@l(3)
- andi. 4,4,1
+
+ mfsprg 3, 0 /* get per-CPU pointer */
+ lwz 4, PC_CURTHREAD(3) /* deref to get curthread */
+ lwz 3, TD_KSE(4) /* deref to get current KSE */
+ lwz 4, KE_FLAGS(3) /* get KSE flags value */
+ andi. 4,4,KEF_ASTPENDING|KEF_NEEDRESCHED
beq 1f
- li 6,EXC_AST
+ li 6,EXC_AST /* update exception type */
stw 6,FRAME_EXC+8(1)
- b trapagain
+ mfmsr 3 /* re-enable interrupts */
+ ori 3,3,PSL_EE@l
+ mtmsr 3
+ isync
+ addi 3,1,8
+ bl CNAME(ast_test)
+ b trapexit /* test ast ret value ? */
1:
+#endif
FRAME_LEAVE(tempsave)
rfi
@@ -820,157 +790,6 @@ s_isitrap:
mfsrr0 3
b s_pte_spill /* above */
-/*
- * External interrupt second level handler
- */
-#define INTRENTER \
-/* Save non-volatile registers: */ \
- stwu 1,-IFRAMELEN(1); /* temporarily */ \
- stw 0,IFRAME_R0(1); \
- mfsprg 0,1; /* get original SP */ \
- stw 0,IFRAME_R1(1); /* and store it */ \
- stw 3,IFRAME_R3(1); \
- stw 4,IFRAME_R4(1); \
- stw 5,IFRAME_R5(1); \
- stw 6,IFRAME_R6(1); \
- stw 7,IFRAME_R7(1); \
- stw 8,IFRAME_R8(1); \
- stw 9,IFRAME_R9(1); \
- stw 10,IFRAME_R10(1); \
- stw 11,IFRAME_R11(1); \
- stw 12,IFRAME_R12(1); \
- stw 28,IFRAME_LR(1); /* saved LR */ \
- stw 29,IFRAME_CR(1); /* saved CR */ \
- stw 30,IFRAME_XER(1); /* saved XER */ \
- lmw 28,tempsave(0); /* restore r28-r31 */ \
- mfctr 6; \
- lis 5,CNAME(intr_depth)@ha; \
- lwz 5,CNAME(intr_depth)@l(5); \
- mfsrr0 4; \
- mfsrr1 3; \
- stw 6,IFRAME_CTR(1); \
- stw 5,IFRAME_INTR_DEPTH(1); \
- stw 4,IFRAME_SRR0(1); \
- stw 3,IFRAME_SRR1(1); \
- mtcr 3; \
- bc 4,17,99f; /* branch if PSL_PR is false */ \
- lis 3,EMPTY_SEGMENT@h; \
- ori 3,3,EMPTY_SEGMENT@l; \
- mtsr 0,3; /* reset SRs so BAT spills work */ \
- mtsr 1,3; \
- mtsr 2,3; \
- mtsr 3,3; \
- mtsr 4,3; \
- mtsr 5,3; \
- mtsr 6,3; \
- mtsr 7,3; \
-/* interrupts are recoverable here, and enable translation */ \
- lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \
- ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \
- mtsr KERNEL_SR,3; \
-99: mfmsr 5; \
- ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \
- mtmsr 5; \
- isync
-
- .globl CNAME(extint_call)
-extintr:
- INTRENTER
-CNAME(extint_call):
- bl CNAME(extint_call) /* to be filled in later */
-
-intr_exit:
-/* Disable interrupts (should already be disabled) and MMU here: */
- mfmsr 3
- andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l
- mtmsr 3
- isync
-/* restore possibly overwritten registers: */
- lwz 12,IFRAME_R12(1)
- lwz 11,IFRAME_R11(1)
- lwz 10,IFRAME_R10(1)
- lwz 9,IFRAME_R9(1)
- lwz 8,IFRAME_R8(1)
- lwz 7,IFRAME_R7(1)
- lwz 6,IFRAME_SRR1(1)
- lwz 5,IFRAME_SRR0(1)
- lwz 4,IFRAME_CTR(1)
- lwz 3,IFRAME_XER(1)
- mtsrr1 6
- mtsrr0 5
- mtctr 4
- mtxer 3
-/* Returning to user mode? */
- mtcr 6 /* saved SRR1 */
- bc 4,17,1f /* branch if PSL_PR is false */
- mfsprg 31,0
- lwz 3,PC_CURPMAP(31)
- lwz 4,PM_SR+0(3)
- mtsr 0,4 /* Restore SR0 */
- lwz 4,PM_SR+4(3)
- mtsr 1,4 /* Restore SR1 */
- lwz 4,PM_SR+8(3)
- mtsr 2,4 /* Restore SR2 */
- lwz 4,PM_SR+12(3)
- mtsr 3,4 /* Restore SR3 */
- lwz 4,PM_SR+16(3)
- mtsr 4,4 /* Restore SR4 */
- lwz 4,PM_SR+20(3)
- mtsr 5,4 /* Restore SR5 */
- lwz 4,PM_SR+24(3)
- mtsr 6,4 /* Restore SR6 */
- lwz 4,PM_SR+28(3)
- mtsr 7,4 /* Restore SR7 */
- lwz 3,PM_KERNELSR(3)
- mtsr KERNEL_SR,3 /* Restore kernel SR */
- lis 3,CNAME(astpending)@ha /* Test AST pending */
- lwz 4,CNAME(astpending)@l(3)
- andi. 4,4,1
- beq 1f
-/* Setup for entry to realtrap: */
- lwz 3,IFRAME_R1(1) /* get saved SP */
- mtsprg 1,3
- li 6,EXC_AST
- stmw 28,tempsave(0) /* establish tempsave again */
- mtlr 6
- lwz 28,IFRAME_LR(1) /* saved LR */
- lwz 29,IFRAME_CR(1) /* saved CR */
- lwz 6,IFRAME_R6(1)
- lwz 5,IFRAME_R5(1)
- lwz 4,IFRAME_R4(1)
- lwz 3,IFRAME_R3(1)
- lwz 0,IFRAME_R0(1)
- lis 30,CNAME(intr_depth)@ha /* adjust reentrancy count */
- lwz 31,CNAME(intr_depth)@l(30)
- addi 31,31,-1
- stw 31,CNAME(intr_depth)@l(30)
- b realtrap
-1:
-/* Here is the normal exit of extintr: */
- lwz 5,IFRAME_CR(1)
- lwz 6,IFRAME_LR(1)
- mtcr 5
- mtlr 6
- lwz 6,IFRAME_R6(1)
- lwz 5,IFRAME_R5(1)
- lis 3,CNAME(intr_depth)@ha /* adjust reentrancy count */
- lwz 4,CNAME(intr_depth)@l(3)
- addi 4,4,-1
- stw 4,CNAME(intr_depth)@l(3)
- lwz 4,IFRAME_R4(1)
- lwz 3,IFRAME_R3(1)
- lwz 0,IFRAME_R0(1)
- lwz 1,IFRAME_R1(1)
- rfi
-
-/*
- * Decrementer interrupt second level handler
- */
-decrintr:
- INTRENTER
- addi 3,1,8 /* intr frame -> clock frame */
- bl CNAME(decr_intr)
- b intr_exit
#if defined(DDB)
/*
OpenPOWER on IntegriCloud