]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/port/devcons.c
kernel: avoid selecting the boot process in killbig()
[plan9front.git] / sys / src / 9 / port / devcons.c
index 8ede174f082d8f1b7444c330dc97a3ee03a4b9b2..551e4b5b27fc182a191626ea08fd1dfbd16470b3 100644 (file)
@@ -4,15 +4,12 @@
 #include       "dat.h"
 #include       "fns.h"
 #include       "../port/error.h"
-#include       "pool.h"
 
 #include       <authsrv.h>
 
 void   (*consdebug)(void) = nil;
 void   (*screenputs)(char*, int) = nil;
 
-Queue* kbdq;                   /* unprocessed console input */
-Queue* lineq;                  /* processed console input */
 Queue* serialoq;               /* serial console output */
 Queue* kprintoq;               /* console output, for /dev/kprint */
 ulong  kprintinuse;            /* test and set whether /dev/kprint is open */
@@ -20,34 +17,9 @@ int  iprintscreenputs = 1;
 
 int    panicking;
 
-static struct
-{
-       QLock;
-
-       int     raw;            /* true if we shouldn't process input */
-       Ref     ctl;            /* number of opens to the control file */
-       int     x;              /* index into line */
-       char    line[1024];     /* current input line */
-
-       int     count;
-       int     ctlpoff;
-
-       /* a place to save up characters at interrupt time before dumping them in the queue */
-       Lock    lockputc;
-       char    istage[1024];
-       char    *iw;
-       char    *ir;
-       char    *ie;
-} kbd = {
-       .iw     = kbd.istage,
-       .ir     = kbd.istage,
-       .ie     = kbd.istage + sizeof(kbd.istage),
-};
-
 char   *sysname;
 vlong  fasthz;
 
-static void    seedrand(void);
 static int     readtime(ulong, char*, int);
 static int     readbintime(char*, int);
 static int     writetime(char*, int);
@@ -55,25 +27,21 @@ static int  writebintime(char*, int);
 
 enum
 {
-       CMhalt,
        CMreboot,
        CMpanic,
+       CMrdb,
 };
 
 Cmdtab rebootmsg[] =
 {
-       CMhalt,         "halt",         1,
        CMreboot,       "reboot",       0,
        CMpanic,        "panic",        0,
+       CMrdb,          "rdb",          0,
 };
 
 void
 printinit(void)
 {
-       lineq = qopen(2*1024, 0, nil, nil);
-       if(lineq == nil)
-               panic("printinit");
-       qnoblock(lineq, 1);
 }
 
 int
@@ -95,17 +63,6 @@ prflush(void)
                        break;
 }
 
