summaryrefslogtreecommitdiff
path: root/os/js/trap.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /os/js/trap.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/js/trap.c')
-rw-r--r--os/js/trap.c472
1 files changed, 472 insertions, 0 deletions
diff --git a/os/js/trap.c b/os/js/trap.c
new file mode 100644
index 00000000..b9117bfe
--- /dev/null
+++ b/os/js/trap.c
@@ -0,0 +1,472 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "ureg.h"
+#include "io.h"
+#include "../port/error.h"
+
+void noted(Ureg**, ulong);
+void rfnote(Ureg**);
+int domuldiv(ulong, Ureg*);
+
+extern Label catch;
+extern void traplink(void);
+extern void syslink(void);
+static void faultsparc(Ureg *ur);
+static void faultasync(Ureg *ur);
+
+ long ticks;
+static char excbuf[64]; /* BUG: not reentrant! */
+
+char *trapname[]={
+ "reset",
+ "instruction access exception",
+ "illegal instruction",
+ "privileged instruction",
+ "fp: disabled",
+ "window overflow",
+ "window underflow",
+ "unaligned address",
+ "fp: exception",
+ "data access exception",
+ "tag overflow",
+ "watchpoint detected",
+};
+
+char *fptrapname[]={
+ "none",
+ "IEEE 754 exception",
+ "unfinished FP op",
+ "unimplemented FP op",
+ "sequence error",
+ "hardware error",
+ "invalid FP register",
+ "reserved",
+}
+;
+
+char*
+excname(ulong tbr)
+{
+ char xx[64];
+ char *t;
+
+ switch(tbr){
+ case 8:
+ if(up == 0)
+ panic("fptrap in kernel\n");
+ else{
+panic("fptrap not implemented\n");
+#ifdef notdef
+ if(m->fpunsafe==0 && up->p->fpstate!=FPactive)
+ panic("fptrap not active\n"); fsr = up->fpsave.env;
+ sprint(excbuf, "fp: %s fppc=0x%lux",
+ fptrapname[(fsr>>14)&7],
+ up->fpsave.q[0].a, fsr);
+#endif
+ }
+ return excbuf;
+ case 36:
+ return "trap: cp disabled";
+ case 37:
+ return "trap: unimplemented instruction";
+ case 40:
+ return "trap: cp exception";
+ case 42:
+ return "trap: divide by zero";
+ case 128:
+ return "syscall";
+ case 129:
+ return "breakpoint";
+ }
+ t = 0;
+ if(tbr < sizeof trapname/sizeof(char*))
+ t = trapname[tbr];
+ if(t == 0){
+ if(tbr >= 130)
+ sprint(xx, "trap instruction %ld", tbr-128);
+ else if(17<=tbr && tbr<=31)
+ sprint(xx, "interrupt level %ld", tbr-16);
+ else
+ sprint(xx, "unknown trap %ld", tbr);
+ t = xx;
+ }
+ if(strncmp(t, "fp: ", 4) == 0)
+ strcpy(excbuf, t);
+ else
+ sprint(excbuf, "trap: %s", t);
+ return excbuf;
+
+}
+
+void
+trap(Ureg *ur)
+{
+ int user;
+ ulong tbr, iw;
+
+ tbr = (ur->tbr&0xFFF)>>4;
+ /*
+ * Hack to catch bootstrap fault during probe
+ */
+ if(catch.pc)
+ gotolabel(&catch);
+
+ if(up)
+ up->dbgreg = ur;
+
+ user = !(ur->psr&PSRPSUPER);
+ if(user) {
+ panic("how did we get to user mode???");
+ }
+ if(tbr > 16){ /* interrupt */
+ switch(tbr-16) {
+ case 15: /* asynch mem err */
+ faultasync(ur);
+ break;
+ case 14: /* processor counter */
+ clock(ur);
+ break;
+ case 13: /* keyboard/mouse */
+ ns16552intr(0);
+ kbdintr();
+ break;
+ case 6: /* lance */
+ lanceintr();
+ break;
+ default:
+ print("unexp intr lev %ld\n", tbr-16);
+ goto Error;
+ }
+ }else{
+ switch(tbr){
+ case 1: /* instr. access */
+ case 9: /* data access */
+ if(up && up->fpstate==FPACTIVE) {
+ fpquiet();
+ fpsave(&up->fpsave);
+ up->fpstate = FPINACTIVE;
+ }
+ faultsparc(ur);
+ goto Return;
+ case 2: /* illegal instr, maybe mul */
+ iw = *(ulong*)ur->pc;
+ if((iw&0xC1500000) == 0x80500000){
+ if(domuldiv(iw, ur))
+ goto Return;
+ tbr = ur->tbr;
+ }
+ break;
+ case 4: /* floating point disabled */
+panic("some more floating point crapola");
+break;
+#ifdef notdef
+ if(u && u->p){
+ if(up->p->fpstate == FPINIT)
+ restfpregs(initfpp, up->fpsave.fsr);
+ else if(u->p->fpstate == FPinactive)
+ restfpregs(&u->fpsave, u->fpsave.fsr);
+ else
+ break;
+ u->p->fpstate = FPactive;
+ ur->psr |= PSREF;
+ return;
+ }
+ break;
+#endif
+ case 8: /* floating point exception */
+panic("floating point crapola #3");
+break;
+#ifdef notdef
+ /* if unsafe, trap happened shutting down FPU; just return */
+ if(m->fpunsafe){
+ m->fptrap = (fptrap()==0);
+ return;
+ }
+ if(fptrap())
+ goto Return; /* handled the problem */
+ break;
+#endif
+ default:
+ break;
+ }
+ Error:
+ panic("kernel trap: %s pc=0x%lux\n", excname(tbr), ur->pc);
+ }
+ Return:
+ return;
+}
+
+void
+trapinit(void)
+{
+ int i;
+ long t, a;
+
+ a = ((ulong)traplink-TRAPS)>>2;
+ a += 0x40000000; /* CALL traplink(SB) */
+ t = TRAPS;
+ for(i=0; i<256; i++){
+ *(ulong*)(t+0) = a; /* CALL traplink(SB) */
+ *(ulong*)(t+4) = 0xa7480000; /* MOVW PSR, R19 */
+ a -= 16/4;
+ t += 16;
+ }
+
+#ifdef notdef
+ flushpage(TRAPS);
+#else
+ flushicache();
+#endif
+
+ puttbr(TRAPS);
+ setpsr(getpsr()|PSRET|SPL(15)); /* enable traps, not interrupts */
+}
+
+void
+mulu(ulong u1, ulong u2, ulong *lop, ulong *hip)
+{
+ ulong lo1, lo2, hi1, hi2, lo, hi, t1, t2, t;
+
+ lo1 = u1 & 0xffff;
+ lo2 = u2 & 0xffff;
+ hi1 = u1 >> 16;
+ hi2 = u2 >> 16;
+
+ lo = lo1 * lo2;
+ t1 = lo1 * hi2;
+ t2 = lo2 * hi1;
+ hi = hi1 * hi2;
+ t = lo;
+ lo += t1 << 16;
+ if(lo < t)
+ hi++;
+ t = lo;
+ lo += t2 << 16;
+ if(lo < t)
+ hi++;
+ hi += (t1 >> 16) + (t2 >> 16);
+ *lop = lo;
+ *hip = hi;
+}
+
+void
+muls(long l1, long l2, long *lop, long *hip)
+{
+ ulong t, lo, hi;
+ ulong mlo, mhi;
+ int sign;
+
+ sign = 0;
+ if(l1 < 0){
+ sign ^= 1;
+ l1 = -l1;
+ }
+ if(l2 < 0){
+ sign ^= 1;
+ l2 = -l2;
+ }
+ mulu(l1, l2, &mlo, &mhi);
+ lo = mlo;
+ hi = mhi;
+ if(sign){
+ t = lo = ~lo;
+ hi = ~hi;
+ lo++;
+ if(lo < t)
+ hi++;
+ }
+ *lop = lo;
+ *hip = hi;
+}
+
+int
+domuldiv(ulong iw, Ureg *ur)
+{
+ long op1, op2;
+ long *regp;
+ long *regs;
+
+ regs = (long*)ur;
+ if(iw & (1<<13)){ /* signed immediate */
+ op2 = iw & 0x1FFF;
+ if(op2 & 0x1000)
+ op2 |= ~0x1FFF;
+ }else
+ op2 = regs[iw&0x1F];
+ op1 = regs[(iw>>14)&0x1F];
+ regp = &regs[(iw>>25)&0x1F];
+
+ if(iw & (4<<19)){ /* divide */
+ if(ur->y!=0 && ur->y!=~0){
+ unimp:
+ ur->tbr = 37; /* "unimplemented instruction" */
+ return 0; /* complex Y is too hard */
+ }
+ if(op2 == 0){
+ ur->tbr = 42; /* "zero divide" */
+ return 0;
+ }
+ if(iw & (1<<19)){
+ if(ur->y && (op1&(1<<31))==0)
+ goto unimp; /* Y not sign extension */
+ *regp = op1 / op2;
+ }else{
+ if(ur->y)
+ goto unimp;
+ *regp = (ulong)op1 / (ulong)op2;
+ }
+ }else{
+ if(iw & (1<<19))
+ muls(op1, op2, regp, (long*)&ur->y);
+ else
+ mulu(op1, op2, (ulong*)regp, &ur->y);
+ }
+ if(iw & (16<<19)){ /* set CC */
+ ur->psr &= ~(0xF << 20);
+ if(*regp & (1<<31))
+ ur->psr |= 8 << 20; /* N */
+ if(*regp == 0)
+ ur->psr |= 4 << 20; /* Z */
+ /* BUG: don't get overflow right on divide */
+ }
+ ur->pc += 4;
+ ur->npc = ur->pc+4;
+ return 1;
+}
+
+void
+dumpregs(Ureg *ur)
+{
+ int i;
+ ulong *l;
+
+ if(up) {
+ print("registers for %s %ld\n",up->text,up->pid);
+ if(ur->usp < (ulong)up->kstack ||
+ ur->usp > (ulong)up->kstack+KSTACK-8)
+ print("invalid stack pointer\n");
+ } else
+ print("registers for kernel\n");
+
+ print("PSR=%lux PC=%lux TBR=%lux\n", ur->psr, ur->pc, ur->tbr);
+ l = &ur->r0;
+ for(i=0; i<32; i+=2, l+=2)
+ print("R%d\t%.8lux\tR%d\t%.8lux\n", i, l[0], i+1, l[1]);
+}
+
+
+/* This routine must save the values of registers the user is not permitted to
+ * write from devproc and the restore the saved values before returning
+ */
+void
+setregisters(Ureg *xp, char *pureg, char *uva, int n)
+{
+ ulong psr;
+
+ psr = xp->psr;
+ memmove(pureg, uva, n);
+ xp->psr = psr;
+}
+
+void
+dumpstack(void)
+{
+}
+
+/*
+ * Must only be called splhi() when it is safe to spllo(). Because the FP unit
+ * traps if you touch it when an exception is pending, and because if you
+ * trap with ET==0 you halt, this routine sets some global flags to enable
+ * the rest of the system to handle the trap that might occur here without
+ * upsetting the kernel. Shouldn't be necessary, but safety first.
+ */
+int
+fpquiet(void)
+{
+ int i, notrap;
+ ulong fsr;
+ char buf[128];
+
+ i = 0;
+ notrap = 1;
+ up->fpstate = FPINACTIVE;
+ for(;;){
+ m->fptrap = 0;
+ fsr = getfsr();
+ if(m->fptrap){
+ /* trap occurred and up->fpsave contains state */
+ sprint(buf, "sys: %s", excname(8));
+#ifdef notdef
+ postnote(u->p, 1, buf, NDebug);
+#else
+ panic(buf);
+#endif
+ notrap = 0;
+ break;
+ }
+ if((fsr&(1<<13)) == 0)
+ break;
+ if(++i > 1000){
+ print("fp not quiescent\n");
+ break;
+ }
+ }
+ up->fpstate = FPACTIVE;
+ return notrap;
+}
+
+enum
+{
+ SE_WRITE = 4<<5,
+ SE_PROT = 2<<2,
+};
+
+static void
+faultsparc(Ureg *ur)
+{
+ ulong addr;
+ char buf[ERRMAX];
+ int read;
+ ulong tbr, ser;
+
+ tbr = (ur->tbr&0xFFF)>>4;
+ addr = ur->pc; /* assume instr. exception */
+ read = 1;
+ if(tbr == 9){ /* data access exception */
+ addr = getrmmu(SFAR);
+ ser = getrmmu(SFSR);
+ if(ser&(SE_WRITE)) /* is SE_PROT needed? */
+ read = 0;
+ }
+
+ up->dbgreg = ur; /* for remote acid */
+ spllo();
+ sprint(buf, "sys: trap: fault %s addr=0x%lux",
+ read? "read" : "write", addr);
+
+ if(up->type == Interp)
+ disfault(ur,buf);
+ dumpregs(ur);
+ panic("fault: %s", buf);
+}
+
+static void
+faultasync(Ureg *ur)
+{
+ int user;
+
+ print("interrupt 15 AFSR %lux AFAR %lux MFSR %lux MFAR %lux\n",
+ getphys(AFSR), getphys(AFAR), getphys(MFSR), getphys(MFAR));
+ dumpregs(ur);
+ /*
+ * Clear interrupt
+ */
+ putphys(PROCINTCLR, 1<<15);
+ user = !(ur->psr&PSRPSUPER);
+ if(user)
+ pexit("Suicide", 0);
+ panic("interrupt 15");
+}