Subject: trap.c rework
To: None <port-mips@netbsd.org>
From: Toru Nishimura <nisimura@itc.aist-nara.ac.jp>
List: port-mips
Date: 03/31/2000 14:34:05
Hello, MIPS guys
I have a change proposal of MIPS common code for how interrupt service
is dispatched; to take interrupt() routine out of MIPS common trap.c.
Instead, routine provided by the target port is called straightly.
This change would eliminate complicate adjustments done in
<machine/intr.h>, and provide saner logics to use peculiar to target
hardware.
-- proposal --
Every MIPS port provides following interrupt service routine to be
called by MIPS common code.
void
cpu_intr(status, cause, pc, ipending)
u_int32_t status; /* STATUS */
u_int32_t cause; /* CAUSE */
u_int32_t pc; /* EPC */
u_int32_t ipending; /* CAUSE & STATUS */
And, <machine/intr.h> is expected to have as follows;
/*
* software simulated interrupt
*/
extern unsigned ssir;
#define SIR_NET 0x1
#define setsoftnet() setsoft(SIR_NET)
#define setsoft(x) \
do { ssir |= (x); _setsoftintr(MIPS_SOFT_INT_MASK_1); } while (0)
#define setsoftclock() _setsoftintr(MIPS_SOFT_INT_MASK_0)
Here go sample code fragments to show the impact of this proposal.
void
cobalt_intr(status, cause, pc, ipending)
u_int32_t status;
u_int32_t cause;
u_int32_t pc;
u_int32_t ipending;
{
struct clockframe cf;
static u_int32_t cycles;
int s;
uvmexp.intrs++;
/* XXX Reverse hardlock and statclock? */
#define TICK_CYCLES 1250000 /* XXX 250 MHz XXX */
if (ipending & MIPS_INT_MASK_5) {
cycles = mips3_cycle_count();
mips3_write_compare(cycles + TICK_CYCLES);
cf.pc = pc;
cf.sr = status;
s = splstatclock(); /* XXX redo interrupts XXX */
statclock(&cf);
splx(s); /* XXX redo interrupts XXX */
cause &= ~MIPS_INT_MASK_5;
}
if (ipending & MIPS_INT_MASK_4) {
iointr(ipending, &cf);
cause &= ~MIPS_INT_MASK_4;
}
if (ipending & MIPS_INT_MASK_3) {
s = spltty(); /* XXX redo interrupts XXX */
comintr(com0);
splx(s); /* XXX redo interrupts XXX */
cause &= ~MIPS_INT_MASK_3;
}
if (ipending & MIPS_INT_MASK_1) {
s = splnet(); /* XXX redo interrupts XXX */
tlp_intr(tlp0);
splx(s); /* XXX redo interrupts XXX */
cause &= ~MIPS_INT_MASK_1;
}
if (ipending & MIPS_INT_MASK_2) {
s = splnet(); /* XXX redo interrupts XXX */
tlp_intr(tlp1);
splx(s); /* XXX redo interrupts XXX */
cause &= ~MIPS_INT_MASK_1;
cause &= ~MIPS_INT_MASK_2;
}
if (ipending & MIPS_INT_MASK_0) {
volatile u_int32_t *irq_src =
(u_int32_t *)MIPS_PHYS_TO_KSEG1(0x14000c18);
if (*irq_src & 0x00000100) {
*irq_src = 0;
cf.pc = pc;
cf.sr = status;
s = splclock(); /* XXX redo interrupts XXX */
hardclock(&cf);
splx(s); /* XXX redo interrupts XXX */
}
cause &= ~MIPS_INT_MASK_0;
}
_splset ((status & ~cause & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
/* software simulated interrupt */
if ((ipending & MIPS_SOFT_INT_MASK_1)
|| (ssir && (status & MIPS_SOFT_INT_MASK_1))) {
#define DO_SIR(bit, fn) \
do { \
if (n & (bit)) { \
uvmexp.softs++; \
fn; \
} \
} while (0)
unsigned n;
n = ssir; ssir = 0;
_clrsoftintr(MIPS_SOFT_INT_MASK_1);
DO_SIR(SIR_NET, netintr());
#undef DO_SIR
}
/* 'softclock' interrupt */
if (ipending & MIPS_SOFT_INT_MASK_0) {
_clrsoftintr(MIPS_SOFT_INT_MASK_0);
uvmexp.softs++;
intrcnt[SOFTCLOCK_INTR]++;
softclock();
}
}
void
arc_intr(status, cause, pc, ipending)
u_int32_t status;
u_int32_t cause;
u_int32_t pc;
u_int32_t ipending;
{
struct clockframe cf;
static u_int32_t cycles;
int i;
uvmexp.intrs++;
#define TICK_CYCLES 0 /* ??? */
if (ipending & MIPS_INT_MASK_5) {
cycles = mips3_cycle_count();
mips3_write_compare(cycles + TICK_CYCLES);
}
cf.pc = pc;
cf.sr = status;
/*
* Check off all enabled interrupts. Called interrupt routine
* returns mask of interrupts to reenable.
*/
for (i = 0; i < MIPS_INT_LEVELS; i++) {
if (cpu_int_tab[i].int_mask & ipending) {
cause &= (*cpu_int_tab[i].int_hand)(ipending, &cf);
}
}
_splset((status & ~cause & MIPS3_HARD_INT_MASK) | MIPS_SR_INT_IE);
/* software simulated interrupt */
if (ipending & MIPS_SOFT_INT_MASK_1)
|| (ssir && (status & MIPS_SOFT_INT_MASK_1))) {
#define DO_SIR(bit, fn) \
do { \
if (n & (bit)) { \
uvmexp.softs++; \
fn; \
} \
} while (0)
unsigned n;
n = ssir; ssir = 0;
_clrsoftintr(MIPS_SOFT_INT_MASK_1);
DO_SIR(SIR_NET, netintr());
#undef DO_SIR
}
/* 'softclock' interrupt */
if (ipending & MIPS_SOFT_INT_MASK_0) {
_clrsoftintr(MIPS_SOFT_INT_MASK_0);
uvmexp.softs++;
intrcnt[SOFTCLOCK_INTR]++;
softclock();
}
}
void
newsmips_intr(pc, status, cause, ipending)
u_int32_t status;
u_int32_t cause;
u_int32_t pc;
u_int32_t ipending;
{
#define INT_MASK_DEV (MIPS_HARD_INT_MASK &~ MIPS_INT_MASK_3)
#define INT_MASK_FPU MIPS_INT_MASK_3
uvmexp.intrs++;
/* device interrupts */
if (ipending & INT_MASK_DEV) {
(*platform.iointr)(status, cause, pc, ipending);
}
/* FPU nofiticaition */
if (ipending & INT_MASK_FPU) {
if (!USERMODE(status))
goto kerneltouchedFPU;
intrcnt[FPU_INTR]++;
/* dealfpu(status, cause, pc); */
MachFPInterrupt(status, cause, pc, curproc->p_md.md_regs);
}
/* software simulated interrupt */
if (ipending & MIPS_SOFT_INT_MASK_1)
|| (ssir && (status & MIPS_SOFT_INT_MASK_1))) {
#define DO_SIR(bit, fn) \
do { \
if (n & (bit)) { \
uvmexp.softs++; \
fn; \
} \
} while (0)
unsigned n;
n = ssir; ssir = 0;
_clrsoftintr(MIPS_SOFT_INT_MASK_1);
DO_SIR(SIR_NET, netintr());
#undef DO_SIR
}
/* 'softclock' interrupt */
if (ipending & MIPS_SOFT_INT_MASK_0) {
_clrsoftintr(MIPS_SOFT_INT_MASK_0);
uvmexp.softs++;
intrcnt[SOFTCLOCK_INTR]++;
softclock();
}
}
void
pmax_intr(status, cause, pc, ipending)
u_int32_t status;
u_int32_t cause;
u_int32_t pc;
u_int32_t ipending;
{
#define INT_MASK_DEV (MIPS_HARD_INT_MASK &~ MIPS_INT_MASK_5)
#define INT_MASK_FPU MIPS_INT_MASK_5
uvmexp.intrs++;
/* device interrupts */
if (ipending & INT_MASK_DEV) {
(*platform.iointr)(status, cause, pc, ipending);
}
/* FPU nofiticaition */
if (ipending & INT_MASK_FPU) {
if (!USERMODE(status))
goto kerneltouchedFPU;
intrcnt[FPU_INTR]++;
/* dealfpu(status, cause, pc); */
MachFPInterrupt(status, cause, pc, curproc->p_md.md_regs);
}
/* software simulated interrupt */
if ((ipending & MIPS_SOFT_INT_MASK_1)
|| (ssir && (status & MIPS_SOFT_INT_MASK_1))) {
#define DO_SIR(bit, fn) \
do { \
if (n & (bit)) { \
uvmexp.softs++; \
fn; \
} \
} while (0)
unsigned n;
n = ssir; ssir = 0;
_clrsoftintr(MIPS_SOFT_INT_MASK_1);
DO_SIR(SIR_NET, netintr());
#undef DO_SIR
}
/* 'softclock' interrupt */
if (ipending & MIPS_SOFT_INT_MASK_0) {
_clrsoftintr(MIPS_SOFT_INT_MASK_0);
uvmexp.softs++;
intrcnt[SOFTCLOCK_INTR]++;
softclock();
}
return;
kerneltouchedFPU:
panic("kernel used FPU: PC %x, CR %x, SR %x", pc, cause, status);
}
void
hpcmips_intr(status, cause, pc, ipending)
u_int32_t status;
u_int32_t cause;
u_int32_t pc;
u_int32_t ipending;
{
uvmexp.intrs++;
/* device interrupts */
(*platform.iointr)(status, cause, pc, ipending);
/* software simulated interrupt */
if ((ipending & MIPS_SOFT_INT_MASK_1)
|| (ssir && (status & MIPS_SOFT_INT_MASK_1))) {
#define DO_SIR(bit, fn) \
do { \
if (n & (bit)) { \
uvmexp.softs++; \
fn; \
} \
} while (0)
unsigned n;
n = ssir; ssir = 0;
_clrsoftintr(MIPS_SOFT_INT_MASK_1);
DO_SIR(SIR_NET, netintr());
#undef DO_SIR
}
/* 'softclock' interrupt */
if (ipending & MIPS_SOFT_INT_MASK_0) {
_clrsoftintr(MIPS_SOFT_INT_MASK_0);
uvmexp.softs++;
intrcnt[SOFTCLOCK_INTR]++;
softclock();
}
return;
}
--