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/bitsy/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        "io.h"
    7 #include        "ureg.h"
    8 #include        "../port/error.h"
    9 #include        "tos.h"
   10 
   11 Intrregs *intrregs;
   12 
   13 typedef struct Vctl {
   14         Vctl*   next;                   /* handlers on this vector */
   15         char    *name;          /* of driver, xallocated */
   16         void    (*f)(Ureg*, void*);     /* handler to call */
   17         void*   a;                      /* argument to call it with */
   18 } Vctl;
   19 
   20 static Lock     vctllock;
   21 static Vctl     *vctl[32];
   22 static Vctl     *gpiovctl[27];
   23 static int      gpioirqref[12];
   24 
   25 /*
   26  *   Layout at virtual address 0.
   27  */
   28 typedef struct Vpage0 {
   29         void    (*vectors[8])(void);
   30         ulong   vtable[8];
   31 } Vpage0;
   32 Vpage0 *vpage0;
   33 
   34 static int      irq(Ureg*);
   35 static void     gpiointr(Ureg*, void*);
   36 
   37 /* recover state after power suspend
   38  * NB: to help debugging bad suspend code,
   39  *     I changed some prints below to iprints,
   40  *     to avoid deadlocks when a panic is being
   41  *     issued during the suspend/resume handler.
   42  */
   43 void
   44 trapresume(void)
   45 {
   46         vpage0 = (Vpage0*)EVECTORS;
   47         memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
   48         memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
   49         wbflush();
   50         mappedIvecEnable();
   51 }
   52 
   53 /*
   54  *  set up for exceptions
   55  */
   56 void
   57 trapinit(void)
   58 {
   59         /* set up the exception vectors */
   60         vpage0 = (Vpage0*)EVECTORS;
   61         memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
   62         memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
   63 
   64         wbflush();
   65 
   66         /* use exception vectors at 0xFFFF0000 */
   67         mappedIvecEnable();
   68 
   69         /* set up the stacks for the interrupt modes */
   70         setr13(PsrMfiq, m->sfiq);
   71         setr13(PsrMirq, m->sirq);
   72         setr13(PsrMabt, m->sabt);
   73         setr13(PsrMund, m->sund);
   74 
   75         /* map in interrupt registers */
   76         intrregs = mapspecial(INTRREGS, sizeof(*intrregs));
   77 
   78         /* make all interrupts IRQ (i.e. not FIQ) and disable all interrupts */
   79         intrregs->iclr = 0;
   80         intrregs->icmr = 0;
   81 
   82         /* turn off all gpio interrupts */
   83         gpioregs->rising = 0;
   84         gpioregs->falling = 0;
   85         gpioregs->edgestatus = gpioregs->edgestatus;
   86 
   87         /* allow all enabled interrupts to take processor out of sleep mode */
   88         intrregs->iccr = 0;
   89 }
   90 
   91 void
   92 trapdump(char *tag)
   93 {
   94         iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n",
   95                 tag, intrregs->icip, intrregs->icmr, intrregs->iclr,
   96                 intrregs->iccr, intrregs->icfp);
   97 }
   98 
   99 void
  100 warnregs(Ureg *ur, char *tag)
  101 {
  102         char buf[1024];
  103         char *e = buf+sizeof(buf);
  104         char *p;
  105 
  106         p = seprint(buf, e, "%s:\n", tag);
  107         p = seprint(p, e, "type 0x%.8lux psr 0x%.8lux pc 0x%.8lux\n",
  108                 ur->type, ur->psr, ur->pc);
  109         p = seprint(p, e, "r0  0x%.8lux r1  0x%.8lux r2  0x%.8lux r3  0x%.8lux\n",
  110                 ur->r0, ur->r1, ur->r2, ur->r3);
  111         p = seprint(p, e, "r4  0x%.8lux r5  0x%.8lux r6  0x%.8lux r7  0x%.8lux\n",
  112                 ur->r4, ur->r5, ur->r6, ur->r7);
  113         p = seprint(p, e, "r8  0x%.8lux r9  0x%.8lux r10 0x%.8lux r11 0x%.8lux\n",
  114                 ur->r8, ur->r9, ur->r10, ur->r11);
  115         seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n",
  116                 ur->r12, ur->r13, ur->r14);
  117         iprint("%s", buf);
  118 }
  119 
  120 /*
  121  *  enable an irq interrupt
  122  */
  123 static void
  124 irqenable(int irq, IntrHandler *f, void* a, char *name)
  125 {
  126         Vctl *v;
  127 
  128         if(irq >= nelem(vctl) || irq < 0)
  129                 panic("intrenable");
  130 
  131         v = malloc(sizeof(Vctl));
  132         v->f = f;
  133         v->a = a;
  134         v->name = xalloc(strlen(name)+1);
  135         strcpy(v->name, name);
  136 
  137         lock(&vctllock);
  138         v->next = vctl[irq];
  139         vctl[irq] = v;
  140         intrregs->icmr |= 1<<irq;
  141         unlock(&vctllock);
  142 }
  143 
  144 /*
  145  *  disable an irq interrupt
  146  */
  147 static void
  148 irqdisable(int irq, IntrHandler *f, void* a, char *name)
  149 {
  150         Vctl **vp, *v;
  151 
  152         if(irq >= nelem(vctl) || irq < 0)
  153                 panic("intrdisable");
  154 
  155         lock(&vctllock);
  156         for(vp = &vctl[irq]; v = *vp; vp = &v->next)
  157                 if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
  158                         print("irqdisable: remove %s\n", name);
  159                         *vp = v->next;
  160                         free(v);
  161                         break;
  162                 }
  163         if (v == nil)
  164                 print("irqdisable: irq %d, name %s not enabled\n", irq, name);
  165         if (vctl[irq] == nil){
  166                 print("irqdisable: clear icmr bit %d\n", irq);
  167                 intrregs->icmr &= ~(1<<irq);
  168         }
  169         unlock(&vctllock);
  170 }
  171 
  172 /*
  173  *  enable an interrupt
  174  */
  175 void
  176 intrenable(int type, int which, IntrHandler *f, void* a, char *name)
  177 {
  178         int irq;
  179         Vctl *v;
  180 
  181         if(type == IRQ){
  182                 irqenable(which, f, a, name);
  183                 return;
  184         }
  185 
  186         /* from here down, it must be a GPIO edge interrupt */
  187         irq = which;
  188         if(which >= nelem(gpiovctl) || which < 0)
  189                 panic("intrenable");
  190         if(which > 11)
  191                 irq = 11;
  192 
  193         /* the pin had better be configured as input */
  194         if((1<<which) & gpioregs->direction)
  195                 panic("intrenable of output pin %d", which);
  196 
  197         /* create a second level vctl for the gpio edge interrupt */
  198         v = malloc(sizeof(Vctl));
  199         v->f = f;
  200         v->a = a;
  201         v->name = xalloc(strlen(name)+1);
  202         strcpy(v->name, name);
  203 
  204         lock(&vctllock);
  205         v->next = gpiovctl[which];
  206         gpiovctl[which] = v;
  207 
  208         /* set edge register to enable interrupt */
  209         switch(type){
  210         case GPIOboth:
  211                 gpioregs->rising |= 1<<which;
  212                 gpioregs->falling |= 1<<which;
  213                 break;
  214         case GPIOfalling:
  215                 gpioregs->falling |= 1<<which;
  216                 break;
  217         case GPIOrising:
  218                 gpioregs->rising |= 1<<which;
  219                 break;
  220         }
  221         unlock(&vctllock);
  222         /* point the irq to the gpio interrupt handler */
  223         if(gpioirqref[irq]++ == 0)
  224                 irqenable(irq, gpiointr, nil, "gpio edge");
  225 }
  226 
  227 /*
  228  *  disable an interrupt
  229  */
  230 void
  231 intrdisable(int type, int which, IntrHandler *f, void* a, char *name)
  232 {
  233         int irq;
  234         Vctl **vp, *v;
  235 
  236 
  237         if(type == IRQ){
  238                 irqdisable(which, f, a, name);
  239                 return;
  240         }
  241 
  242         /* from here down, it must be a GPIO edge interrupt */
  243         irq = which;
  244         if(which >= nelem(gpiovctl) || which < 0)
  245                 panic("intrdisable");
  246         if(which > 11)
  247                 irq = 11;
  248 
  249         lock(&vctllock);
  250         for(vp = &gpiovctl[which]; v = *vp; vp = &v->next)
  251                 if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
  252                         break;
  253                 }
  254         if (gpiovctl[which] == nil){
  255                 /* set edge register to enable interrupt */
  256                 switch(type){
  257                 case GPIOboth:
  258                         print("intrdisable: gpio-rising+falling clear bit %d\n", which);
  259                         gpioregs->rising &= ~(1<<which);
  260                         gpioregs->falling &= ~(1<<which);
  261                         break;
  262                 case GPIOfalling:
  263                         print("intrdisable: gpio-falling clear bit %d\n", which);
  264                         gpioregs->falling &= ~(1<<which);
  265                         break;
  266                 case GPIOrising:
  267                         print("intrdisable: gpio-rising clear bit %d\n", which);
  268                         gpioregs->rising &= ~(1<<which);
  269                         break;
  270                 }
  271         
  272         }
  273         if (v) {
  274                 print("intrdisable: removing %s\n", name);
  275                 *vp = v->next;
  276         }else
  277                 print("intrdisable: which %d, name %s not enabled\n", which, name);
  278         unlock(&vctllock);
  279         /* disable the gpio interrupt handler if necessary */
  280         if(--gpioirqref[irq] == 0){
  281                 print("intrdisable: inrqdisable gpiointr\n");
  282                 irqdisable(irq, gpiointr, nil, "gpio edge");
  283         }
  284         free(v);
  285 }
  286 
  287 /*
  288  *  called by trap to handle access faults
  289  */
  290 static void
  291 faultarm(Ureg *ureg, ulong va, int user, int read)
  292 {
  293         int n, insyscall;
  294         char buf[ERRMAX];
  295 
  296         if (up == nil) {
  297                 warnregs(ureg, "kernel fault");
  298                 panic("fault: nil up in faultarm, accessing 0x%lux", va);
  299         }
  300         insyscall = up->insyscall;
  301         up->insyscall = 1;
  302         n = fault(va, read);
  303         if(n < 0){
  304                 if(!user){
  305                         warnregs(ureg, "kernel fault");
  306                         panic("fault: kernel accessing 0x%lux", va);
  307                 }
  308 //              warnregs(ureg, "user fault");
  309                 sprint(buf, "sys: trap: fault %s va=0x%lux", read ? "read" : "write", va);
  310                 postnote(up, 1, buf, NDebug);
  311         }
  312         up->insyscall = insyscall;
  313 }
  314 
  315 /*
  316  *  returns 1 if the instruction writes memory, 0 otherwise
  317  */
  318 int
  319 writetomem(ulong inst)
  320 {
  321         /* swap always write memory */
  322         if((inst & 0x0FC00000) == 0x01000000)
  323                 return 1;
  324 
  325         /* loads and stores are distinguished by bit 20 */
  326         if(inst & (1<<20))
  327                 return 0;
  328 
  329         return 1;
  330 }
  331 
  332 
  333 /*
  334  *  here on all exceptions other than syscall (SWI)
  335  */
  336 void
  337 trap(Ureg *ureg)
  338 {
  339         ulong inst;
  340         int clockintr, user, x, rv;
  341         ulong va, fsr;
  342         char buf[ERRMAX];
  343         int rem;
  344 
  345         if(up != nil)
  346                 rem = ((char*)ureg)-up->kstack;
  347         else
  348                 rem = ((char*)ureg)-((char*)(MACHADDR+sizeof(Mach)));
  349         if(rem < 256) {
  350                 dumpstack();
  351                 panic("trap %d bytes remaining, up = %#p, ureg = %#p, at pc 0x%lux",
  352                         rem, up, ureg, ureg->pc);
  353         }
  354 
  355         user = (ureg->psr & PsrMask) == PsrMusr;
  356 
  357         /*
  358          * All interrupts/exceptions should be resumed at ureg->pc-4,
  359          * except for Data Abort which resumes at ureg->pc-8.
  360          */
  361         if(ureg->type == (PsrMabt+1))
  362                 ureg->pc -= 8;
  363         else
  364                 ureg->pc -= 4;
  365 
  366         clockintr = 0;
  367         switch(ureg->type){
  368         default:
  369                 panic("unknown trap");
  370                 break;
  371         case PsrMirq:
  372                 clockintr = irq(ureg);
  373                 break;
  374         case PsrMabt:   /* prefetch fault */
  375                 faultarm(ureg, ureg->pc, user, 1);
  376                 break;
  377         case PsrMabt+1: /* data fault */
  378                 va = getfar();
  379                 inst = *(ulong*)(ureg->pc);
  380                 fsr = getfsr() & 0xf;
  381                 switch(fsr){
  382                 case 0x0:
  383                         panic("vector exception at %lux", ureg->pc);
  384                         break;
  385                 case 0x1:
  386                 case 0x3:
  387                         if(user){
  388                                 snprint(buf, sizeof(buf), "sys: alignment: pc 0x%lux va 0x%lux\n",
  389                                         ureg->pc, va);
  390                                 postnote(up, 1, buf, NDebug);
  391                         } else
  392                                 panic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va);
  393                         break;
  394                 case 0x2:
  395                         panic("terminal exception at %lux", ureg->pc);
  396                         break;
  397                 case 0x4:
  398                 case 0x6:
  399                 case 0x8:
  400                 case 0xa:
  401                 case 0xc:
  402                 case 0xe:
  403                         panic("external abort 0x%lux pc 0x%lux addr 0x%lux", fsr, ureg->pc, va);
  404                         break;
  405                 case 0x5:
  406                 case 0x7:
  407                         /* translation fault, i.e., no pte entry */
  408                         faultarm(ureg, va, user, !writetomem(inst));
  409                         break;
  410                 case 0x9:
  411                 case 0xb:
  412                         /* domain fault, accessing something we shouldn't */
  413                         if(user){
  414                                 sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n",
  415                                         ureg->pc, va);
  416                                 postnote(up, 1, buf, NDebug);
  417                         } else
  418                                 panic("kernel access violation: pc 0x%lux va 0x%lux",
  419                                         ureg->pc, va);
  420                         break;
  421                 case 0xd:
  422                 case 0xf:
  423                         /* permission error, copy on write or real permission error */
  424                         faultarm(ureg, va, user, !writetomem(inst));
  425                         break;
  426                 }
  427                 break;
  428         case PsrMund:   /* undefined instruction */
  429                 if (user) {
  430                         /* look for floating point instructions to interpret */
  431                         x = spllo();
  432                         rv = fpiarm(ureg);
  433                         splx(x);
  434                         if (rv == 0) {
  435                                 sprint(buf, "undefined instruction: pc 0x%lux\n", ureg->pc);
  436                                 postnote(up, 1, buf, NDebug);
  437                         }
  438                 }else{
  439                         iprint("undefined instruction: pc=0x%lux, inst=0x%lux, 0x%lux, 0x%lux, 0x%lux, 0x%lux\n", ureg->pc, ((ulong*)ureg->pc)[-2], ((ulong*)ureg->pc)[-1], ((ulong*)ureg->pc)[0], ((ulong*)ureg->pc)[1], ((ulong*)ureg->pc)[2]);
  440                         panic("undefined instruction");
  441                 }
  442                 break;
  443         }
  444         splhi();
  445 
  446         /* delaysched set because we held a lock or because our quantum ended */
  447         if(up && up->delaysched && clockintr){
  448                 sched();
  449                 splhi();
  450         }
  451 
  452         if(user){
  453                 if(up->procctl || up->nnote)
  454                         notify(ureg);
  455                 kexit(ureg);
  456         }
  457 }
  458 
  459 /*
  460  *  here on irq's
  461  */
  462 static int
  463 irq(Ureg *ur)
  464 {
  465         ulong va;
  466         int clockintr, i;
  467         Vctl *v;
  468 
  469         va = intrregs->icip;
  470 
  471         if(va & (1<<IRQtimer0))
  472                 clockintr = 1;
  473         else
  474                 clockintr = 0;
  475         for(i = 0; i < 32; i++){
  476                 if(((1<<i) & va) == 0)
  477                         continue;
  478                 for(v = vctl[i]; v != nil; v = v->next){
  479                         v->f(ur, v->a);
  480                         va &= ~(1<<i);
  481                 }
  482         }
  483         if(va)
  484                 print("unknown interrupt: %lux\n", va);
  485 
  486         return clockintr;
  487 }
  488 
  489 /*
  490  *  here on gpio interrupts
  491  */
  492 static void
  493 gpiointr(Ureg *ur, void*)
  494 {
  495         ulong va;
  496         int i;
  497         Vctl *v;
  498 
  499         va = gpioregs->edgestatus;
  500         gpioregs->edgestatus = va;
  501 
  502         for(i = 0; i < 27; i++){
  503                 if(((1<<i) & va) == 0)
  504                         continue;
  505                 for(v = gpiovctl[i]; v != nil; v = v->next){
  506                         v->f(ur, v->a);
  507                         va &= ~(1<<i);
  508                 }
  509         }
  510         if(va)
  511                 print("unknown gpio interrupt: %lux\n", va);
  512 }
  513 
  514 /*
  515  *  system calls
  516  */
  517 #include "../port/systab.h"
  518 
  519 /*
  520  *  Syscall is called directly from assembler without going through trap().
  521  */
  522 void
  523 syscall(Ureg* ureg)
  524 {
  525         char *e;
  526         ulong   sp;
  527         long    ret;
  528         int     i, scallnr;
  529 
  530         if((ureg->psr & PsrMask) != PsrMusr) {
  531                 panic("syscall: pc 0x%lux r14 0x%lux cs 0x%lux", ureg->pc, ureg->r14, ureg->psr);
  532         }
  533 
  534         m->syscall++;
  535         up->insyscall = 1;
  536         up->pc = ureg->pc;
  537         up->dbgreg = ureg;
  538 
  539         scallnr = ureg->r0;
  540         up->scallnr = scallnr;
  541         spllo();
  542 
  543         sp = ureg->sp;
  544         up->nerrlab = 0;
  545         ret = -1;
  546         if(!waserror()){
  547                 if(scallnr >= nsyscall){
  548                         pprint("bad sys call number %d pc %lux\n",
  549                                 scallnr, ureg->pc);
  550                         postnote(up, 1, "sys: bad sys call", NDebug);
  551                         error(Ebadarg);
  552                 }
  553 
  554                 if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
  555                         validaddr(sp, sizeof(Sargs)+BY2WD, 0);
  556 
  557                 up->s = *((Sargs*)(sp+BY2WD));
  558                 up->psstate = sysctab[scallnr];
  559 
  560                 ret = systab[scallnr](up->s.args);
  561                 poperror();
  562         }else{
  563                 /* failure: save the error buffer for errstr */
  564                 e = up->syserrstr;
  565                 up->syserrstr = up->errstr;
  566                 up->errstr = e;
  567         }
  568         if(up->nerrlab){
  569                 print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
  570                 for(i = 0; i < NERR; i++)
  571                         print("sp=%lux pc=%lux\n",
  572                                 up->errlab[i].sp, up->errlab[i].pc);
  573                 panic("error stack");
  574         }
  575 
  576         up->insyscall = 0;
  577         up->psstate = 0;
  578 
  579         /*
  580          *  Put return value in frame.  On the x86 the syscall is
  581          *  just another trap and the return value from syscall is
  582          *  ignored.  On other machines the return value is put into
  583          *  the results register by caller of syscall.
  584          */
  585         ureg->r0 = ret;
  586 
  587         if(scallnr == NOTED)
  588                 noted(ureg, *(ulong*)(sp+BY2WD));
  589 
  590         if(up->delaysched)
  591                 sched();
  592 
  593         splhi();
  594         if(scallnr != RFORK && (up->procctl || up->nnote))
  595                 notify(ureg);
  596 }
  597 
  598 /*
  599  *   Return user to state before notify()
  600  */
  601 void
  602 noted(Ureg* ureg, ulong arg0)
  603 {
  604         Ureg *nureg;
  605         ulong oureg, sp;
  606 
  607         qlock(&up->debug);
  608         if(arg0!=NRSTR && !up->notified) {
  609                 qunlock(&up->debug);
  610                 pprint("call to noted() when not notified\n");
  611                 pexit("Suicide", 0);
  612         }
  613         up->notified = 0;
  614 
  615         nureg = up->ureg;       /* pointer to user returned Ureg struct */
  616 
  617         /* sanity clause */
  618         oureg = (ulong)nureg;
  619         if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
  620                 pprint("bad ureg in noted or call to noted when not notified\n");
  621                 qunlock(&up->debug);
  622                 pexit("Suicide", 0);
  623         }
  624 
  625         /* don't let user change system flags */
  626         nureg->psr = (ureg->psr & ~(PsrMask|PsrDfiq|PsrDirq)) |
  627                         (nureg->psr & (PsrMask|PsrDfiq|PsrDirq));
  628 
  629         memmove(ureg, nureg, sizeof(Ureg));
  630 
  631         switch(arg0){
  632         case NCONT:
  633         case NRSTR:
  634                 if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->sp, BY2WD, 0)){
  635                         qunlock(&up->debug);
  636                         pprint("suicide: trap in noted\n");
  637                         pexit("Suicide", 0);
  638                 }
  639                 up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
  640                 qunlock(&up->debug);
  641                 break;
  642 
  643         case NSAVE:
  644                 if(!okaddr(nureg->pc, BY2WD, 0)
  645                 || !okaddr(nureg->sp, BY2WD, 0)){
  646                         qunlock(&up->debug);
  647                         pprint("suicide: trap in noted\n");
  648                         pexit("Suicide", 0);
  649                 }
  650                 qunlock(&up->debug);
  651                 sp = oureg-4*BY2WD-ERRMAX;
  652                 splhi();
  653                 ureg->sp = sp;
  654                 ((ulong*)sp)[1] = oureg;        /* arg 1 0(FP) is ureg* */
  655                 ((ulong*)sp)[0] = 0;            /* arg 0 is pc */
  656                 break;
  657 
  658         default:
  659                 pprint("unknown noted arg 0x%lux\n", arg0);
  660                 up->lastnote.flag = NDebug;
  661                 /* fall through */
  662                 
  663         case NDFLT:
  664                 if(up->lastnote.flag == NDebug){ 
  665                         qunlock(&up->debug);
  666                         pprint("suicide: %s\n", up->lastnote.msg);
  667                 } else
  668                         qunlock(&up->debug);
  669                 pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
  670         }
  671 }
  672 
  673 /*
  674  *  Call user, if necessary, with note.
  675  *  Pass user the Ureg struct and the note on his stack.
  676  */
  677 int
  678 notify(Ureg* ureg)
  679 {
  680         int l;
  681         ulong s, sp;
  682         Note *n;
  683 
  684         if(up->procctl)
  685                 procctl(up);
  686         if(up->nnote == 0)
  687                 return 0;
  688 
  689         s = spllo();
  690         qlock(&up->debug);
  691         up->notepending = 0;
  692         n = &up->note[0];
  693         if(strncmp(n->msg, "sys:", 4) == 0){
  694                 l = strlen(n->msg);
  695                 if(l > ERRMAX-15)       /* " pc=0x12345678\0" */
  696                         l = ERRMAX-15;
  697                 sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
  698         }
  699 
  700         if(n->flag!=NUser && (up->notified || up->notify==0)){
  701                 if(n->flag == NDebug)
  702                         pprint("suicide: %s\n", n->msg);
  703                 qunlock(&up->debug);
  704                 pexit(n->msg, n->flag!=NDebug);
  705         }
  706 
  707         if(up->notified) {
  708                 qunlock(&up->debug);
  709                 splhi();
  710                 return 0;
  711         }
  712                 
  713         if(!up->notify){
  714                 qunlock(&up->debug);
  715                 pexit(n->msg, n->flag!=NDebug);
  716         }
  717         sp = ureg->sp;
  718         sp -= sizeof(Ureg);
  719 
  720         if(!okaddr((ulong)up->notify, 1, 0)
  721         || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)){
  722                 pprint("suicide: bad address in notify\n");
  723                 qunlock(&up->debug);
  724                 pexit("Suicide", 0);
  725         }
  726 
  727         up->ureg = (void*)sp;
  728         memmove((Ureg*)sp, ureg, sizeof(Ureg));
  729         *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
  730         up->ureg = (void*)sp;
  731         sp -= BY2WD+ERRMAX;
  732         memmove((char*)sp, up->note[0].msg, ERRMAX);
  733         sp -= 3*BY2WD;
  734         *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;     /* arg 2 is string */
  735         *(ulong*)(sp+1*BY2WD) = (ulong)up->ureg;        /* arg 1 is ureg* */
  736         *(ulong*)(sp+0*BY2WD) = 0;              /* arg 0 is pc */
  737         ureg->sp = sp;
  738         ureg->pc = (ulong)up->notify;
  739         up->notified = 1;
  740         up->nnote--;
  741         memmove(&up->lastnote, &up->note[0], sizeof(Note));
  742         memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
  743 
  744         qunlock(&up->debug);
  745         splx(s);
  746         return 1;
  747 }
  748 
  749 /* Give enough context in the ureg to produce a kernel stack for
  750  * a sleeping process
  751  */
  752 void
  753 setkernur(Ureg *ureg, Proc *p)
  754 {
  755         ureg->pc = p->sched.pc;
  756         ureg->sp = p->sched.sp+4;
  757         ureg->r14 = (ulong)sched;
  758 }
  759 
  760 /*
  761  *  return the userpc the last exception happened at
  762  */
  763 ulong
  764 userpc(void)
  765 {
  766         Ureg *ureg;
  767 
  768         ureg = (Ureg*)up->dbgreg;
  769         return ureg->pc;
  770 }
  771 
  772 /* This routine must save the values of registers the user is not permitted
  773  * to write from devproc and then restore the saved values before returning.
  774  */
  775 void
  776 setregisters(Ureg* ureg, char* pureg, char* uva, int n)
  777 {
  778         USED(ureg, pureg, uva, n);
  779 }
  780 
  781 /*
  782  *  this is the body for all kproc's
  783  */
  784 static void
  785 linkproc(void)
  786 {
  787         spllo();
  788         up->kpfun(up->kparg);
  789         pexit("kproc exiting", 0);
  790 }
  791 
  792 /*
  793  *  setup stack and initial PC for a new kernel proc.  This is architecture
  794  *  dependent because of the starting stack location
  795  */
  796 void
  797 kprocchild(Proc *p, void (*func)(void*), void *arg)
  798 {
  799         p->sched.pc = (ulong)linkproc;
  800         p->sched.sp = (ulong)p->kstack+KSTACK;
  801 
  802         p->kpfun = func;
  803         p->kparg = arg;
  804 }
  805 
  806 
  807 /* 
  808  *  Craft a return frame which will cause the child to pop out of
  809  *  the scheduler in user mode with the return register zero.  Set
  810  *  pc to point to a l.s return function.
  811  */
  812 void
  813 forkchild(Proc *p, Ureg *ureg)
  814 {
  815         Ureg *cureg;
  816 
  817 //print("%lud setting up for forking child %lud\n", up->pid, p->pid);
  818         p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg);
  819         p->sched.pc = (ulong)forkret;
  820 
  821         cureg = (Ureg*)(p->sched.sp);
  822         memmove(cureg, ureg, sizeof(Ureg));
  823 
  824         /* syscall returns 0 for child */
  825         cureg->r0 = 0;
  826 
  827         /* Things from bottom of syscall which were never executed */
  828         p->psstate = 0;
  829         p->insyscall = 0;
  830 }
  831 
  832 /*
  833  *  setup stack, initial PC, and any arch dependent regs for an execing user proc.
  834  */
  835 long
  836 execregs(ulong entry, ulong ssize, ulong nargs)
  837 {
  838         ulong *sp;
  839         Ureg *ureg;
  840 
  841         sp = (ulong*)(USTKTOP - ssize);
  842         *--sp = nargs;
  843 
  844         ureg = up->dbgreg;
  845         memset(ureg, 0, 15*sizeof(ulong));
  846         ureg->r13 = (ulong)sp;
  847         ureg->pc = entry;
  848 //print("%lud: EXECREGS pc 0x%lux sp 0x%lux\n", up->pid, ureg->pc, ureg->r13);
  849         return USTKTOP-sizeof(Tos);             /* address of kernel/user shared data */
  850 }
  851 
  852 /*
  853  * Fill in enough of Ureg to get a stack trace, and call a function.
  854  * Used by debugging interface rdb.
  855  */
  856 void
  857 callwithureg(void (*fn)(Ureg*))
  858 {
  859         Ureg ureg;
  860         ureg.pc = getcallerpc(&fn);
  861         ureg.sp = (ulong)&fn;
  862         fn(&ureg);
  863 }
  864 
  865 static void
  866 _dumpstack(Ureg *ureg)
  867 {
  868         ulong l, v, i;
  869         ulong *p;
  870         extern ulong etext;
  871 
  872         if(up == 0){
  873                 iprint("no current proc\n");
  874                 return;
  875         }
  876 
  877         iprint("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14);
  878         i = 0;
  879         for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){
  880                 v = *(ulong*)l;
  881                 if(KTZERO < v && v < (ulong)&etext && (v&3)==0){
  882                         v -= 4;
  883                         p = (ulong*)v;
  884                         if((*p & 0x0f000000) == 0x0b000000){
  885                                 iprint("%.8lux=%.8lux ", l, v);
  886                                 i++;
  887                         }
  888                 }
  889                 if(i == 4){
  890                         i = 0;
  891                         iprint("\n");
  892                 }
  893         }
  894         if(i)
  895                 iprint("\n");
  896 }
  897 
  898 void
  899 dumpstack(void)
  900 {
  901         callwithureg(_dumpstack);
  902 }
  903 
  904 /*
  905  *  pc output by ps
  906  */
  907 ulong
  908 dbgpc(Proc *p)
  909 {
  910         Ureg *ureg;
  911 
  912         ureg = p->dbgreg;
  913         if(ureg == 0)
  914                 return 0;
  915 
  916         return ureg->pc;
  917 }
  918 
  919 /*
  920  * called in sysfile.c
  921  */
  922 void
  923 evenaddr(ulong addr)
  924 {
  925         if(addr & 3){
  926                 postnote(up, 1, "sys: odd address", NDebug);
  927                 error(Ebadarg);
  928         }
  929 }

Cache object: 61ccc26a41fddab4db042b360c564319


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