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/ppc/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        "../port/error.h"
    8 #include        "tos.h"
    9 #include        <trace.h>
   10 
   11 static Lock vctllock;
   12 Vctl *vctl[256];
   13 
   14 void
   15 intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
   16 {
   17         int vno;
   18         Vctl *v;
   19 
   20         if(f == nil){
   21                 print("intrenable: nil handler for %d for %s\n",
   22                         irq, name);
   23                 return;
   24         }
   25 
   26         v = xalloc(sizeof(Vctl));
   27         v->isintr = 1;
   28         v->irq = irq;
   29         v->f = f;
   30         v->a = a;
   31         strncpy(v->name, name, KNAMELEN-1);
   32         v->name[KNAMELEN-1] = 0;
   33 
   34         ilock(&vctllock);
   35         vno = vectorenable(v);
   36         if(vno == -1){
   37                 iunlock(&vctllock);
   38                 print("intrenable: couldn't enable irq %d for %s\n",
   39                         irq, v->name);
   40                 xfree(v);
   41                 return;
   42         }
   43         v->next = vctl[vno];
   44         vctl[vno] = v;
   45         iunlock(&vctllock);
   46 }
   47 
   48 void
   49 intrdisable(int irq, void (*f)(Ureg *, void *), void *a, char *name)
   50 {
   51         Vctl **pv, *v;
   52 
   53         ilock(&vctllock);
   54         pv = &vctl[irq];
   55         while (*pv && 
   56                   ((*pv)->irq != irq || (*pv)->f != f || (*pv)->a != a ||
   57                    strcmp((*pv)->name, name)))
   58                 pv = &((*pv)->next);
   59 
   60         if(*pv == nil){
   61                 print("intrdisable: irq %d not found\n", irq);
   62                 iunlock(&vctllock);
   63                 return;
   64         }
   65 
   66         v = *pv;
   67         *pv = (*pv)->next;      /* Link out the entry */
   68         
   69         if(vctl[irq] == nil)
   70                 vectordisable(v);
   71         iunlock(&vctllock);
   72         xfree(v);
   73 }
   74 
   75 void    syscall(Ureg*);
   76 void    noted(Ureg*, ulong);
   77 static void _dumpstack(Ureg*);
   78 
   79 char *excname[] =
   80 {
   81         "reserved 0",
   82         "system reset",
   83         "machine check",
   84         "data access",
   85         "instruction access",
   86         "external interrupt",
   87         "alignment",
   88         "program exception",
   89         "floating-point unavailable",
   90         "decrementer",
   91         "reserved A",
   92         "reserved B",
   93         "system call",
   94         "trace trap",
   95         "floating point assist",
   96         "reserved F",
   97         "reserved 10",
   98         "data load translation miss",
   99         "data store translation miss",
  100         "instruction address breakpoint",
  101         "system management interrupt",
  102 };
  103 
  104 char *fpcause[] =
  105 {
  106         "inexact operation",
  107         "division by zero",
  108         "underflow",
  109         "overflow",
  110         "invalid operation",
  111 };
  112 char    *fpexcname(Ureg*, ulong, char*);
  113 #define FPEXPMASK       0xfff80300              /* Floating exception bits in fpscr */
  114 
  115 
  116 char *regname[]={
  117         "CAUSE",        "SRR1",
  118         "PC",           "GOK",
  119         "LR",           "CR",
  120         "XER",          "CTR",
  121         "R0",           "R1",
  122         "R2",           "R3",
  123         "R4",           "R5",
  124         "R6",           "R7",
  125         "R8",           "R9",
  126         "R10",          "R11",
  127         "R12",          "R13",
  128         "R14",          "R15",
  129         "R16",          "R17",
  130         "R18",          "R19",
  131         "R20",          "R21",
  132         "R22",          "R23",
  133         "R24",          "R25",
  134         "R26",          "R27",
  135         "R28",          "R29",
  136         "R30",          "R31",
  137         "DCMP",         "ICMP",
  138         "DMISS",        "IMISS",
  139         "HASH1",        "HASH2",
  140         "DAR",          "DSISR",
  141 };
  142 
  143 void
  144 kexit(Ureg*)
  145 {
  146         uvlong t;
  147         Tos *tos;
  148 
  149         /* precise time accounting, kernel exit */
  150         tos = (Tos*)(USTKTOP-sizeof(Tos));
  151         cycles(&t);
  152         tos->kcycles += t - up->kentry;
  153         tos->pcycles = up->pcycles;
  154         tos->pid = up->pid;
  155 }
  156 
  157 void
  158 trap(Ureg *ureg)
  159 {
  160         int ecode, user;
  161         char buf[ERRMAX], *s;
  162         extern FPsave initfp;
  163 
  164         ecode = (ureg->cause >> 8) & 0xff;
  165         user = (ureg->srr1 & MSR_PR) != 0;
  166         if(user){
  167                 cycles(&up->kentry);
  168                 up->dbgreg = ureg;
  169         }
  170         if(ureg->status & MSR_RI == 0)
  171                 print("double fault?: ecode = %d\n", ecode);
  172 
  173         switch(ecode) {
  174         case CEI:
  175                 m->intr++;
  176                 intr(ureg);
  177                 break;
  178         case CDEC:
  179                 clockintr(ureg);
  180                 break;
  181         case CDSI:
  182                 m->pfault++;
  183                 if (up == nil){
  184                         dumpregs(ureg);
  185                         panic("kernel fault");
  186                 }
  187                 up->mmureg = ureg;
  188                 faultpower(ureg, ureg->dar, (ureg->dsisr & BIT(6)) == 0);
  189                 break;
  190         case CISI:
  191                 m->pfault++;
  192                 if (up == nil){
  193                         dumpregs(ureg);
  194                         panic("kernel fault");
  195                 }
  196                 up->mmureg = ureg;
  197                 faultpower(ureg, ureg->pc, 1);
  198                 break;
  199         case CIMISS:    /* instruction miss */
  200                 if (up == nil){
  201                         dumpregs(ureg);
  202                         panic("kernel fault");
  203                 }
  204                 up->mmureg = ureg;
  205                 faultpower(ureg, ureg->imiss, 1);
  206                 break;
  207         case CLMISS:    /* data load miss */
  208                 if (up == nil){
  209                         dumpregs(ureg);
  210                         panic("kernel fault");
  211                 }
  212                 up->mmureg = ureg;
  213                 faultpower(ureg, ureg->dmiss, 1);
  214                 break;
  215         case CSMISS:    /* data store miss */
  216                 if (up == nil){
  217                         dumpregs(ureg);
  218                         panic("kernel fault");
  219                 }
  220                 up->mmureg = ureg;
  221                 faultpower(ureg, ureg->dmiss, 0);
  222                 break;
  223 
  224         case CSYSCALL:
  225                 if(!user)
  226                         panic("syscall in kernel: srr1 0x%4.4luX\n", ureg->srr1);
  227                 syscall(ureg);
  228                 if (up->delaysched){
  229                         sched();
  230                         splhi();
  231                 }
  232                 kexit(ureg);
  233                 return;         /* syscall() calls notify itself, don't do it again */
  234 
  235         case CFPU:
  236                 if(!user || up == nil) {
  237                         dumpregs(ureg);
  238                         panic("floating point in kernel");
  239                 }
  240                 switch(up->fpstate){
  241                 case FPinit:
  242                         fprestore(&initfp);
  243                         up->fpstate = FPactive;
  244                         break;
  245                 case FPinactive:
  246                         fprestore(&up->fpsave);
  247                         up->fpstate = FPactive;
  248                         break;
  249                 case FPactive:
  250                         print("up->fpstate %d\n", up->fpstate);
  251                         delay(100);
  252                         dumpregs(ureg);
  253                         delay(200);
  254                         panic("fpstate");
  255                         break;
  256                 default:
  257                         if(user){
  258                                 spllo();
  259                                 sprint(buf, "sys: floating point in note handler:");
  260                                 postnote(up, 1, buf, NDebug);
  261                                 break;
  262                         }
  263                         panic("kernel fpstate illegal");
  264                 }
  265                 ureg->srr1 |= MSR_FP;
  266                 break;
  267         case CPROG:
  268                 if(ureg->status & (1<<19))
  269                         s = "floating point exception";
  270                 else if(ureg->status & (1<<18))
  271                         s = "illegal instruction";
  272                 else if(ureg->status & (1<<17))
  273                         s = "privileged instruction";
  274                 else
  275                         s = "undefined program exception";
  276                 if(user){
  277                         spllo();
  278                         sprint(buf, "sys: trap: %s", s);
  279                         postnote(up, 1, buf, NDebug);
  280                         break;
  281                 }
  282                 dumpregs(ureg);
  283                 panic(s);
  284                 break;
  285         default:
  286                 if(ecode < nelem(excname) && user){
  287                         spllo();
  288                         sprint(buf, "sys: trap: %s", excname[ecode]);
  289                         postnote(up, 1, buf, NDebug);
  290                         break;
  291                 }
  292                 dumpregs(ureg);
  293                 if(ecode < nelem(excname))
  294                         panic("%s", excname[ecode]);
  295                 panic("unknown trap/intr: %d\n", ecode);
  296         }
  297 
  298         /* restoreureg must execute at high IPL */
  299         splhi();
  300 
  301         /* delaysched set because we held a lock or because our quantum ended */
  302         if(up && up->delaysched && ecode == CDEC){
  303                 sched();
  304                 splhi();
  305         }
  306 
  307         if(user) {
  308                 if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
  309                         postnote(up, 1, buf, NDebug);
  310                 }
  311                 notify(ureg);
  312                 if(up->fpstate != FPactive)
  313                         ureg->srr1 &= ~MSR_FP;
  314                 kexit(ureg);
  315         }
  316 }
  317 
  318 void
  319 faultpower(Ureg *ureg, ulong addr, int read)
  320 {
  321         int user, insyscall, n;
  322         char buf[ERRMAX];
  323 
  324         user = (ureg->srr1 & MSR_PR) != 0;
  325         insyscall = up->insyscall;
  326         up->insyscall = 1;
  327         n = fault(addr, read);
  328         if(n < 0){
  329                 if(!user){
  330                         dumpregs(ureg);
  331                         panic("fault: 0x%lux", addr);
  332                 }
  333                 sprint(buf, "sys: trap: fault %s addr=0x%lux", read? "read" : "write", addr);
  334                 postnote(up, 1, buf, NDebug);
  335         }
  336         up->insyscall = insyscall;
  337 }
  338 
  339 void
  340 sethvec(int v, void (*r)(void))
  341 {
  342         ulong *vp, pa, o;
  343 
  344         vp = KADDR(v);
  345         vp[0] = 0x7c1043a6;                     /* MOVW R0, SPR(SPRG0) */
  346         vp[1] = 0x7c0802a6;                     /* MOVW LR, R0 */
  347         vp[2] = 0x7c1243a6;                     /* MOVW R0, SPR(SPRG2) */
  348         pa = PADDR(r);
  349         o = pa >> 25;
  350         if(o != 0 && o != 0x7F){
  351                 /* a branch too far */
  352                 vp[3] = (15<<26)|(pa>>16);      /* MOVW $r&~0xFFFF, R0 */
  353                 vp[4] = (24<<26)|(pa&0xFFFF);   /* OR $r&0xFFFF, R0 */
  354                 vp[5] = 0x7c0803a6;             /* MOVW R0, LR */
  355                 vp[6] = 0x4e800021;             /* BL (LR) */
  356         }else
  357                 vp[3] = (18<<26)|(pa&0x3FFFFFC)|3;      /* bla */
  358 }
  359 
  360 void
  361 setmvec(int v, void (*r)(void), void (*t)(void))
  362 {
  363         ulong *vp, pa, o, n;
  364 
  365         vp = KADDR(v);
  366         n = 0;
  367         vp[n++] = 0x7c1043a6;                   /* MOVW R0, SPR(SPRG0) */
  368         vp[n++] = 0x7c0802a6;                   /* MOVW LR, R0 */
  369         vp[n++] = 0x7c1243a6;                   /* MOVW R0, SPR(SPRG2) */
  370         pa = PADDR(r);
  371         o = pa >> 25;
  372         if(o != 0 && o != 0x7F){
  373                 /* a branch too far */
  374                 vp[n++] = (15<<26)|(pa>>16);    /* MOVW $r&~0xFFFF, R0 */
  375                 vp[n++] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
  376                 vp[n++] = 0x7c0803a6;           /* MOVW R0, LR */
  377                 vp[n++] = 0x4e800021;           /* BL (LR) */
  378         }else
  379                 vp[n++] = (18<<26)|(pa&0x3FFFFFC)|3;    /* bla */
  380         pa = PADDR(t);
  381         o = pa >> 25;
  382         if(o != 0 && o != 0x7F){
  383                 /* a branch too far */
  384                 vp[n++] = (15<<26)|(pa>>16);    /* MOVW $r&~0xFFFF, R0 */
  385                 vp[n++] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
  386                 vp[n++] = 0x7c0803a6;           /* MOVW R0, LR */
  387                 vp[n] = 0x4e800021;             /* BL (LR) */
  388         }else
  389                 vp[n] = (18<<26)|(pa&0x3FFFFFC)|3;      /* bla */
  390 }
  391 
  392 char*
  393 fpexcname(Ureg *ur, ulong fpscr, char *buf)
  394 {
  395         int i;
  396         char *s;
  397         ulong fppc;
  398 
  399         fppc = ur->pc;
  400         s = 0;
  401         fpscr >>= 3;            /* trap enable bits */
  402         fpscr &= (fpscr>>22);   /* anded with exceptions */
  403         for(i=0; i<5; i++)
  404                 if(fpscr & (1<<i))
  405                         s = fpcause[i];
  406         if(s == 0)
  407                 return "no floating point exception";
  408         sprint(buf, "%s fppc=0x%lux", s, fppc);
  409         return buf;
  410 }
  411 
  412 /*
  413  * Fill in enough of Ureg to get a stack trace, and call a function.
  414  * Used by debugging interface rdb.
  415  */
  416 
  417 static void
  418 getpcsp(ulong *pc, ulong *sp)
  419 {
  420         *pc = getcallerpc(&pc);
  421         *sp = (ulong)&pc-4;
  422 }
  423 
  424 void
  425 callwithureg(void (*fn)(Ureg*))
  426 {
  427         Ureg ureg;
  428 
  429         getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
  430         ureg.lr = getcallerpc(&fn);
  431         fn(&ureg);
  432 }
  433 
  434 static void
  435 _dumpstack(Ureg *ureg)
  436 {
  437         ulong l, sl, el, v;
  438         int i;
  439 
  440         l = (ulong)&l;
  441         if(up == 0){
  442                 el = (ulong)m+BY2PG;
  443                 sl = el-KSTACK;
  444         }
  445         else{
  446                 sl = (ulong)up->kstack;
  447                 el = sl + KSTACK;
  448         }
  449         if(l > el || l < sl){
  450                 el = (ulong)m+BY2PG;
  451                 sl = el-KSTACK;
  452         }
  453         if(l > el || l < sl)
  454                 return;
  455         print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->lr);
  456         i = 0;
  457         for(; l < el; l += 4){
  458                 v = *(ulong*)l;
  459                 if(KTZERO < v && v < (ulong)etext){
  460                         print("%.8lux=%.8lux ", l, v);
  461                         if(i++ == 4){
  462                                 print("\n");
  463                                 i = 0;
  464                         }
  465                 }
  466         }
  467 }
  468 
  469 void
  470 dumpstack(void)
  471 {
  472         callwithureg(_dumpstack);
  473 }
  474 
  475 void
  476 dumpregs(Ureg *ur)
  477 {
  478         int i;
  479         ulong *l;
  480 
  481         if(up) {
  482                 print("registers for %s %ld\n", up->text, up->pid);
  483                 if(ur->srr1 & MSR_PR == 0)
  484                 if(ur->usp < (ulong)up->kstack || ur->usp > (ulong)up->kstack+KSTACK)
  485                         print("invalid stack ptr\n");
  486         }
  487         else
  488                 print("registers for kernel\n");
  489 
  490         for(i=0; i<16; i+=2)
  491                 print("sr[%x]\t0x%.8lux\tsr[%x]\t0x%.8lux\n", i, getsr(i<<28), i+1, getsr((i+1)<<28));
  492         l = &ur->cause;
  493         for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
  494                 print("%s\t0x%.8lux\t%s\t0x%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
  495         delay(500);
  496 }
  497 
  498 static void
  499 linkproc(void)
  500 {
  501         spllo();
  502         (*up->kpfun)(up->kparg);
  503         pexit("", 0);
  504 }
  505 
  506 void
  507 kprocchild(Proc *p, void (*func)(void*), void *arg)
  508 {
  509         p->sched.pc = (ulong)linkproc;
  510         p->sched.sp = (ulong)p->kstack+KSTACK;
  511 
  512         p->kpfun = func;
  513         p->kparg = arg;
  514 }
  515 
  516 /*
  517  * called in sysfile.c
  518  */
  519 void
  520 evenaddr(ulong addr)
  521 {
  522         if(addr & 3){
  523                 postnote(up, 1, "sys: odd address", NDebug);
  524                 error(Ebadarg);
  525         }
  526 }
  527 
  528 long
  529 execregs(ulong entry, ulong ssize, ulong nargs)
  530 {
  531         ulong *sp;
  532         Ureg *ureg;
  533 
  534         sp = (ulong*)(USTKTOP - ssize);
  535         *--sp = nargs;
  536 
  537         ureg = up->dbgreg;
  538         ureg->usp = (ulong)sp;
  539         ureg->pc = entry;
  540         ureg->srr1 &= ~MSR_FP;          /* disable floating point */
  541         up->fpstate = FPinit;
  542         return USTKTOP-sizeof(Tos);             /* address of kernel/user shared data */
  543 }
  544 
  545 void
  546 forkchild(Proc *p, Ureg *ur)
  547 {
  548         Ureg *cur;
  549 
  550         p->sched.sp = (ulong)p->kstack+KSTACK-UREGSIZE;
  551         p->sched.pc = (ulong)forkret;
  552 
  553         cur = (Ureg*)(p->sched.sp+2*BY2WD);
  554         memmove(cur, ur, sizeof(Ureg));
  555         cur->r3 = 0;
  556         
  557         /* Things from bottom of syscall we never got to execute */
  558         p->psstate = 0;
  559         p->insyscall = 0;
  560 }
  561 
  562 ulong
  563 userpc(void)
  564 {
  565         Ureg *ureg;
  566 
  567         ureg = (Ureg*)up->dbgreg;
  568         return ureg->pc;
  569 }
  570 
  571 
  572 /* This routine must save the values of registers the user is not 
  573  * permitted to write from devproc and then restore the saved values 
  574  * before returning
  575  */
  576 void
  577 setregisters(Ureg *xp, char *pureg, char *uva, int n)
  578 {
  579         ulong status;
  580 
  581         status = xp->status;
  582         memmove(pureg, uva, n);
  583         xp->status = status;
  584 }
  585 
  586 /* Give enough context in the ureg to produce a kernel stack for
  587  * a sleeping process
  588  */
  589 void
  590 setkernur(Ureg* ureg, Proc* p)
  591 {
  592         ureg->pc = p->sched.pc;
  593         ureg->sp = p->sched.sp+4;
  594 }
  595 
  596 ulong
  597 dbgpc(Proc *p)
  598 {
  599         Ureg *ureg;
  600 
  601         ureg = p->dbgreg;
  602         if(ureg == 0)
  603                 return 0;
  604 
  605         return ureg->pc;
  606 }
  607 
  608 /*
  609  *  system calls
  610  */
  611 #include "../port/systab.h"
  612 
  613 /* TODO: make this trap a separate asm entry point, like on other RISC architectures */
  614 void
  615 syscall(Ureg* ureg)
  616 {
  617         int i;
  618         char *e;
  619         long    ret;
  620         ulong sp, scallnr;
  621 
  622         m->syscall++;
  623         up->insyscall = 1;
  624         up->pc = ureg->pc;
  625         up->dbgreg = ureg;
  626 
  627         if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
  628                 print("fpstate check, entry syscall\n");
  629                 delay(200);
  630                 dumpregs(ureg);
  631                 print("fpstate check, entry syscall\n");
  632         }
  633 
  634         scallnr = ureg->r3;
  635         up->scallnr = ureg->r3;
  636         if(scallnr == RFORK && up->fpstate == FPactive){
  637                 fpsave(&up->fpsave);
  638                 up->fpstate = FPinactive;
  639         }
  640         spllo();
  641 
  642         sp = ureg->usp;
  643         up->nerrlab = 0;
  644         ret = -1;
  645         if(!waserror()){
  646                 if(scallnr >= nsyscall || systab[scallnr] == nil){
  647                         pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc);
  648                         postnote(up, 1, "sys: bad sys call", NDebug);
  649                         error(Ebadarg);
  650                 }
  651 
  652                 if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
  653                         validaddr(sp, sizeof(Sargs)+BY2WD, 0);
  654 
  655                 up->s = *((Sargs*)(sp+BY2WD));
  656                 up->psstate = sysctab[scallnr];
  657 
  658                 ret = systab[scallnr](up->s.args);
  659                 poperror();
  660         }else{
  661                 /* failure: save the error buffer for errstr */
  662                 e = up->syserrstr;
  663                 up->syserrstr = up->errstr;
  664                 up->errstr = e;
  665         }
  666         if(up->nerrlab){
  667                 print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
  668                 print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);
  669                 for(i = 0; i < NERR; i++)
  670                         print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
  671                 panic("error stack");
  672         }
  673 
  674         up->insyscall = 0;
  675         up->psstate = 0;
  676 
  677         /*
  678          *  Put return value in frame.  On the x86 the syscall is
  679          *  just another trap and the return value from syscall is
  680          *  ignored.  On other machines the return value is put into
  681          *  the results register by caller of syscall.
  682          */
  683         ureg->r3 = ret;
  684 
  685         if(scallnr == NOTED)
  686                 noted(ureg, *(ulong*)(sp+BY2WD));
  687 
  688         /* restoreureg must execute at high IPL */
  689         splhi();
  690         if(scallnr!=RFORK)
  691                 notify(ureg);
  692 
  693         if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
  694                 print("fpstate check, exit syscall nr %lud, pid %lud\n", scallnr, up->pid);
  695                 dumpregs(ureg);
  696         }
  697         if(up->fpstate != FPactive)
  698                 ureg->srr1 &= ~MSR_FP;
  699 }
  700 
  701 /*
  702  *  Call user, if necessary, with note.
  703  *  Pass user the Ureg struct and the note on his stack.
  704  */
  705 int
  706 notify(Ureg* ur)
  707 {
  708         int l;
  709         ulong s, sp;
  710         Note *n;
  711 
  712         if(up->procctl)
  713                 procctl(up);
  714         if(up->nnote == 0)
  715                 return 0;
  716 
  717         s = spllo();
  718         qlock(&up->debug);
  719         up->notepending = 0;
  720         n = &up->note[0];
  721         if(strncmp(n->msg, "sys:", 4) == 0){
  722                 l = strlen(n->msg);
  723                 if(l > ERRMAX-15)       /* " pc=0x12345678\0" */
  724                         l = ERRMAX-15;
  725                 sprint(n->msg+l, " pc=0x%.8lux", ur->pc);
  726         }
  727 
  728         if(n->flag!=NUser && (up->notified || up->notify==0)){
  729                 if(n->flag == NDebug)
  730                         pprint("suicide: %s\n", n->msg);
  731                 qunlock(&up->debug);
  732                 pexit(n->msg, n->flag!=NDebug);
  733         }
  734 
  735         if(up->notified) {
  736                 qunlock(&up->debug);
  737                 splhi();
  738                 return 0;
  739         }
  740 
  741         if(!up->notify) {
  742                 qunlock(&up->debug);
  743                 pexit(n->msg, n->flag!=NDebug);
  744         }
  745 
  746         if(up->fpstate == FPactive){
  747                 fpsave(&up->fpsave);
  748                 up->fpstate = FPinactive;
  749         }
  750         up->fpstate |= FPillegal;
  751 
  752         sp = ur->usp & ~(BY2V-1);
  753         sp -= sizeof(Ureg);
  754 
  755         if(!okaddr((ulong)up->notify, BY2WD, 0) ||
  756            !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)) {
  757                 pprint("suicide: bad address or sp in notify\n");
  758                 qunlock(&up->debug);
  759                 pexit("Suicide", 0);
  760         }
  761 
  762         memmove((Ureg*)sp, ur, sizeof(Ureg));
  763         *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
  764         up->ureg = (void*)sp;
  765         sp -= BY2WD+ERRMAX;
  766         memmove((char*)sp, up->note[0].msg, ERRMAX);
  767         sp -= 3*BY2WD;
  768         *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;     /* arg 2 is string */
  769         ur->r1 = (long)up->ureg;                /* arg 1 is ureg* */
  770         ((ulong*)sp)[1] = (ulong)up->ureg;      /* arg 1 0(FP) is ureg* */
  771         ((ulong*)sp)[0] = 0;                    /* arg 0 is pc */
  772         ur->usp = sp;
  773         ur->pc = (ulong)up->notify;
  774         up->notified = 1;
  775         up->nnote--;
  776         memmove(&up->lastnote, &up->note[0], sizeof(Note));
  777         memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
  778 
  779         qunlock(&up->debug);
  780         splx(s);
  781         return 1;
  782 }
  783 
  784 
  785 /*
  786  *   Return user to state before notify()
  787  */
  788 void
  789 noted(Ureg* ureg, ulong arg0)
  790 {
  791         Ureg *nureg;
  792         ulong oureg, sp;
  793 
  794         qlock(&up->debug);
  795         if(arg0!=NRSTR && !up->notified) {
  796                 qunlock(&up->debug);
  797                 pprint("call to noted() when not notified\n");
  798                 pexit("Suicide", 0);
  799         }
  800         up->notified = 0;
  801 
  802         nureg = up->ureg;       /* pointer to user returned Ureg struct */
  803 
  804         /* sanity clause */
  805         oureg = (ulong)nureg;
  806         if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
  807                 pprint("bad ureg in noted or call to noted when not notified\n");
  808                 qunlock(&up->debug);
  809                 pexit("Suicide", 0);
  810         }
  811 
  812         memmove(ureg, nureg, sizeof(Ureg));
  813 
  814         switch(arg0){
  815         case NCONT:
  816         case NRSTR:
  817                 if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){
  818                         pprint("suicide: trap in noted\n");
  819                         qunlock(&up->debug);
  820                         pexit("Suicide", 0);
  821                 }
  822                 up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
  823                 qunlock(&up->debug);
  824                 break;
  825 
  826         case NSAVE:
  827                 if(!okaddr(nureg->pc, BY2WD, 0)
  828                 || !okaddr(nureg->usp, BY2WD, 0)){
  829                         pprint("suicide: trap in noted\n");
  830                         qunlock(&up->debug);
  831                         pexit("Suicide", 0);
  832                 }
  833                 qunlock(&up->debug);
  834                 sp = oureg-4*BY2WD-ERRMAX;
  835                 splhi();
  836                 ureg->sp = sp;
  837                 ((ulong*)sp)[1] = oureg;        /* arg 1 0(FP) is ureg* */
  838                 ((ulong*)sp)[0] = 0;            /* arg 0 is pc */
  839                 break;
  840 
  841         default:
  842                 pprint("unknown noted arg 0x%lux\n", arg0);
  843                 up->lastnote.flag = NDebug;
  844                 /* fall through */
  845                 
  846         case NDFLT:
  847                 if(up->lastnote.flag == NDebug)
  848                         pprint("suicide: %s\n", up->lastnote.msg);
  849                 qunlock(&up->debug);
  850                 pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
  851         }
  852         up->fpstate &= ~FPillegal;
  853         if (up->fpstate == FPactive)
  854                 ureg->srr1 |= MSR_FP;
  855         else
  856                 ureg->srr1 &= ~MSR_FP;
  857 }

Cache object: d2a965dac1ed8b00152eef6859afbf35


[ 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.