Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 589 → Rev 590

/kernel/trunk/arch/mips32/src/exception.c
34,7 → 34,97
#include <arch.h>
#include <debug.h>
#include <proc/thread.h>
#include <symtab.h>
#include <print.h>
#include <interrupt.h>
 
static char * exctable[] = {
"Interrupt","TLB Modified","TLB Invalid","TLB Invalid Store",
"Address Error - load/instr. fetch",
"Address Error - store",
"Bus Error - fetch instruction",
"Bus Error - data reference",
"Syscall",
"BreakPoint",
"Reserved Instruction",
"Coprocessor Unusable",
"Arithmetic Overflow",
"Trap",
"Virtual Coherency - instruction",
"Floating Point",
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
"WatchHi/WatchLo", /* 23 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
"Virtual Coherency - data",
};
 
static void print_regdump(struct exception_regdump *pstate)
{
char *pcsymbol = "";
char *rasymbol = "";
 
char *s = get_symtab_entry(pstate->epc);
if (s)
pcsymbol = s;
s = get_symtab_entry(pstate->ra);
if (s)
rasymbol = s;
printf("PC: %X(%s) RA: %X(%s)\n",pstate->epc,pcsymbol,
pstate->ra,rasymbol);
}
 
static void unhandled_exception(int n, void *data)
{
struct exception_regdump *pstate = (struct exception_regdump *)data;
 
print_regdump(pstate);
panic("unhandled exception %s\n", exctable[n]);
}
 
static void breakpoint_exception(int n, void *data)
{
struct exception_regdump *pstate = (struct exception_regdump *)data;
/* it is necessary to not re-execute BREAK instruction after
returning from Exception handler
(see page 138 in R4000 Manual for more information) */
pstate->epc += 4;
}
 
static void tlbmod_exception(int n, void *data)
{
struct exception_regdump *pstate = (struct exception_regdump *)data;
tlb_modified(pstate);
}
 
static void tlbinv_exception(int n, void *data)
{
struct exception_regdump *pstate = (struct exception_regdump *)data;
tlb_invalid(pstate);
}
 
static void cpunsbl_exception(int n, void *data)
{
if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
scheduler_fpu_lazy_request();
else
panic("unhandled Coprocessor Unusable Exception\n");
}
 
static void interrupt_exception(int n, void *pstate)
{
__u32 cause;
int i;
/* decode interrupt number and process the interrupt */
cause = (cp0_cause_read() >> 8) &0xff;
for (i = 0; i < 8; i++)
if (cause & (1 << i))
exc_dispatch(i+INT_OFFSET, pstate);
}
 
 
void exception(struct exception_regdump *pstate)
{
int cause;
63,69 → 153,9
 
cause = cp0_cause_read();
excno = cp0_cause_excno(cause);
/* decode exception number and process the exception */
switch (excno) {
case EXC_Int:
interrupt(pstate);
break;
case EXC_TLBL:
case EXC_TLBS:
tlb_invalid(pstate);
break;
case EXC_CpU:
#ifdef CONFIG_FPU_LAZY
if (cp0_cause_coperr(cause) == fpu_cop_id)
scheduler_fpu_lazy_request();
else
#endif
panic("unhandled Coprocessor Unusable Exception\n");
break;
case EXC_Mod:
tlb_modified(pstate);
break;
case EXC_AdEL:
panic("unhandled Address Error Exception - load or instruction fetch\n");
break;
case EXC_AdES:
panic("unhandled Address Error Exception - store\n");
break;
case EXC_IBE:
panic("unhandled Bus Error Exception - fetch instruction\n");
break;
case EXC_DBE:
panic("unhandled Bus Error Exception - data reference: load or store\n");
break;
case EXC_Bp:
/* it is necessary to not re-execute BREAK instruction after returning from Exception handler
(see page 138 in R4000 Manual for more information) */
epc_shift = 4;
break;
case EXC_RI:
panic("unhandled Reserved Instruction Exception\n");
break;
case EXC_Ov:
panic("unhandled Arithmetic Overflow Exception\n");
break;
case EXC_Tr:
panic("unhandled Trap Exception\n");
break;
case EXC_VCEI:
panic("unhandled Virtual Coherency Exception - instruction\n");
break;
case EXC_FPE:
panic("unhandled Floating-Point Exception\n");
break;
case EXC_WATCH:
panic("unhandled reference to WatchHi/WatchLo address\n");
break;
case EXC_VCED:
panic("unhandled Virtual Coherency Exception - data\n");
break;
default:
panic("unhandled exception %d\n", excno);
}
pstate->epc += epc_shift;
/* Dispatch exception */
exc_dispatch(excno, pstate);
 
/* Set to NULL, so that we can still support nested
* exceptions
* TODO: We should probably set EXL bit before this command,
135,3 → 165,20
if (THREAD)
THREAD->pstate = NULL;
}
 
void exception_init(void)
{
int i;
 
/* Clear exception table */
for (i=0;i < IVT_ITEMS; i++)
exc_register(i, "undef", unhandled_exception);
exc_register(EXC_Bp, "bkpoint", breakpoint_exception);
exc_register(EXC_Mod, "tlb_mod", tlbmod_exception);
exc_register(EXC_TLBL, "tlbinvl", tlbinv_exception);
exc_register(EXC_TLBS, "tlbinvl", tlbinv_exception);
exc_register(EXC_Int, "interrupt", interrupt_exception);
#ifdef CONFIG_FPU_LAZY
exc_register(EXC_CpU, "cpunus", cpun_exception);
#endif
}