The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/alphapc/trap.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include        "u.h"
    2 #include        "../port/lib.h"
    3 #include        "mem.h"
    4 #include        "dat.h"
    5 #include        "fns.h"
    6 #include        "ureg.h"
    7 #include        "io.h"
    8 #include        "../port/error.h"
    9 
   10 void    noted(Ureg*, Ureg**, ulong);
   11 void    rfnote(Ureg**);
   12 void    kernfault(Ureg*, int);
   13 void    illegal(Ureg *);
   14 void    fen(Ureg *);
   15 
   16 char *regname[]={
   17         "type", "a0",           "a1",
   18         "a2",           "R0",           "R1",
   19         "R2",           "R3",           "R4",
   20         "R5",           "R6",           "R7",
   21         "R8",           "R9",           "R10",
   22         "R11",  "R12",  "R13",
   23         "R14",  "R15",  "R19",
   24         "R20",  "R21",  "R22",
   25         "R23",  "R24",  "R25",
   26         "R26",  "R27",  "R28",
   27         "R30",  "status",       "PC",
   28         "R29",  "R16",  "R17",
   29         "R18",
   30 };
   31 
   32 static Lock vctllock;
   33 static Vctl *vctl[256];
   34 
   35 void
   36 intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
   37 {
   38         int vno;
   39         Vctl *v;
   40 
   41         if(f == nil){
   42                 print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",
   43                         irq, tbdf, name);
   44                 return;
   45         }
   46 
   47         v = xalloc(sizeof(Vctl));
   48         v->isintr = 1;
   49         v->irq = irq;
   50         v->tbdf = tbdf;
   51         v->f = f;
   52         v->a = a;
   53         strncpy(v->name, name, KNAMELEN-1);
   54         v->name[KNAMELEN-1] = 0;
   55 
   56         ilock(&vctllock);
   57         vno = arch->intrenable(v);
   58         if(vno == -1){
   59                 iunlock(&vctllock);
   60                 print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
   61                         irq, tbdf, v->name);
   62                 xfree(v);
   63                 return;
   64         }
   65         if(vctl[vno]){
   66                 if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
   67                         panic("intrenable: handler: %s %s %#p %#p %#p %#p",
   68                                 vctl[vno]->name, v->name,
   69                                 vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
   70                 v->next = vctl[vno];
   71         }
   72         vctl[vno] = v;
   73         iunlock(&vctllock);
   74 }
   75 
   76 int
   77 intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
   78 {
   79         Vctl **pv, *v;
   80         int vno;
   81 
   82         /*
   83          * For now, none of this will work with the APIC code,
   84          * there is no mapping between irq and vector as the IRQ
   85          * is pretty meaningless.
   86          */
   87         if(arch->intrvecno == nil)
   88                 return -1;
   89         vno = arch->intrvecno(irq);
   90         ilock(&vctllock);
   91         for(pv = &vctl[vno]; *pv != nil; pv = &((*pv)->next)){
   92                 if((*pv)->irq != irq)
   93                         continue;
   94                 if((*pv)->tbdf != tbdf)
   95                         continue;
   96                 if((*pv)->f != f)
   97                         continue;
   98                 if((*pv)->a != a)
   99                         continue;
  100                 if(strcmp((*pv)->name, name) != 0)
  101                         continue;
  102                 break;
  103         }
  104         assert(*pv != nil);
  105 
  106         v = *pv;
  107         *pv = (*pv)->next;      /* Link out the entry */
  108         
  109         if (vctl[vno] == nil && arch->intrdisable != nil)
  110                 arch->intrdisable(irq);
  111         iunlock(&vctllock);
  112         xfree(v);
  113         return 0;
  114 }
  115 
  116 int
  117 irqallocread(char *buf, long n, vlong offset)
  118 {
  119         int vno;
  120         Vctl *v;
  121         long oldn;
  122         char str[11+1+KNAMELEN+1], *p;
  123         int m;
  124 
  125         if(n < 0 || offset < 0)
  126                 error(Ebadarg);
  127 
  128         oldn = n;
  129         for(vno=0; vno<nelem(vctl); vno++){
  130                 for(v=vctl[vno]; v; v=v->next){
  131                         m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name);
  132                         if(m <= offset) /* if do not want this, skip entry */
  133                                 offset -= m;
  134                         else{
  135                                 /* skip offset bytes */
  136                                 m -= offset;
  137                                 p = str+offset;
  138                                 offset = 0;
  139 
  140                                 /* write at most max(n,m) bytes */
  141                                 if(m > n)
  142                                         m = n;
  143                                 memmove(buf, p, m);
  144                                 n -= m;
  145                                 buf += m;
  146 
  147                                 if(n == 0)
  148                                         return oldn;
  149                         }       
  150                 }
  151         }
  152         return oldn - n;
  153 }
  154 
  155 typedef struct Mcheck Mcheck;
  156 struct Mcheck
  157 {
  158         ulong   len;
  159         ulong   inprogress;
  160         ulong   procoff;
  161         ulong   sysoff;
  162         ulong   code;
  163 };
  164 
  165 static char *
  166 smcheck(ulong code)
  167 {
  168         switch (code) {
  169         case 0x80: return "tag parity error";
  170         case 0x82: return "tag control parity error";
  171         case 0x84: return "generic hard error";
  172         case 0x86: return "correctable ECC error";
  173         case 0x88: return "uncorrectable ECC error";
  174         case 0x8a: return "OS-specific PAL bugcheck";
  175         case 0x90: return "callsys in kernel mode";
  176         case 0x96: return "i-cache read retryable error";
  177         case 0x98: return "processor detected hard error";
  178 
  179         case 0x203: return "system detected uncorrectable ECC error";
  180         case 0x205: return "parity error detected by CIA";
  181         case 0x207: return "non-existent memory error";
  182         case 0x209: return "PCI SERR detected";
  183         case 0x20b: return "PCI data parity error detected";
  184         case 0x20d: return "PCI address parity error detected";
  185         case 0x20f: return "PCI master abort error";
  186         case 0x211: return "PCI target abort error";
  187         case 0x213: return "scatter/gather PTE invalid error";
  188         case 0x215: return "flash ROM write error";
  189         case 0x217: return "IOA timeout detected";
  190         case 0x219: return "IOCHK#, EISA add-in board parity or other catastrophic error";
  191         case 0x21b: return "EISA fail-safe timer timeout";
  192         case 0x21d: return "EISA bus time-out";
  193         case 0x21f: return "EISA software generated NMI";
  194         case 0x221: return "unexpected ev5 IRQ[3] interrupt";
  195         default: return "unknown mcheck";
  196         }
  197 }
  198 
  199 void
  200 mcheck(Ureg *ur, void *x)
  201 {
  202         Mcheck *m;
  203         uvlong *data;
  204         int i, col;
  205 
  206         m = x;
  207         data = x;
  208         iprint("panic: Machine Check @%#p: %s (%lux) len %lud\n",
  209                         m, smcheck(m->code), m->code, m->len);
  210         iprint("proc offset %lux sys offset %lux\n", m->procoff, m->sysoff);
  211         for (i = 0, col = 0; i < m->len/8; i++) {
  212                 iprint("%.3x: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : "    ");
  213                 if (col++ == 2)
  214                         col = 0;
  215         }
  216         if(col != 2)
  217                 print("\n");
  218         print("\n");
  219         dumpregs(ur);
  220         prflush();
  221         firmware();
  222 }
  223 
  224 void
  225 intr(Ureg *ur)
  226 {
  227         int i, vno;
  228         Vctl *ctl, *v;
  229         Mach *mach;
  230 
  231         vno = (ulong)ur->a1>>4;
  232         vno -= 0x80;
  233         if(vno < nelem(vctl) && (ctl = vctl[vno])){
  234                 if(ctl->isintr){
  235                         m->intr++;
  236                         if(vno >= VectorPIC && vno <= MaxVectorPIC)
  237                                 m->lastintr = vno-VectorPIC;
  238                 }
  239 
  240                 if(ctl->isr)
  241                         ctl->isr(vno);
  242                 for(v = ctl; v != nil; v = v->next) {
  243                         if(v->f)
  244                                 v->f(ur, v->a);
  245                 }
  246 
  247                 if(ctl->eoi)
  248                         ctl->eoi(vno);
  249 
  250                 if(ctl->isintr && up)
  251                         preempted();
  252         }
  253         else if(vno >= VectorPIC && vno <= MaxVectorPIC){
  254                 /*
  255                  * An unknown interrupt.
  256                  * Check for a default IRQ7. This can happen when
  257                  * the IRQ input goes away before the acknowledge.
  258                  * In this case, a 'default IRQ7' is generated, but
  259                  * the corresponding bit in the ISR isn't set.
  260                  * In fact, just ignore all such interrupts.
  261                  */
  262                 iprint("cpu%d: spurious interrupt %d, last %d",
  263                         m->machno, vno-VectorPIC, m->lastintr);
  264                 for(i = 0; i < 32; i++){
  265                         if(!(active.machs & (1<<i)))
  266                                 continue;
  267                         mach = MACHP(i);
  268                         if(m->machno == mach->machno)
  269                                 continue;
  270                         iprint(": cpu%d: last %d", mach->machno, mach->lastintr);
  271                 }
  272                 iprint("\n");
  273                 m->spuriousintr++;
  274                 return;
  275         }
  276         else{
  277                 dumpregs(ur);
  278                 print("unknown intr: %d\n", vno); /* */
  279         }
  280 }
  281 
  282 void
  283 trap(Ureg *ur)
  284 {
  285         char buf[ERRMAX];
  286         int clockintr, user, x;
  287 
  288         user = ur->status&UMODE;
  289 
  290         if(user){
  291                 up = m->proc;
  292                 up->dbgreg = ur;
  293         }
  294         clockintr = 0;
  295         switch ((int)ur->type) {
  296         case 1: /* arith */
  297                 fptrap(ur);
  298                 break;
  299         case 2: /* bad instr or FEN */
  300                 illegal(ur);
  301                 break;
  302 
  303         case 3: /* intr */
  304                 m->intr++;
  305                 switch ((int)ur->a0) {
  306                 case 0: /* interprocessor */
  307                         panic("interprocessor intr");
  308                         break;
  309                 case 1: /* clock */
  310                         clockintr = 1;
  311                         clock(ur);
  312                         break;
  313                 case 2: /* machine check */
  314                         mcheck(ur, (void*)(KZERO|(ulong)ur->a2));
  315                         break;
  316                 case 3: /* device */
  317                         intr(ur);
  318                         break;
  319                 case 4: /* perf counter */
  320                         panic("perf count");
  321                         break;
  322                 default:
  323                         panic("bad intr");
  324                         break;
  325                 }
  326                 break;
  327 
  328         case 4: /* memory fault */
  329                 if(up == 0)
  330                         kernfault(ur, (ulong)ur->a1);
  331 
  332                 x = up->insyscall;
  333                 up->insyscall = 1;
  334                 spllo();
  335                 faultalpha(ur);
  336                 up->insyscall = x;
  337                 break;
  338         case 6: /* alignment fault */
  339                 ur->pc -= 4;
  340                 sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0);
  341                 fataltrap(ur, buf);
  342                 break;
  343         default:        /* cannot happen */
  344                 panic("bad trap type %d", (int)ur->type);
  345                 break;
  346         }
  347 
  348         splhi();
  349 
  350         /* delaysched set because we held a lock or because our quantum ended */
  351         if(up && up->delaysched && clockintr){
  352                 sched();
  353                 splhi();
  354         }
  355 
  356         if(user){
  357                 if(up->procctl || up->nnote)
  358                         notify(ur);
  359                 kexit(ur);
  360         }
  361 }
  362 
  363 void
  364 trapinit(void)
  365 {
  366         splhi();
  367         wrent(0, intr0);
  368         wrent(1, arith);
  369         wrent(2, fault0);
  370         wrent(3, illegal0);
  371         wrent(4, unaligned);
  372         wrent(5, syscall0);
  373 }
  374 
  375 void
  376 fataltrap(Ureg *ur, char *reason)
  377 {
  378         char buf[ERRMAX];
  379 
  380         if(ur->status&UMODE) {
  381                 spllo();
  382                 sprint(buf, "sys: %s", reason);
  383                 postnote(up, 1, buf, NDebug);
  384                 return;
  385         }
  386         print("kernel %s pc=%lux\n", reason, (ulong)ur->pc);
  387         dumpregs(ur);
  388         dumpstack();
  389         if(m->machno == 0)
  390                 spllo();
  391         exit(1);
  392 }
  393 
  394 void
  395 kernfault(Ureg *ur, int code)
  396 {
  397         Label l;
  398         char *s;
  399 
  400         splhi();
  401         if (code == 0)
  402                 s = "read";
  403         else if (code == 1)
  404                 s = "write";
  405         else
  406                 s = "ifetch";
  407         print("panic: kfault %s VA=0x%lux\n", s, (ulong)ur->a0);
  408         print("u=%#p status=0x%lux pc=0x%lux sp=0x%lux\n",
  409                         up, (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp);
  410         dumpregs(ur);
  411         l.sp = ur->sp;
  412         l.pc = ur->pc;
  413         dumpstack();
  414         exit(1);
  415 }
  416 
  417 void
  418 dumpregs(Ureg *ur)
  419 {
  420         int i, col;
  421         uvlong *l;
  422 
  423         if(up)
  424                 print("registers for %s %ld\n", up->text, up->pid);
  425         else
  426                 print("registers for kernel\n");
  427 
  428         l = &ur->type;
  429         col = 0;
  430         for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) {
  431                 print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : "     ");
  432                 if (col++ == 2)
  433                         col = 0;
  434         }
  435         print("\n");
  436 }
  437 
  438 
  439 /*
  440  * Fill in enough of Ureg to get a stack trace, and call a function.
  441  * Used by debugging interface rdb.
  442  */
  443 static void
  444 getpcsp(ulong *pc, ulong *sp)
  445 {
  446         *pc = getcallerpc(&pc);
  447         *sp = (ulong)&pc-8;
  448 }
  449 
  450 void
  451 callwithureg(void (*fn)(Ureg*))
  452 {
  453         Ureg ureg;
  454 
  455         getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
  456         ureg.r26 = getcallerpc(&fn);
  457         fn(&ureg);
  458 }
  459 
  460 void
  461 _dumpstack(Ureg *ureg)
  462 {
  463         ulong l, sl, el, v, i, instr, op;
  464         extern ulong etext;
  465 
  466         l=(ulong)&l;
  467         if(l&4)
  468                 l += 4;
  469         if(up == 0){
  470                 el = (ulong)m+BY2PG;
  471                 sl = el-KSTACK;
  472         }
  473         else{
  474                 sl = (ulong)up->kstack;
  475                 el = sl + KSTACK;
  476         }
  477         if(l > el || l < sl){
  478                 el = (ulong)m+BY2PG;
  479                 sl = el-KSTACK;
  480         }
  481         if(l > el || l < sl)
  482                 return;
  483         print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", (ulong)ureg->pc, (ulong)ureg->sp, (ulong)ureg->r26);
  484 
  485         i = 0;
  486         for(; l<el; l+=8){
  487                 v = *(ulong*)l - 4;
  488                 if(KTZERO < v && v < (ulong)&etext && (v&3) == 0){
  489                         /*
  490                          * Check for JSR/BSR
  491                          */
  492                         instr = *(ulong*)v;
  493                         op = (instr>>26);
  494                         if(op == 26 || op == 52){
  495                                 print("%lux=%lux ", l, v);
  496                                 i++;
  497                         }
  498                 }
  499                 if(i == 4){
  500                         i = 0;
  501                         print("\n");
  502                 }
  503         }
  504         if(i)
  505                 print("\n");
  506 }
  507 
  508 void
  509 dumpstack(void)
  510 {
  511         callwithureg(_dumpstack);
  512 }
  513 
  514 int
  515 notify(Ureg *ur)
  516 {
  517         int l;
  518         ulong sp;
  519         Note *n;
  520 
  521         if(up->procctl)
  522                 procctl(up);
  523         if(up->nnote == 0)
  524                 return 0;
  525 
  526         spllo();
  527         qlock(&up->debug);
  528         up->notepending = 0;
  529 
  530         if(up->fpstate == FPactive){
  531                 savefpregs(&up->fpsave);
  532                 up->fpstate = FPinactive;
  533         }
  534         up->fpstate |= FPillegal;
  535 
  536         n = &up->note[0];
  537         if(strncmp(n->msg, "sys:", 4) == 0) {
  538                 l = strlen(n->msg);
  539                 if(l > ERRMAX-15)       /* " pc=0x12345678\0" */
  540                         l = ERRMAX-15;
  541 
  542                 sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc);
  543         }
  544 
  545         if(n->flag != NUser && (up->notified || up->notify==0)) {
  546                 if(n->flag == NDebug)
  547                         pprint("suicide: %s\n", n->msg);
  548                 qunlock(&up->debug);
  549                 pexit(n->msg, n->flag!=NDebug);
  550         }
  551 
  552         if(up->notified) {
  553                 qunlock(&up->debug);
  554                 splhi();
  555                 return 0;
  556         }
  557                 
  558         if(!up->notify) {
  559                 qunlock(&up->debug);
  560                 pexit(n->msg, n->flag!=NDebug);
  561         }
  562         sp = ur->usp & ~(BY2V-1);
  563         sp -= sizeof(Ureg);
  564 
  565         if(!okaddr((ulong)up->notify, BY2WD, 0)
  566         || !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) {
  567                 pprint("suicide: bad address or sp in notify\n");
  568 print("suicide: bad address or sp in notify\n");
  569                 qunlock(&up->debug);
  570                 pexit("Suicide", 0);
  571         }
  572 
  573         memmove((Ureg*)sp, ur, sizeof(Ureg));
  574         *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
  575         up->ureg = (void*)sp;
  576         sp -= 2*BY2WD+ERRMAX;
  577         memmove((char*)sp, up->note[0].msg, ERRMAX);
  578         sp -= 4*BY2WD;
  579         *(ulong*)(sp+3*BY2WD) = sp+4*BY2WD;     /* arg 2 is string */
  580         ur->r0 = (ulong)up->ureg;               /* arg 1 (R0) is ureg* */
  581         *(ulong*)(sp+2*BY2WD) = (ulong)up->ureg;        /* arg 1 0(FP) is ureg* */
  582         *(ulong*)(sp+0*BY2WD) = 0;              /* arg 0 is pc */
  583         ur->usp = sp;
  584         ur->pc = (ulong)up->notify;
  585         up->notified = 1;
  586         up->nnote--;
  587         memmove(&up->lastnote, &up->note[0], sizeof(Note));
  588         memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
  589 
  590         qunlock(&up->debug);
  591         splhi();
  592         return 1;
  593 }
  594 
  595 /*
  596  * Check that status is OK to return from note.
  597  */
  598 int
  599 validstatus(ulong kstatus, ulong ustatus)
  600 {
  601         if((kstatus & 7) != (ustatus & 7))
  602                 return 0;
  603         if((ustatus&UMODE) != UMODE)
  604                 return 0;
  605         return 1;
  606 }
  607 
  608 /*
  609  * Return user to state before notify()
  610  */
  611 void
  612 noted(Ureg *kur, Ureg **urp, ulong arg0)
  613 {
  614         Ureg *nur;
  615         ulong oureg, sp;
  616 
  617         qlock(&up->debug);
  618         if(arg0!=NRSTR && !up->notified) {
  619                 qunlock(&up->debug);
  620                 pprint("call to noted() when not notified\n");
  621 print("call to noted() when not notified\n");
  622                 pexit("Suicide", 0);
  623         }
  624         up->notified = 0;
  625 
  626         up->fpstate &= ~FPillegal;
  627 
  628         nur = up->ureg;
  629 
  630         oureg = (ulong)nur;
  631         if((oureg & (BY2V-1))
  632         || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
  633                 pprint("bad ureg in noted or call to noted() when not notified\n");
  634 print("bad ureg in noted or call to noted() when not notified\n");
  635                 qunlock(&up->debug);
  636                 pexit("Suicide", 0);
  637         }
  638 
  639         if(!validstatus(kur->status, nur->status)) {
  640                 qunlock(&up->debug);
  641                 pprint("bad noted ureg status %lux\n", (ulong)nur->status);
  642 print("bad noted ureg status %lux\n", (ulong)nur->status);
  643                 pexit("Suicide", 0);
  644         }
  645 
  646         memmove(*urp, up->ureg, sizeof(Ureg));
  647         switch(arg0) {
  648         case NCONT:
  649         case NRSTR:
  650                 if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
  651                         pprint("suicide: trap in noted\n");
  652 print("suicide: trap in noted\n");
  653                         qunlock(&up->debug);
  654                         pexit("Suicide", 0);
  655                 }
  656                 up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
  657                 qunlock(&up->debug);
  658                 splhi();
  659                 rfnote(urp);
  660                 break;
  661 
  662         case NSAVE:
  663                 if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
  664                         pprint("suicide: trap in noted\n");
  665 print("suicide: trap in noted\n");
  666                         qunlock(&up->debug);
  667                         pexit("Suicide", 0);
  668                 }
  669                 qunlock(&up->debug);
  670                 sp = oureg-4*BY2WD-ERRMAX;
  671                 splhi();
  672                 (*urp)->sp = sp;
  673                 ((ulong*)sp)[1] = oureg;        /* arg 1 0(FP) is ureg* */
  674                 ((ulong*)sp)[0] = 0;                    /* arg 0 is pc */
  675                 (*urp)->r0 = oureg;             /* arg 1 is ureg* */
  676                 rfnote(urp);
  677                 break;
  678 
  679         default:
  680                 pprint("unknown noted arg 0x%lux\n", arg0);
  681 print("unknown noted arg 0x%lux\n", arg0);
  682                 up->lastnote.flag = NDebug;
  683                 /* fall through */
  684                 
  685         case NDFLT:
  686                 if(up->lastnote.flag == NDebug)
  687                         pprint("suicide: %s\n", up->lastnote.msg);
  688                 qunlock(&up->debug);
  689                 pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
  690         }
  691 }
  692 
  693 #include "../port/systab.h"
  694 
  695 long
  696 syscall(Ureg *aur)
  697 {
  698         int i;
  699         char *e;
  700         long ret;
  701         ulong sp;
  702         Ureg *ur;
  703         ulong scallnr;
  704 
  705         m->syscall++;
  706         up = m->proc;
  707         up->insyscall = 1;
  708         ur = aur;
  709         up->pc = ur->pc;
  710         up->dbgreg = aur;
  711         ur->type = 5;           /* for debugging */
  712 
  713         scallnr = ur->r0;
  714         up->scallnr = ur->r0;
  715 
  716         if(scallnr == RFORK && up->fpstate == FPactive){
  717                 savefpregs(&up->fpsave);
  718                 up->fpstate = FPinactive;
  719 //print("SR=%lux+", up->fpsave.fpstatus);
  720         }
  721         spllo();
  722 
  723         sp = ur->sp;
  724         up->nerrlab = 0;
  725         ret = -1;
  726         if(!waserror()) {
  727                 if(scallnr >= nsyscall || systab[scallnr] == nil){
  728                         pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc);
  729                         postnote(up, 1, "sys: bad sys call", NDebug);
  730                         error(Ebadarg);
  731                 }
  732 
  733                 if(sp & (BY2WD-1)){     /* XXX too weak? */
  734                         pprint("odd sp in sys call pc %lux sp %lux\n",
  735                                 (ulong)ur->pc, (ulong)ur->sp);
  736                         postnote(up, 1, "sys: odd stack", NDebug);
  737                         error(Ebadarg);
  738                 }
  739 
  740                 if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)))
  741                         validaddr(sp, sizeof(Sargs), 0);
  742 
  743                 up->s = *((Sargs*)(sp+2*BY2WD));
  744                 up->psstate = sysctab[scallnr];
  745                 ret = systab[scallnr](up->s.args);
  746                 poperror();
  747         }else{
  748                 /* failure: save the error buffer for errstr */
  749                 e = up->syserrstr;
  750                 up->syserrstr = up->errstr;
  751                 up->errstr = e;
  752         }
  753         if(up->nerrlab){
  754                 print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
  755                 for(i = 0; i < NERR; i++)
  756                         print("sp=%lux pc=%lux\n",
  757                                 up->errlab[i].sp, up->errlab[i].pc);
  758                 panic("error stack");
  759         }
  760 
  761         up->nerrlab = 0;
  762         up->psstate = 0;
  763         up->insyscall = 0;
  764         if(scallnr == NOTED)                    /* ugly hack */
  765                 noted(ur, &aur, *(ulong*)(sp+2*BY2WD)); /* doesn't return */
  766 
  767         if(scallnr!=RFORK && (up->procctl || up->nnote)){
  768                 ur->r0 = ret;                           /* load up for noted() */
  769                 if(notify(ur))
  770                         return ur->r0;
  771         }
  772 
  773         return ret;
  774 }
  775 
  776 void
  777 forkchild(Proc *p, Ureg *ur)
  778 {
  779         Ureg *cur;
  780 
  781         p->sched.sp = (ulong)p->kstack+KSTACK-(4*BY2WD+sizeof(Ureg));
  782         p->sched.pc = (ulong)forkret;
  783 
  784         cur = (Ureg*)(p->sched.sp+4*BY2WD);
  785         memmove(cur, ur, sizeof(Ureg));
  786 
  787         /* Things from bottom of syscall we never got to execute */
  788         p->psstate = 0;
  789         p->insyscall = 0;
  790 }
  791 
  792 static
  793 void
  794 linkproc(void)
  795 {
  796         spllo();
  797         up->kpfun(up->kparg);
  798         pexit("kproc exiting", 0);
  799 }
  800 
  801 void
  802 kprocchild(Proc *p, void (*func)(void*), void *arg)
  803 {
  804         p->sched.pc = (ulong)linkproc;
  805         p->sched.sp = (ulong)p->kstack+KSTACK;
  806 
  807         p->kpfun = func;
  808         p->kparg = arg;
  809 }
  810 
  811 long
  812 execregs(ulong entry, ulong ssize, ulong nargs)
  813 {
  814         Ureg *ur;
  815         ulong *sp;
  816 
  817         sp = (ulong*)(USTKTOP - ssize);
  818         *--sp = nargs;
  819 
  820         ur = (Ureg*)up->dbgreg;
  821         ur->usp = (ulong)sp;
  822         ur->pc = entry;
  823         return USTKTOP-BY2WD;                   /* address of user-level clock */
  824 }
  825 
  826 ulong
  827 userpc(void)
  828 {
  829         Ureg *ur;
  830 
  831         ur = (Ureg*)up->dbgreg;
  832         return ur->pc;
  833 }
  834 
  835 /* This routine must save the values of registers the user is not permitted to write
  836  * from devproc and then restore the saved values before returning
  837  */
  838 void
  839 setregisters(Ureg *xp, char *pureg, char *uva, int n)
  840 {
  841         ulong status;
  842 
  843         status = xp->status;
  844         memmove(pureg, uva, n);
  845         xp->status = status;
  846 }
  847 
  848 /* Give enough context in the ureg to produce a kernel stack for
  849  * a sleeping process
  850  */
  851 void
  852 setkernur(Ureg *xp, Proc *p)
  853 {
  854         xp->pc = p->sched.pc;
  855         xp->sp = p->sched.sp;
  856         xp->r26 = (ulong)sched;
  857 }
  858 
  859 ulong
  860 dbgpc(Proc *p)
  861 {
  862         Ureg *ur;
  863 
  864         ur = p->dbgreg;
  865         if(ur == 0)
  866                 return 0;
  867 
  868         return ur->pc;
  869 }
  870 
  871 void
  872 illegal(Ureg *ur)
  873 {
  874         switch ((int)ur->a0) {
  875         case 0: /* breakpoint */
  876                 ur->pc -= 4;
  877                 fataltrap(ur, "breakpoint");
  878                 break;
  879         case 1: /* bugchk */
  880                 fataltrap(ur, "trap: bugchk");
  881                 break;
  882         case 2: /* gentrap */
  883                 fataltrap(ur, "trap: gentrap");
  884                 break;
  885         case 3: /* FEN */
  886                 fen(ur);
  887                 break;
  888         case 4: /* opDEC */
  889                 fataltrap(ur, "trap: illegal instruction");
  890                 break;
  891         default:
  892                 panic("illegal illegal %d", (int)ur->a0);
  893                 break;
  894         }
  895 }
  896 
  897 void
  898 fen(Ureg *ur)
  899 {
  900         if(up){
  901                 switch(up->fpstate){
  902                 case FPinit:
  903                         restfpregs(&initfp);
  904                         up->fpstate = FPactive;
  905 //print("EI=%lux+", initfp.fpstatus);
  906                         return;
  907 
  908                 case FPinactive:
  909                         restfpregs(&up->fpsave);
  910                         up->fpstate = FPactive;
  911 //print("EIA=%lux+", up->fpsave.fpstatus);
  912                         return;
  913                 }
  914         }
  915         fataltrap(ur, "trap: floating enable"); /* should never happen */
  916 }

Cache object: e8e2aacad23e441dd8cf341502558223


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.