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>
This commit is contained in:
parent
0c079d8c6f
commit
6c2a062580
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
123
sys/powerpc/aim/interrupt.c
Normal file
123
sys/powerpc/aim/interrupt.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
||||
@ -274,48 +272,6 @@ CNAME(isitrap601):
|
||||
bla s_isitrap
|
||||
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
|
||||
@ -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)
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
123
sys/powerpc/powerpc/interrupt.c
Normal file
123
sys/powerpc/powerpc/interrupt.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
||||
@ -274,48 +272,6 @@ CNAME(isitrap601):
|
||||
bla s_isitrap
|
||||
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
|
||||
@ -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)
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user