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/mtx/trap.c

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

Cache object: fb2c04e644b5ef3d7fddf6d147b93392


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