123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916 |
- #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*, Ureg**, ulong);
- void rfnote(Ureg**);
- void kernfault(Ureg*, int);
- void illegal(Ureg *);
- void fen(Ureg *);
- char *regname[]={
- "type", "a0", "a1",
- "a2", "R0", "R1",
- "R2", "R3", "R4",
- "R5", "R6", "R7",
- "R8", "R9", "R10",
- "R11", "R12", "R13",
- "R14", "R15", "R19",
- "R20", "R21", "R22",
- "R23", "R24", "R25",
- "R26", "R27", "R28",
- "R30", "status", "PC",
- "R29", "R16", "R17",
- "R18",
- };
- static Lock vctllock;
- static Vctl *vctl[256];
- void
- intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
- {
- int vno;
- Vctl *v;
- if(f == nil){
- print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",
- irq, tbdf, name);
- return;
- }
- v = xalloc(sizeof(Vctl));
- v->isintr = 1;
- v->irq = irq;
- v->tbdf = tbdf;
- v->f = f;
- v->a = a;
- strncpy(v->name, name, KNAMELEN-1);
- v->name[KNAMELEN-1] = 0;
- ilock(&vctllock);
- vno = arch->intrenable(v);
- if(vno == -1){
- iunlock(&vctllock);
- print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
- irq, tbdf, v->name);
- xfree(v);
- return;
- }
- if(vctl[vno]){
- if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
- panic("intrenable: handler: %s %s %luX %luX %luX %luX\n",
- vctl[vno]->name, v->name,
- vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
- v->next = vctl[vno];
- }
- vctl[vno] = v;
- iunlock(&vctllock);
- }
- int
- intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
- {
- Vctl **pv, *v;
- int vno;
- /*
- * For now, none of this will work with the APIC code,
- * there is no mapping between irq and vector as the IRQ
- * is pretty meaningless.
- */
- if(arch->intrvecno == nil)
- return -1;
- vno = arch->intrvecno(irq);
- ilock(&vctllock);
- for(pv = &vctl[vno]; *pv != nil; pv = &((*pv)->next)){
- if((*pv)->irq != irq)
- continue;
- if((*pv)->tbdf != tbdf)
- continue;
- if((*pv)->f != f)
- continue;
- if((*pv)->a != a)
- continue;
- if(strcmp((*pv)->name, name) != 0)
- continue;
- break;
- }
- assert(*pv != nil);
- v = *pv;
- *pv = (*pv)->next; /* Link out the entry */
-
- if (vctl[vno] == nil && arch->intrdisable != nil)
- arch->intrdisable(irq);
- iunlock(&vctllock);
- xfree(v);
- return 0;
- }
- int
- irqallocread(char *buf, long n, vlong offset)
- {
- int vno;
- Vctl *v;
- long oldn;
- char str[11+1+KNAMELEN+1], *p;
- int m;
- if(n < 0 || offset < 0)
- error(Ebadarg);
- oldn = n;
- for(vno=0; vno<nelem(vctl); vno++){
- for(v=vctl[vno]; v; v=v->next){
- m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name);
- if(m <= offset) /* if do not want this, skip entry */
- offset -= m;
- else{
- /* skip offset bytes */
- m -= offset;
- p = str+offset;
- offset = 0;
- /* write at most max(n,m) bytes */
- if(m > n)
- m = n;
- memmove(buf, p, m);
- n -= m;
- buf += m;
- if(n == 0)
- return oldn;
- }
- }
- }
- return oldn - n;
- }
- typedef struct Mcheck Mcheck;
- struct Mcheck
- {
- ulong len;
- ulong inprogress;
- ulong procoff;
- ulong sysoff;
- ulong code;
- };
- static char *
- smcheck(ulong code)
- {
- switch (code) {
- case 0x80: return "tag parity error";
- case 0x82: return "tag control parity error";
- case 0x84: return "generic hard error";
- case 0x86: return "correctable ECC error";
- case 0x88: return "uncorrectable ECC error";
- case 0x8a: return "OS-specific PAL bugcheck";
- case 0x90: return "callsys in kernel mode";
- case 0x96: return "i-cache read retryable error";
- case 0x98: return "processor detected hard error";
- case 0x203: return "system detected uncorrectable ECC error";
- case 0x205: return "parity error detected by CIA";
- case 0x207: return "non-existent memory error";
- case 0x209: return "PCI SERR detected";
- case 0x20b: return "PCI data parity error detected";
- case 0x20d: return "PCI address parity error detected";
- case 0x20f: return "PCI master abort error";
- case 0x211: return "PCI target abort error";
- case 0x213: return "scatter/gather PTE invalid error";
- case 0x215: return "flash ROM write error";
- case 0x217: return "IOA timeout detected";
- case 0x219: return "IOCHK#, EISA add-in board parity or other catastrophic error";
- case 0x21b: return "EISA fail-safe timer timeout";
- case 0x21d: return "EISA bus time-out";
- case 0x21f: return "EISA software generated NMI";
- case 0x221: return "unexpected ev5 IRQ[3] interrupt";
- default: return "unknown mcheck";
- }
- }
- void
- mcheck(Ureg *ur, void *x)
- {
- Mcheck *m;
- uvlong *data;
- int i, col;
- m = x;
- data = x;
- iprint("panic: Machine Check @%lux: %s (%lux) len %lud\n",
- m, smcheck(m->code), m->code, m->len);
- iprint("proc offset %lux sys offset %lux\n", m->procoff, m->sysoff);
- for (i = 0, col = 0; i < m->len/8; i++) {
- iprint("%.3x: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : " ");
- if (col++ == 2)
- col = 0;
- }
- if(col != 2)
- print("\n");
- print("\n");
- dumpregs(ur);
- prflush();
- firmware();
- }
- void
- intr(Ureg *ur)
- {
- int i, vno;
- Vctl *ctl, *v;
- Mach *mach;
- vno = (ulong)ur->a1>>4;
- vno -= 0x80;
- if(vno < nelem(vctl) && (ctl = vctl[vno])){
- if(ctl->isintr){
- m->intr++;
- if(vno >= VectorPIC && vno <= MaxVectorPIC)
- m->lastintr = vno-VectorPIC;
- }
- if(ctl->isr)
- ctl->isr(vno);
- for(v = ctl; v != nil; v = v->next) {
- if(v->f)
- v->f(ur, v->a);
- }
- if(ctl->eoi)
- ctl->eoi(vno);
- if(ctl->isintr && up)
- preempted();
- }
- else if(vno >= VectorPIC && vno <= MaxVectorPIC){
- /*
- * An unknown interrupt.
- * Check for a default IRQ7. This can happen when
- * the IRQ input goes away before the acknowledge.
- * In this case, a 'default IRQ7' is generated, but
- * the corresponding bit in the ISR isn't set.
- * In fact, just ignore all such interrupts.
- */
- iprint("cpu%d: spurious interrupt %d, last %d",
- m->machno, vno-VectorPIC, m->lastintr);
- for(i = 0; i < 32; i++){
- if(!(active.machs & (1<<i)))
- continue;
- mach = MACHP(i);
- if(m->machno == mach->machno)
- continue;
- iprint(": cpu%d: last %d", mach->machno, mach->lastintr);
- }
- iprint("\n");
- m->spuriousintr++;
- return;
- }
- else{
- dumpregs(ur);
- print("unknown intr: %d\n", vno); /* */
- }
- }
- void
- trap(Ureg *ur)
- {
- char buf[ERRMAX];
- int clockintr, user, x;
- user = ur->status&UMODE;
- if(user){
- up = m->proc;
- up->dbgreg = ur;
- }
- clockintr = 0;
- switch ((int)ur->type) {
- case 1: /* arith */
- fptrap(ur);
- break;
- case 2: /* bad instr or FEN */
- illegal(ur);
- break;
- case 3: /* intr */
- m->intr++;
- switch ((int)ur->a0) {
- case 0: /* interprocessor */
- panic("interprocessor intr");
- break;
- case 1: /* clock */
- clockintr = 1;
- clock(ur);
- break;
- case 2: /* machine check */
- mcheck(ur, (void*)(KZERO|(ulong)ur->a2));
- break;
- case 3: /* device */
- intr(ur);
- break;
- case 4: /* perf counter */
- panic("perf count");
- break;
- default:
- panic("bad intr");
- break;
- }
- break;
- case 4: /* memory fault */
- if(up == 0)
- kernfault(ur, (ulong)ur->a1);
- x = up->insyscall;
- up->insyscall = 1;
- spllo();
- faultalpha(ur);
- up->insyscall = x;
- break;
- case 6: /* alignment fault */
- ur->pc -= 4;
- sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0);
- fataltrap(ur, buf);
- break;
- default: /* cannot happen */
- panic("bad trap type %d", (int)ur->type);
- break;
- }
- splhi();
- /* delaysched set because we held a lock or because our quantum ended */
- if(up && up->delaysched && clockintr){
- sched();
- splhi();
- }
- if(user){
- if(up->procctl || up->nnote)
- notify(ur);
- kexit(ur);
- }
- }
- void
- trapinit(void)
- {
- splhi();
- wrent(0, intr0);
- wrent(1, arith);
- wrent(2, fault0);
- wrent(3, illegal0);
- wrent(4, unaligned);
- wrent(5, syscall0);
- }
- void
- fataltrap(Ureg *ur, char *reason)
- {
- char buf[ERRMAX];
- if(ur->status&UMODE) {
- spllo();
- sprint(buf, "sys: %s", reason);
- postnote(up, 1, buf, NDebug);
- return;
- }
- print("kernel %s pc=%lux\n", reason, (ulong)ur->pc);
- dumpregs(ur);
- dumpstack();
- if(m->machno == 0)
- spllo();
- exit(1);
- }
- void
- kernfault(Ureg *ur, int code)
- {
- Label l;
- char *s;
- splhi();
- if (code == 0)
- s = "read";
- else if (code == 1)
- s = "write";
- else
- s = "ifetch";
- print("panic: kfault %s VA=0x%lux\n", s, (ulong)ur->a0);
- print("u=0x%lux status=0x%lux pc=0x%lux sp=0x%lux\n",
- up, (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp);
- dumpregs(ur);
- l.sp = ur->sp;
- l.pc = ur->pc;
- dumpstack();
- exit(1);
- }
- void
- dumpregs(Ureg *ur)
- {
- int i, col;
- uvlong *l;
- if(up)
- print("registers for %s %ld\n", up->text, up->pid);
- else
- print("registers for kernel\n");
- l = &ur->type;
- col = 0;
- for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) {
- print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : " ");
- if (col++ == 2)
- col = 0;
- }
- print("\n");
- }
- /*
- * Fill in enough of Ureg to get a stack trace, and call a function.
- * Used by debugging interface rdb.
- */
- static void
- getpcsp(ulong *pc, ulong *sp)
- {
- *pc = getcallerpc(&pc);
- *sp = (ulong)&pc-8;
- }
- void
- callwithureg(void (*fn)(Ureg*))
- {
- Ureg ureg;
- getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
- ureg.r26 = getcallerpc(&fn);
- fn(&ureg);
- }
- void
- _dumpstack(Ureg *ureg)
- {
- ulong l, sl, el, v, i, instr, op;
- extern ulong etext;
- l=(ulong)&l;
- if(l&4)
- l += 4;
- if(up == 0){
- el = (ulong)m+BY2PG;
- sl = el-KSTACK;
- }
- else{
- sl = (ulong)up->kstack;
- el = sl + KSTACK;
- }
- if(l > el || l < sl){
- el = (ulong)m+BY2PG;
- sl = el-KSTACK;
- }
- if(l > el || l < sl)
- return;
- print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", (ulong)ureg->pc, (ulong)ureg->sp, (ulong)ureg->r26);
- i = 0;
- for(; l<el; l+=8){
- v = *(ulong*)l - 4;
- if(KTZERO < v && v < (ulong)&etext && (v&3) == 0){
- /*
- * Check for JSR/BSR
- */
- instr = *(ulong*)v;
- op = (instr>>26);
- if(op == 26 || op == 52){
- print("%lux=%lux ", l, v);
- i++;
- }
- }
- if(i == 4){
- i = 0;
- print("\n");
- }
- }
- if(i)
- print("\n");
- }
- void
- dumpstack(void)
- {
- callwithureg(_dumpstack);
- }
- int
- notify(Ureg *ur)
- {
- int l;
- ulong sp;
- Note *n;
- if(up->procctl)
- procctl(up);
- if(up->nnote == 0)
- return 0;
- spllo();
- qlock(&up->debug);
- up->notepending = 0;
- if(up->fpstate == FPactive){
- savefpregs(&up->fpsave);
- up->fpstate = FPinactive;
- }
- up->fpstate |= FPillegal;
- n = &up->note[0];
- if(strncmp(n->msg, "sys:", 4) == 0) {
- l = strlen(n->msg);
- if(l > ERRMAX-15) /* " pc=0x12345678\0" */
- l = ERRMAX-15;
- sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc);
- }
- if(n->flag != NUser && (up->notified || up->notify==0)) {
- if(n->flag == NDebug)
- pprint("suicide: %s\n", n->msg);
- qunlock(&up->debug);
- pexit(n->msg, n->flag!=NDebug);
- }
- if(up->notified) {
- qunlock(&up->debug);
- splhi();
- return 0;
- }
-
- if(!up->notify) {
- qunlock(&up->debug);
- pexit(n->msg, n->flag!=NDebug);
- }
- sp = ur->usp & ~(BY2V-1);
- sp -= sizeof(Ureg);
- if(!okaddr((ulong)up->notify, BY2WD, 0)
- || !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) {
- pprint("suicide: bad address or sp in notify\n");
- print("suicide: bad address or sp in notify\n");
- qunlock(&up->debug);
- pexit("Suicide", 0);
- }
- memmove((Ureg*)sp, ur, sizeof(Ureg));
- *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
- up->ureg = (void*)sp;
- sp -= 2*BY2WD+ERRMAX;
- memmove((char*)sp, up->note[0].msg, ERRMAX);
- sp -= 4*BY2WD;
- *(ulong*)(sp+3*BY2WD) = sp+4*BY2WD; /* arg 2 is string */
- ur->r0 = (ulong)up->ureg; /* arg 1 (R0) is ureg* */
- *(ulong*)(sp+2*BY2WD) = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
- *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
- ur->usp = sp;
- ur->pc = (ulong)up->notify;
- up->notified = 1;
- up->nnote--;
- memmove(&up->lastnote, &up->note[0], sizeof(Note));
- memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
- qunlock(&up->debug);
- splhi();
- return 1;
- }
- /*
- * Check that status is OK to return from note.
- */
- int
- validstatus(ulong kstatus, ulong ustatus)
- {
- if((kstatus & 7) != (ustatus & 7))
- return 0;
- if((ustatus&UMODE) != UMODE)
- return 0;
- return 1;
- }
- /*
- * Return user to state before notify()
- */
- void
- noted(Ureg *kur, Ureg **urp, ulong arg0)
- {
- Ureg *nur;
- ulong oureg, sp;
- qlock(&up->debug);
- if(arg0!=NRSTR && !up->notified) {
- qunlock(&up->debug);
- pprint("call to noted() when not notified\n");
- print("call to noted() when not notified\n");
- pexit("Suicide", 0);
- }
- up->notified = 0;
- up->fpstate &= ~FPillegal;
- nur = up->ureg;
- oureg = (ulong)nur;
- if((oureg & (BY2V-1))
- || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
- pprint("bad ureg in noted or call to noted() when not notified\n");
- print("bad ureg in noted or call to noted() when not notified\n");
- qunlock(&up->debug);
- pexit("Suicide", 0);
- }
- if(!validstatus(kur->status, nur->status)) {
- qunlock(&up->debug);
- pprint("bad noted ureg status %lux\n", (ulong)nur->status);
- print("bad noted ureg status %lux\n", (ulong)nur->status);
- pexit("Suicide", 0);
- }
- memmove(*urp, up->ureg, sizeof(Ureg));
- switch(arg0) {
- case NCONT:
- case NRSTR:
- if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
- pprint("suicide: trap in noted\n");
- print("suicide: trap in noted\n");
- qunlock(&up->debug);
- pexit("Suicide", 0);
- }
- up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
- qunlock(&up->debug);
- splhi();
- rfnote(urp);
- break;
- case NSAVE:
- if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
- pprint("suicide: trap in noted\n");
- print("suicide: trap in noted\n");
- qunlock(&up->debug);
- pexit("Suicide", 0);
- }
- qunlock(&up->debug);
- sp = oureg-4*BY2WD-ERRMAX;
- splhi();
- (*urp)->sp = sp;
- ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
- ((ulong*)sp)[0] = 0; /* arg 0 is pc */
- (*urp)->r0 = oureg; /* arg 1 is ureg* */
- rfnote(urp);
- break;
- default:
- pprint("unknown noted arg 0x%lux\n", arg0);
- print("unknown noted arg 0x%lux\n", arg0);
- up->lastnote.flag = NDebug;
- /* fall through */
-
- case NDFLT:
- if(up->lastnote.flag == NDebug)
- pprint("suicide: %s\n", up->lastnote.msg);
- qunlock(&up->debug);
- pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
- }
- }
- #include "../port/systab.h"
- long
- syscall(Ureg *aur)
- {
- int i;
- char *e;
- long ret;
- ulong sp;
- Ureg *ur;
- ulong scallnr;
- m->syscall++;
- up = m->proc;
- up->insyscall = 1;
- ur = aur;
- up->pc = ur->pc;
- up->dbgreg = aur;
- ur->type = 5; /* for debugging */
- scallnr = ur->r0;
- up->scallnr = ur->r0;
- if(scallnr == RFORK && up->fpstate == FPactive){
- savefpregs(&up->fpsave);
- up->fpstate = FPinactive;
- //print("SR=%lux+", up->fpsave.fpstatus);
- }
- spllo();
- sp = ur->sp;
- up->nerrlab = 0;
- ret = -1;
- if(!waserror()) {
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc);
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- if(sp & (BY2WD-1)){ /* XXX too weak? */
- pprint("odd sp in sys call pc %lux sp %lux\n",
- (ulong)ur->pc, (ulong)ur->sp);
- postnote(up, 1, "sys: odd stack", NDebug);
- error(Ebadarg);
- }
- if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)))
- validaddr(sp, sizeof(Sargs), 0);
- up->s = *((Sargs*)(sp+2*BY2WD));
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr](up->s.args);
- poperror();
- }else{
- /* failure: save the error buffer for errstr */
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- }
- if(up->nerrlab){
- print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
- for(i = 0; i < NERR; i++)
- print("sp=%lux pc=%lux\n",
- up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
- up->nerrlab = 0;
- up->psstate = 0;
- up->insyscall = 0;
- if(scallnr == NOTED) /* ugly hack */
- noted(ur, &aur, *(ulong*)(sp+2*BY2WD)); /* doesn't return */
- if(scallnr!=RFORK && (up->procctl || up->nnote)){
- ur->r0 = ret; /* load up for noted() */
- if(notify(ur))
- return ur->r0;
- }
- return ret;
- }
- void
- forkchild(Proc *p, Ureg *ur)
- {
- Ureg *cur;
- p->sched.sp = (ulong)p->kstack+KSTACK-(4*BY2WD+sizeof(Ureg));
- p->sched.pc = (ulong)forkret;
- cur = (Ureg*)(p->sched.sp+4*BY2WD);
- memmove(cur, ur, sizeof(Ureg));
- /* Things from bottom of syscall we never got to execute */
- p->psstate = 0;
- p->insyscall = 0;
- }
- static
- void
- linkproc(void)
- {
- spllo();
- up->kpfun(up->kparg);
- pexit("kproc exiting", 0);
- }
- void
- kprocchild(Proc *p, void (*func)(void*), void *arg)
- {
- p->sched.pc = (ulong)linkproc;
- p->sched.sp = (ulong)p->kstack+KSTACK;
- p->kpfun = func;
- p->kparg = arg;
- }
- long
- execregs(ulong entry, ulong ssize, ulong nargs)
- {
- Ureg *ur;
- ulong *sp;
- sp = (ulong*)(USTKTOP - ssize);
- *--sp = nargs;
- ur = (Ureg*)up->dbgreg;
- ur->usp = (ulong)sp;
- ur->pc = entry;
- return USTKTOP-BY2WD; /* address of user-level clock */
- }
- ulong
- userpc(void)
- {
- Ureg *ur;
- ur = (Ureg*)up->dbgreg;
- return ur->pc;
- }
- /* This routine must save the values of registers the user is not permitted to write
- * from devproc and then restore the saved values before returning
- */
- void
- setregisters(Ureg *xp, char *pureg, char *uva, int n)
- {
- ulong status;
- status = xp->status;
- memmove(pureg, uva, n);
- xp->status = status;
- }
- /* Give enough context in the ureg to produce a kernel stack for
- * a sleeping process
- */
- void
- setkernur(Ureg *xp, Proc *p)
- {
- xp->pc = p->sched.pc;
- xp->sp = p->sched.sp;
- xp->r26 = (ulong)sched;
- }
- ulong
- dbgpc(Proc *p)
- {
- Ureg *ur;
- ur = p->dbgreg;
- if(ur == 0)
- return 0;
- return ur->pc;
- }
- void
- illegal(Ureg *ur)
- {
- switch ((int)ur->a0) {
- case 0: /* breakpoint */
- ur->pc -= 4;
- fataltrap(ur, "breakpoint");
- break;
- case 1: /* bugchk */
- fataltrap(ur, "trap: bugchk");
- break;
- case 2: /* gentrap */
- fataltrap(ur, "trap: gentrap");
- break;
- case 3: /* FEN */
- fen(ur);
- break;
- case 4: /* opDEC */
- fataltrap(ur, "trap: illegal instruction");
- break;
- default:
- panic("illegal illegal %d", (int)ur->a0);
- break;
- }
- }
- void
- fen(Ureg *ur)
- {
- if(up){
- switch(up->fpstate){
- case FPinit:
- restfpregs(&initfp);
- up->fpstate = FPactive;
- //print("EI=%lux+", initfp.fpstatus);
- return;
- case FPinactive:
- restfpregs(&up->fpsave);
- up->fpstate = FPactive;
- //print("EIA=%lux+", up->fpsave.fpstatus);
- return;
- }
- }
- fataltrap(ur, "trap: floating enable"); /* should never happen */
- }
|