-/*
- * Log console output so it can be retrieved via /dev/kmesg.
- * This is good for catching boot-time messages after the fact.
- */
-struct {
-       Lock lk;
-//     char buf[16384];                /* normal */
-       char buf[256*1024];             /* for acpi debugging */
-       uint n;
-} kmesg;
-
 static void
 kmesgputs(char *str, int n)
 {
@@ -146,9 +103,7 @@ putstrn0(char *str, int n, int usewrite)
 {
        int m;
        char *t;
-
-       if(!islo())
-               usewrite = 0;
+       int (*wq)(Queue*, void*, int);
 
        /*
         *  how many different output devices do we need?
@@ -164,12 +119,10 @@ putstrn0(char *str, int n, int usewrite)
         *  if there's a serial line being used as a console,
         *  put the message there.
         */
-       if(kprintoq != nil && !qisclosed(kprintoq)){
-               if(usewrite)
-                       qwrite(kprintoq, str, n);
-               else
-                       qiwrite(kprintoq, str, n);
-       }else if(screenputs != nil)
+       wq = usewrite && islo() ? qwrite : qiwrite;
+       if(kprintoq != nil && !qisclosed(kprintoq))
+               (*wq)(kprintoq, str, n);
+       else if(screenputs != nil)
                screenputs(str, n);
 
        if(serialoq == nil){
@@ -179,22 +132,14 @@ putstrn0(char *str, int n, int usewrite)
 
        while(n > 0) {
                t = memchr(str, '\n', n);
-               if(t && !kbd.raw) {
+               if(t != nil) {
                        m = t-str;
-                       if(usewrite){
-                               qwrite(serialoq, str, m);
-                               qwrite(serialoq, "\r\n", 2);
-                       } else {
-                               qiwrite(serialoq, str, m);
-                               qiwrite(serialoq, "\r\n", 2);
-                       }
+                       (*wq)(serialoq, str, m);
+                       (*wq)(serialoq, "\r\n", 2);
                        n -= m+1;
                        str = t+1;
                } else {
-                       if(usewrite)
-                               qwrite(serialoq, str, n);
-                       else
-                               qiwrite(serialoq, str, n);
+                       (*wq)(serialoq, str, n);
                        break;
                }
        }
@@ -206,8 +151,6 @@ putstrn(char *str, int n)
        putstrn0(str, n, 0);
 }
 
-int noprint;
-
 int
 print(char *fmt, ...)
 {
@@ -215,9 +158,6 @@ print(char *fmt, ...)
        va_list arg;
        char buf[PRINTSIZE];
 
-       if(noprint)
-               return -1;
-
        va_start(arg, fmt);
        n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
        va_end(arg);
@@ -273,7 +213,7 @@ iprint(char *fmt, ...)
 void
 panic(char *fmt, ...)
 {
-       int n, s;
+       int s;
        va_list arg;
        char buf[PRINTSIZE];
 
@@ -286,18 +226,23 @@ panic(char *fmt, ...)
        s = splhi();
        strcpy(buf, "panic: ");
        va_start(arg, fmt);
-       n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
+       vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
        va_end(arg);
        iprint("%s\n", buf);
        if(consdebug)
                (*consdebug)();
        splx(s);
        prflush();
-       buf[n] = '\n';
-       putstrn(buf, n+1);
        dumpstack();
 
-       exit(1);
+       /* reboot cpu servers and headless machines when not debugging */
+       if(getconf("*debug") == nil)
+       if(cpuserver || !conf.monitor)
+               exit(1);
+
+       /* otherwise, just hang */
+       while(islo()) idlehands();
+       for(;;);
 }
 
 /* libmp at least contains a few calls to sysfatal; simulate with panic */
@@ -331,7 +276,7 @@ pprint(char *fmt, ...)
                return 0;
 
        c = up->fgrp->fd[2];
-       if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
+       if(c==nil || (c->flag&CMSG)!=0 || (c->mode!=OWRITE && c->mode!=ORDWR))
                return 0;
        n = snprint(buf, sizeof buf, "%s %lud: ", up->text, up->pid);
        va_start(arg, fmt);
@@ -350,226 +295,6 @@ pprint(char *fmt, ...)
        return n;
 }
 
-static void
-echoscreen(char *buf, int n)
-{
-       char *e, *p;
-       char ebuf[128];
-       int x;
-
-       p = ebuf;
-       e = ebuf + sizeof(ebuf) - 4;
-       while(n-- > 0){
-               if(p >= e){
-                       screenputs(ebuf, p - ebuf);
-                       p = ebuf;
-               }
-               x = *buf++;
-               if(x == 0x15){
-                       *p++ = '^';
-                       *p++ = 'U';
-                       *p++ = '\n';
-               } else
-                       *p++ = x;
-       }
-       if(p != ebuf)
-               screenputs(ebuf, p - ebuf);
-}
-
-static void
-echoserialoq(char *buf, int n)
-{
-       char *e, *p;
-       char ebuf[128];
-       int x;
-
-       p = ebuf;
-       e = ebuf + sizeof(ebuf) - 4;
-       while(n-- > 0){
-               if(p >= e){
-                       qiwrite(serialoq, ebuf, p - ebuf);
-                       p = ebuf;
-               }
-               x = *buf++;
-               if(x == '\n'){
-                       *p++ = '\r';
-                       *p++ = '\n';
-               } else if(x == 0x15){
-                       *p++ = '^';
-                       *p++ = 'U';
-                       *p++ = '\n';
-               } else
-                       *p++ = x;
-       }
-       if(p != ebuf)
-               qiwrite(serialoq, ebuf, p - ebuf);
-}
-
-static void
-echo(char *buf, int n)
-{
-       static int ctrlt, pid;
-       int x;
-       char *e, *p;
-
-       if(n == 0)
-               return;
-
-       e = buf+n;
-       for(p = buf; p < e; p++){
-               switch(*p){
-               case 0x10:      /* ^P */
-                       if(cpuserver && !kbd.ctlpoff){
-                               active.exiting = 1;
-                               return;
-                       }
-                       break;
-               case 0x14:      /* ^T */
-                       ctrlt++;
-                       if(ctrlt > 2)
-                               ctrlt = 2;
-                       continue;
-               }
-
-               if(ctrlt != 2)
-                       continue;
-
-               /* ^T escapes */
-               ctrlt = 0;
-               switch(*p){
-               case 'S':
-                       x = splhi();
-                       dumpstack();
-                       procdump();
-                       splx(x);
-                       return;
-               case 's':
-                       dumpstack();
-                       return;
-               case 'x':
-                       xsummary();
-                       ixsummary();
-                       mallocsummary();
-               //      memorysummary();
-                       pagersummary();
-                       return;
-               case 'd':
-                       if(consdebug == nil)
-                               consdebug = rdb;
-                       else
-                               consdebug = nil;
-                       print("consdebug now %#p\n", consdebug);
-                       return;
-               case 'D':
-                       if(consdebug == nil)
-                               consdebug = rdb;
-                       consdebug();
-                       return;
-               case 'p':
-                       x = spllo();
-                       procdump();
-                       splx(x);
-                       return;
-               case 'q':
-                       scheddump();
-                       return;
-               case 'k':
-                       killbig("^t ^t k");
-                       return;
-               case 'r':
-                       exit(0);
-                       return;
-               }
-       }
-
-       qproduce(kbdq, buf, n);
-       if(kbd.raw)
-               return;
-       kmesgputs(buf, n);
-       if(screenputs != nil)
-               echoscreen(buf, n);
-       if(serialoq)
-               echoserialoq(buf, n);
-}
-
-/*
- *  Called by a uart interrupt for console input.
- *
- *  turn '\r' into '\n' before putting it into the queue.
- */
-int
-kbdcr2nl(Queue*, int ch)
-{
-       char *next;
-
-       ilock(&kbd.lockputc);           /* just a mutex */
-       if(ch == '\r' && !kbd.raw)
-               ch = '\n';
-       next = kbd.iw+1;
-       if(next >= kbd.ie)
-               next = kbd.istage;
-       if(next != kbd.ir){
-               *kbd.iw = ch;
-               kbd.iw = next;
-       }
-       iunlock(&kbd.lockputc);
-       return 0;
-}
-
-/*
- *  Put character, possibly a rune, into read queue at interrupt time.
- *  Called at interrupt time to process a character.
- */
-int
-kbdputc(Queue*, int ch)
-{
-       int i, n;
-       char buf[3];
-       Rune r;
-       char *next;
-
-       if(kbd.ir == nil)
-               return 0;               /* in case we're not inited yet */
-       
-       ilock(&kbd.lockputc);           /* just a mutex */
-       r = ch;
-       n = runetochar(buf, &r);
-       for(i = 0; i < n; i++){
-               next = kbd.iw+1;
-               if(next >= kbd.ie)
-                       next = kbd.istage;
-               if(next == kbd.ir)
-                       break;
-               *kbd.iw = buf[i];
-               kbd.iw = next;
-       }
-       iunlock(&kbd.lockputc);
-       return 0;
-}
-
-/*
- *  we save up input characters till clock time to reduce
- *  per character interrupt overhead.
- */
-static void
-kbdputcclock(void)
-{
-       char *iw;
-
-       /* this amortizes cost of qproduce */
-       if(kbd.iw != kbd.ir){
-               iw = kbd.iw;
-               if(iw < kbd.ir){
-                       echo(kbd.ir, kbd.ie-kbd.ir);
-                       kbd.ir = kbd.istage;
-               }
-               if(kbd.ir != iw){
-                       echo(kbd.ir, iw-kbd.ir);
-                       kbd.ir = iw;
-               }
-       }
-}
-
 enum{
        Qdir,
        Qbintime,
@@ -588,7 +313,6 @@ enum{
        Qppid,
        Qrandom,
        Qreboot,
-       Qswap,
        Qsysname,
        Qsysstat,
        Qtime,
@@ -621,7 +345,6 @@ static Dirtab consdir[]={
        "ppid",         {Qppid},        NUMSIZE,        0444,
        "random",       {Qrandom},      0,              0444,
        "reboot",       {Qreboot},      0,              0664,
-       "swap",         {Qswap},        0,              0664,
        "sysname",      {Qsysname},     0,              0664,
        "sysstat",      {Qsysstat},     0,              0666,
        "time",         {Qtime},        NUMSIZE+3*VLNUMSIZE,    0664,
@@ -665,11 +388,6 @@ consinit(void)
 {
        todinit();
        randominit();
-       /*
-        * at 115200 baud, the 1024 char buffer takes 56 ms to process,
-        * processing it every 22 ms should be fine
-        */
-       addclock0link(kbdputcclock, 22);
 }
 
 static Chan*
@@ -696,10 +414,6 @@ consopen(Chan *c, int omode)
        c->aux = nil;
        c = devopen(c, omode, consdir, nelem(consdir), devgen);
        switch((ulong)c->qid.path){
-       case Qconsctl:
-               incref(&kbd.ctl);
-               break;
-
        case Qkprint:
                if(tas(&kprintinuse) != 0){
                        c->flag &= ~COPEN;
@@ -724,14 +438,6 @@ static void
 consclose(Chan *c)
 {
        switch((ulong)c->qid.path){
-       /* last close of control file turns off raw */
-       case Qconsctl:
-               if(c->flag&COPEN){
-                       if(decref(&kbd.ctl) == 0)
-                               kbd.raw = 0;
-               }
-               break;
-
        /* close of kprint allows other opens */
        case Qkprint:
                if(c->flag & COPEN){
@@ -747,9 +453,9 @@ consread(Chan *c, void *buf, long n, vlong off)
 {
        ulong l;
        Mach *mp;
-       char *b, *bp, ch;
-       char tmp[256];          /* must be >= 18*NUMSIZE (Qswap) */
-       int i, k, id, send;
+       char *b, *bp;
+       char tmp[256];
+       int i, k, id;
        vlong offset = off;
        extern char configfile[];
 
@@ -761,49 +467,7 @@ consread(Chan *c, void *buf, long n, vlong off)
                return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
 
        case Qcons:
-               qlock(&kbd);
-               if(waserror()) {
-                       qunlock(&kbd);
-                       nexterror();
-               }
-               while(!qcanread(lineq)){
-                       if(qread(kbdq, &ch, 1) == 0)
-                               continue;
-                       send = 0;
-                       if(ch == 0){
-                               /* flush output on rawoff -> rawon */
-                               if(kbd.x > 0)
-                                       send = !qcanread(kbdq);
-                       }else if(kbd.raw){
-                               kbd.line[kbd.x++] = ch;
-                               send = !qcanread(kbdq);
-                       }else{
-                               switch(ch){
-                               case '\b':
-                                       if(kbd.x > 0)
-                                               kbd.x--;
-                                       break;
-                               case 0x15:      /* ^U */
-                                       kbd.x = 0;
-                                       break;
-                               case '\n':
-                               case 0x04:      /* ^D */
-                                       send = 1;
-                               default:
-                                       if(ch != 0x04)
-                                               kbd.line[kbd.x++] = ch;
-                                       break;
-                               }
-                       }
-                       if(send || kbd.x == sizeof kbd.line){
-                               qwrite(lineq, kbd.line, kbd.x);
-                               kbd.x = 0;
-                       }
-               }
-               n = qread(lineq, buf, n);
-               qunlock(&kbd);
-               poperror();
-               return n;
+               error(Egreg);
 
        case Qcputime:
                k = offset;
@@ -816,8 +480,7 @@ consread(Chan *c, void *buf, long n, vlong off)
                        l = up->time[i];
                        if(i == TReal)
                                l = MACHP(0)->ticks - l;
-                       l = TK2MS(l);
-                       readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
+                       readnum(0, tmp+NUMSIZE*i, NUMSIZE, tk2ms(l), NUMSIZE);
                }
                memmove(buf, tmp+k, n);
                return n;
@@ -874,8 +537,8 @@ consread(Chan *c, void *buf, long n, vlong off)
        case Qsysstat:
                b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1);     /* +1 for NUL */
                bp = b;
-               for(id = 0; id < 32; id++) {
-                       if(active.machs & (1<<id)) {
+               for(id = 0; id < MAXMACH; id++) {
+                       if(active.machs[id]) {
                                mp = MACHP(id);
                                readnum(0, bp, NUMSIZE, id, NUMSIZE);
                                bp += NUMSIZE;
@@ -893,13 +556,14 @@ consread(Chan *c, void *buf, long n, vlong off)
                                bp += NUMSIZE;
                                readnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
                                bp += NUMSIZE;
+                               l = mp->perf.period;
+                               if(l == 0)
+                                       l = 1;
                                readnum(0, bp, NUMSIZE,
-                                       (mp->perf.avg_inidle*100)/mp->perf.period,
-                                       NUMSIZE);
+                                       (mp->perf.avg_inidle*100)/l, NUMSIZE);
                                bp += NUMSIZE;
                                readnum(0, bp, NUMSIZE,
-                                       (mp->perf.avg_inintr*100)/mp->perf.period,
-                                       NUMSIZE);
+                                       (mp->perf.avg_inintr*100)/l, NUMSIZE);
                                bp += NUMSIZE;
                                *bp++ = '\n';
                        }
@@ -913,25 +577,6 @@ consread(Chan *c, void *buf, long n, vlong off)
                poperror();
                return n;
 
-       case Qswap:
-               snprint(tmp, sizeof tmp,
-                       "%lud memory\n"
-                       "%d pagesize\n"
-                       "%lud kernel\n"
-                       "%lud/%lud user\n"
-                       "%lud/%lud swap\n"
-                       "%lud/%lud kernel malloc\n"
-                       "%lud/%lud kernel draw\n",
-                       conf.npage*BY2PG,
-                       BY2PG,
-                       conf.npage-conf.upages,
-                       palloc.user-palloc.freecount, palloc.user,
-                       conf.nswap-swapalloc.free, conf.nswap,
-                       mainmem->cursize, mainmem->maxsize,
-                       imagmem->cursize, imagmem->maxsize);
-
-               return readstr((ulong)offset, buf, n, tmp);
-
        case Qsysname:
                if(sysname == nil)
                        return 0;
@@ -941,9 +586,7 @@ consread(Chan *c, void *buf, long n, vlong off)
                return randomread(buf, n);
 
        case Qdrivers:
-               b = malloc(READSTR);
-               if(b == nil)
-                       error(Enomem);
+               b = smalloc(READSTR);
                k = 0;
                for(i = 0; devtab[i] != nil; i++)
                        k += snprint(b+k, READSTR-k, "#%C %s\n",
@@ -953,8 +596,8 @@ consread(Chan *c, void *buf, long n, vlong off)
                        nexterror();
                }
                n = readstr((ulong)offset, buf, n, b);
-               free(b);
                poperror();
+               free(b);
                return n;
 
        case Qzero:
@@ -980,12 +623,11 @@ consread(Chan *c, void *buf, long n, vlong off)
 static long
 conswrite(Chan *c, void *va, long n, vlong off)
 {
-       char buf[256], ch;
+       char buf[256];
        long l, bp;
        char *a;
        Mach *mp;
-       int id, fd;
-       Chan *swc;
+       int id;
        ulong offset;
        Cmdbuf *cb;
        Cmdtab *ct;
@@ -1011,27 +653,7 @@ conswrite(Chan *c, void *va, long n, vlong off)
                break;
 
        case Qconsctl:
-               if(n >= sizeof(buf))
-                       n = sizeof(buf)-1;
-               strncpy(buf, a, n);
-               buf[n] = 0;
-               for(a = buf; a;){
-                       if(strncmp(a, "rawon", 5) == 0){
-                               kbd.raw = 1;
-                               /* clumsy hack - wake up reader */
-                               ch = 0;
-                               qwrite(kbdq, &ch, 1);                   
-                       } else if(strncmp(a, "rawoff", 6) == 0){
-                               kbd.raw = 0;
-                       } else if(strncmp(a, "ctlpon", 6) == 0){
-                               kbd.ctlpoff = 0;
-                       } else if(strncmp(a, "ctlpoff", 7) == 0){
-                               kbd.ctlpoff = 1;
-                       }
-                       if(a = strchr(a, ' '))
-                               a++;
-               }
-               break;
+               error(Egreg);
 
        case Qtime:
                if(!iseve())
@@ -1070,23 +692,25 @@ conswrite(Chan *c, void *va, long n, vlong off)
                }
                ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
                switch(ct->index) {
-               case CMhalt:
-                       reboot(nil, 0, 0);
-                       break;
                case CMreboot:
                        rebootcmd(cb->nf-1, cb->f+1);
                        break;
                case CMpanic:
                        *(ulong*)0=0;
                        panic("/dev/reboot");
+               case CMrdb:
+                       if(consdebug == nil)
+                               consdebug = rdb;
+                       consdebug();
+                       break;
                }
                poperror();
                free(cb);
                break;
 
        case Qsysstat:
-               for(id = 0; id < 32; id++) {
-                       if(active.machs & (1<<id)) {
+               for(id = 0; id < MAXMACH; id++) {
+                       if(active.machs[id]) {
                                mp = MACHP(id);
                                mp->cs = 0;
                                mp->intr = 0;
@@ -1098,25 +722,6 @@ conswrite(Chan *c, void *va, long n, vlong off)
                }
                break;
 
-       case Qswap:
-               if(n >= sizeof buf)
-                       error(Egreg);
-               memmove(buf, va, n);    /* so we can NUL-terminate */
-               buf[n] = 0;
-               /* start a pager if not already started */
-               if(strncmp(buf, "start", 5) == 0){
-                       kickpager();
-                       break;
-               }
-               if(!iseve())
-                       error(Eperm);
-               if(buf[0]<'0' || '9'<buf[0])
-                       error(Ebadarg);
-               fd = strtoul(buf, 0, 0);
-               swc = fdtochan(fd, -1, 1, 1);
-               setswapchan(swc);
-               break;
-
        case Qsysname:
                if(offset != 0)
                        error(Ebadarg);
@@ -1161,33 +766,6 @@ Dev consdevtab = {
        devwstat,
 };
 
-static ulong   randn;
-
-static void
-seedrand(void)
-{
-       if(!waserror()){
-               randomread((void*)&randn, sizeof(randn));
-               poperror();
-       }
-}
-
-int
-nrand(int n)
-{
-       if(randn == 0)
-               seedrand();
-       randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
-       return (randn>>16) % n;
-}
-
-int
-rand(void)
-{
-       nrand(1);
-       return randn;
-}
-
 static uvlong uvorder = 0x0001020304050607ULL;
 
 static uchar*
@@ -1335,7 +913,8 @@ writebintime(char *buf, int n)
        vlong delta;
        long period;
 
-       n--;
+       if(--n <= 0)
+               error(Ebadtimectl);
        p = (uchar*)buf + 1;
        switch(*buf){
        case 'n':
@@ -1360,5 +939,26 @@ writebintime(char *buf, int n)
                todsetfreq(fasthz);
                break;
        }
-       return n;
+       return n+1;
+}
+
+void
+cpushutdown(void)
+{
+       int ms, once;
+
+       once = active.machs[m->machno];
+       active.machs[m->machno] = 0;
+       active.exiting = 1;
+
+       if(once)
+               iprint("cpu%d: exiting\n", m->machno);
+
+       /* wait for any other processors to shutdown */
+       spllo();
+       for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
+               delay(TK2MS(2));
+               if(memchr(active.machs, 1, MAXMACH) == nil && consactive() == 0)
+                       break;
+       }
 }