From dbced7d071fa7b8d606d09d934700802eaa09c88 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 29 Nov 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-11-29 --- power/dat.h | 4 + power/debugger.c | 1 + power/fns.h | 2 +- power/fptrap.c | 37 ++++++---- power/l.s | 11 ++- power/trap.c | 188 ++++++++++++++++++++--------------------------- 6 files changed, 116 insertions(+), 127 deletions(-) diff --git a/power/dat.h b/power/dat.h index 36eec58d9a7fec588ccb388cef63be0b2cbf9592..21518b8ecc63509c1ed551629cd40fa466c23049 100644 --- a/power/dat.h +++ b/power/dat.h @@ -109,6 +109,10 @@ struct Mach int load; int intr; int ledval; /* value last written to LED */ +ulong cause; +ulong status; +ulong ur; +ulong sp; int stack[1]; }; diff --git a/power/debugger.c b/power/debugger.c index 7e5331b68ba264aa4e44ebc0585a4debf76a445e..175099c58ad99c203e7be108ca03aef08f19d707 100644 --- a/power/debugger.c +++ b/power/debugger.c @@ -143,6 +143,7 @@ printinfo(void) l = (ulong)(mp->proc); dprint("mach[%d]->proc/ %lux\r\n", i, l); dprint("mach[%d]->splpc/ %lux\r\n", i, mp->splpc); + if(l & KZERO){ p = (Proc*)l; l = (ulong)(p->upage); diff --git a/power/fns.h b/power/fns.h index 7627e6859965a5eaeb2542fabcf8afb8aa6756e3..34d0b354548a3dfc13ae382cac55fb6b187f5aac 100644 --- a/power/fns.h +++ b/power/fns.h @@ -24,7 +24,7 @@ ulong fcr31(void); void firmware(int); void flushmmu(void); #define flushpage(s) icflush((void*)(s), BY2PG) -int fptrap(Ureg*, ulong); +void fptrap(Ureg*); void gettlb(int, ulong*); ulong gettlbvirt(int); void gotopc(ulong); diff --git a/power/fptrap.c b/power/fptrap.c index a95fa6a232d23fff226989688e06e9ea6b90bfe4..755f03326327515d8b9a4f3fa3e5fd7a4a55976f 100644 --- a/power/fptrap.c +++ b/power/fptrap.c @@ -24,30 +24,32 @@ enum /* op */ static int fpunimp(ulong); static ulong branch(Ureg*, ulong); -int -fptrap(Ureg *ur, ulong fcr31) +void +fptrap(Ureg *ur) { ulong iw, npc; - if((fcr31&(1<<17)) == 0) - return 0; + if((u->fpsave.fpstatus&(1<<17)) == 0) + return; + if(ur->cause & (1<<31)) iw = *(ulong*)(ur->pc+4); else iw = *(ulong*)ur->pc; - if(fpunimp(iw)){ - if(ur->cause & (1<<31)){ - npc = branch(ur, fcr31); - if(npc) - ur->pc = npc; - else - return 0; - }else - ur->pc += 4; - u->fpsave.fpstatus = fcr31 & ~(1<<17); - return 1; + + if(fpunimp(iw) == 0) + return; + + if(ur->cause & (1<<31)){ + npc = branch(ur, u->fpsave.fpstatus); + if(npc == 0) + return; + ur->pc = npc; } - return 0; + else + ur->pc += 4; + + u->fpsave.fpstatus = u->fpsave.fpstatus & ~(1<<17); } static void @@ -56,6 +58,7 @@ unpack(FPsave *f, int fmt, int reg, int *sign, int *exp) *sign = 1; if(f->fpreg[reg] & 0x80000000) *sign = -1; + switch(fmt){ case 0: *exp = ((f->fpreg[reg]>>23)&0xFF) - ((1<<7)-2); @@ -162,6 +165,8 @@ fpunimp(ulong iw) } if(ed <= -(maxe-4)){ /* guess: underflow */ zeroreg(&u->fpsave, fmt, fd, sd); + /* Set underflow exception and sticky */ + u->fpsave.fpstatus |= (1<<3)|(1<<13); return 1; } return 0; diff --git a/power/l.s b/power/l.s index 530f7b6e448f3c17dea15ed77d93436494f46e01..d4e2b298232bc73efcbd6e887e80b1b896f71f00 100644 --- a/power/l.s +++ b/power/l.s @@ -350,7 +350,7 @@ wasuser: SUBU $(UREGADDR-2*BY2WD-USERADDR), SP, R(USER) MOVW $MPID, R1 MOVB 3(R1), R1 - MOVW $MACHADDR, R(MACH) /* locn of mach 0 */ + MOVW $MACHADDR, R(MACH) /* locn of &mach[0] */ AND $7, R1 SLL $PGSHIFT, R1 ADDU R1, R(MACH) /* add offset for mach # */ @@ -488,10 +488,19 @@ TEXT rfnote(SB), $0 JMP restore TEXT clrfpintr(SB), $0 + + MOVW M(STATUS), R3 + OR $CU1, R3 + MOVW R3, M(STATUS) + WAIT + MOVW FCR31, R1 MOVW R1, R2 AND $~(0x3F<<12), R2 MOVW R2, FCR31 + + AND $~CU1, R3 + MOVW R3, M(STATUS) RET TEXT savefpregs(SB), $0 diff --git a/power/trap.c b/power/trap.c index e98cc86c7a8d02bbccebc6b2bbaa87bf333bf3dd..d9c39fdadd87b512a6403bcb998d9b6a09b513d6 100644 --- a/power/trap.c +++ b/power/trap.c @@ -7,23 +7,10 @@ #include "io.h" #include "../port/error.h" -/* - * vme interrupt routines - */ void (*vmevec[256])(int); - void noted(Ureg**, ulong); void rfnote(Ureg**); -#define LSYS 0x01 -#define LUSER 0x02 -/* - * CAUSE register - */ - -#define EXCCODE(c) ((c>>2)&0x0F) -#define FPEXC 16 - char *excname[] = { "trap: external interrupt", @@ -42,10 +29,18 @@ char *excname[] = "trap: undefined 13", "trap: undefined 14", "trap: undefined 15", /* used as sys call for debugger */ - /* the following is made up */ - "trap: floating point exception" /* FPEXC */ +}; + +char *fpcause[] = +{ + "inexact operation", + "underflow", + "overflow", + "division by zero", + "invalid operation", }; char *fpexcname(Ureg*, ulong, char*); +#define FPEXPMASK (0x3f<<12) /* Floating exception bits in fcr31 */ char *regname[]={ "STATUS", "PC", @@ -69,91 +64,65 @@ char *regname[]={ "R2", "R1", }; -long ticks; - void trap(Ureg *ur) { int ecode; - int user, cop, x; ulong fcr31; + int user, cop, x, fpchk; char buf[2*ERRLEN], buf1[ERRLEN], *fpexcep; -*LED=~1; - ecode = EXCCODE(ur->cause); - LEDON(ecode); + + ecode = (ur->cause>>2)&0xf; user = ur->status&KUP; - if(u) + if(user) u->dbgreg = ur; -*LED=~2; + fpchk = 0; if(u && u->p->fpstate == FPactive) { - savefpregs(&u->fpsave); + if((ur->status&CU1) == 0) /* Paranoid */ + panic("FPactive but no CU1"); u->p->fpstate = FPinactive; ur->status &= ~CU1; + savefpregs(&u->fpsave); + fptrap(ur); + fpchk = 1; } -*LED=~3; switch(ecode){ case CINT: -*LED=~4; if(ur->cause&INTR3) { /* FP trap */ -*LED=~5; - if(u == 0 || u->p->fpstate != FPinactive) - panic("fp intr3 no u or not inactive pc=%lux", ur->pc); - - fcr31 = clrfpintr(); - if(user == 0) - panic("kernel floating point trap pc=%lux", ur->pc); -*LED=~6; - + clrfpintr(); ur->cause &= ~INTR3; - if(!fptrap(ur, fcr31)) { - intr(ur); - spllo(); - fpexcep = fpexcname(ur, fcr31, buf1); - sprint(buf, "sys: fp: %s", fpexcep); - postnote(u->p, 1, buf, NDebug); - break; - } -*LED=~7; } intr(ur); -*LED=~8; break; case CTLBM: case CTLBL: case CTLBS: -*LED=~9; if(u == 0) panic("fault u==0 pc %lux addr %lux", ur->pc, ur->badvaddr); -*LED=~10; + spllo(); x = u->p->insyscall; u->p->insyscall = 1; faultmips(ur, user, ecode); u->p->insyscall = x; -*LED=~11; break; case CCPU: -*LED=~12; cop = (ur->cause>>28)&3; - if(u && cop == 1) { + if(user && u && cop == 1) { if(u->p->fpstate == FPinit) { - restfpregs(&initfp, u->fpsave.fpstatus); - u->p->fpstate = FPactive; - ur->status |= CU1; + u->p->fpstate = FPinactive; + fcr31 = u->fpsave.fpstatus; + u->fpsave = initfp; + u->fpsave.fpstatus = fcr31; break; } - if(u->p->fpstate == FPinactive) { - restfpregs(&u->fpsave, u->fpsave.fpstatus); - u->p->fpstate = FPactive; - ur->status |= CU1; + if(u->p->fpstate == FPinactive) break; - } } -*LED=~13; /* Fallthrough */ default: @@ -170,22 +139,27 @@ trap(Ureg *ur) spllo(); exit(1); } -*LED=~14; - splhi(); - if(user) { -*LED=~15; - notify(ur); -*LED=~16; - if(u->p->fpstate == FPinactive) { - restfpregs(&u->fpsave, u->fpsave.fpstatus); - u->p->fpstate = FPactive; - ur->status |= CU1; + if(fpchk) { + fcr31 = u->fpsave.fpstatus; + if((fcr31>>12) & ((fcr31>>7)|0x20) & 0x3f) { + spllo(); + fpexcep = fpexcname(ur, fcr31, buf1); + sprint(buf, "sys: fp: %s", fpexcep); + postnote(u->p, 1, buf, NDebug); } -*LED=~17; } -*LED=~0; - LEDOFF(ecode); + + splhi(); + if(!user) + return; + + notify(ur); + if(u->p->fpstate == FPinactive) { + restfpregs(&u->fpsave, u->fpsave.fpstatus&~FPEXPMASK); + u->p->fpstate = FPactive; + ur->status |= CU1; + } } void @@ -320,7 +294,7 @@ intr(Ureg *ur) cause &= ~INTR5; } - if(cause & (INTR2|INTR4)){ + if(cause & (INTR2|INTR4)) { LEDON(LEDclock); clock(ur); LEDOFF(LEDclock); @@ -334,13 +308,6 @@ intr(Ureg *ur) char* fpexcname(Ureg *ur, ulong fcr31, char *buf) { - static char *str[]={ - "inexact operation", - "underflow", - "overflow", - "division by zero", - "invalid operation", - }; int i; char *s; ulong fppc; @@ -356,10 +323,11 @@ fpexcname(Ureg *ur, ulong fcr31, char *buf) fcr31 &= (fcr31>>5); /* anded with exceptions */ for(i=0; i<5; i++) if(fcr31 & (1<p->text, u->p->pid); else print("registers for kernel\n"); + l = &ur->status; for(i=0; ip->procctl) @@ -412,11 +380,11 @@ notify(Ureg *ur) if(u->nnote == 0) return 0; - s = spllo(); + spllo(); qlock(&u->p->debug); u->p->notepending = 0; n = &u->note[0]; - if(strncmp(n->msg, "sys:", 4) == 0){ + if(strncmp(n->msg, "sys:", 4) == 0) { l = strlen(n->msg); if(l > ERRLEN-15) /* " pc=0x12345678\0" */ l = ERRLEN-15; @@ -424,7 +392,7 @@ notify(Ureg *ur) sprint(n->msg+l, " pc=0x%lux", ur->pc); } - if(n->flag!=NUser && (u->notified || u->notify==0)){ + if(n->flag != NUser && (u->notified || u->notify==0)) { if(n->flag == NDebug) pprint("suicide: %s\n", n->msg); @@ -434,7 +402,7 @@ notify(Ureg *ur) if(u->notified) { qunlock(&u->p->debug); - splx(s); + splhi(); return 0; } @@ -443,15 +411,15 @@ notify(Ureg *ur) pexit(n->msg, n->flag!=NDebug); } u->svstatus = ur->status; - sp = ur->usp; - sp -= sizeof(Ureg); + sp = ur->usp - sizeof(Ureg); - if(sp&0x3 || !okaddr((ulong)u->notify, 1, 0) - || !okaddr(sp-ERRLEN-3*BY2WD, sizeof(Ureg)+ERRLEN-3*BY2WD, 0)){ + if(sp&0x3 || !okaddr((ulong)u->notify, BY2WD, 0) + || !okaddr(sp-ERRLEN-3*BY2WD, sizeof(Ureg)+ERRLEN-3*BY2WD, 1)) { pprint("suicide: bad address or sp in notify\n"); qunlock(&u->p->debug); pexit("Suicide", 0); } + u->ureg = (void*)sp; memmove((Ureg*)sp, ur, sizeof(Ureg)); sp -= ERRLEN; @@ -469,7 +437,7 @@ notify(Ureg *ur) memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note)); qunlock(&u->p->debug); - splx(s); + splhi(); return 1; } @@ -482,32 +450,30 @@ noted(Ureg **urp, ulong arg0) Ureg *nur; nur = u->ureg; - if(nur->status!=u->svstatus){ + if(nur->status!=u->svstatus) { pprint("bad noted ureg status %lux\n", nur->status); - Die: pexit("Suicide", 0); } qlock(&u->p->debug); - if(!u->notified){ + if(!u->notified) { qunlock(&u->p->debug); pprint("call to noted() when not notified\n"); - goto Die; + pexit("Suicide", 0); } u->notified = 0; memmove(*urp, u->ureg, sizeof(Ureg)); (*urp)->r1 = u->svr1; - switch(arg0){ + switch(arg0) { case NCONT: if(!okaddr(nur->pc, 1, 0) || !okaddr(nur->usp, BY2WD, 0)){ pprint("suicide: trap in noted\n"); qunlock(&u->p->debug); - goto Die; + pexit("Suicide", 0); } splhi(); qunlock(&u->p->debug); rfnote(urp); break; - /* never returns */ default: pprint("unknown noted arg 0x%lux\n", arg0); @@ -546,10 +512,13 @@ syscall(Ureg *aur) * smash them. but we must save fpstatus. */ if(p->fpstate == FPactive) { + if((ur->status&CU1) == 0) + panic("syscall: FPactive but no CU1"); u->fpsave.fpstatus = fcr31(); p->fpstate = FPinit; ur->status &= ~CU1; } + spllo(); if(p->procctl) @@ -587,6 +556,7 @@ syscall(Ureg *aur) p->insyscall = 0; if(u->scallnr == NOTED) /* ugly hack */ noted(&aur, *(ulong*)(sp+BY2WD)); /* doesn't return */ + splhi(); if(u->scallnr!=RFORK && (p->procctl || u->nnote)){ ur->r1 = ret; /* load up for noted() */