perf: Remove the kprof.pdata staging ground
[akaros.git] / kern / drivers / dev / cons.c
1 /*
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9
10 #include <arch/arch.h>
11 #include <ros/fs.h>
12 #include <ns.h>
13 #include <kmalloc.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <time.h>
17 #include <atomic.h>
18 #include <smp.h>
19 #include <error.h>
20 #include <sys/queue.h>
21 #include <event.h>
22 #include <ros/procinfo.h>
23
24 #if 0
25 void (*consdebug) (void) = NULL;
26 #endif
27 void (*screenputs) (const char *, int) = cputbuf;
28
29 struct queue *kbdq;                             /* unprocessed console input */
30 struct queue *lineq;                    /* processed console input */
31 struct queue *serialoq;                 /* serial console output */
32 struct queue *kprintoq;                 /* console output, for /dev/kprint */
33 atomic_t kprintinuse = 0;               /* test and set whether /dev/kprint is open */
34 int iprintscreenputs = 1;
35 int keepbroken = 1;
36
37 static uint8_t logbuffer[1 << 20];
38 static int index = 0;
39 static struct queue *logqueue = NULL;
40 static int reading_kmesg = 0;
41
42 typedef unsigned char uint8_t;
43
44 void logbuf(int c)
45 {
46         if (reading_kmesg)
47                 return;
48         if (index > 1 << 20)
49                 return;
50         logbuffer[index++] = c;
51 }
52
53 /*
54  *  return true if current user is eve
55  */
56 int iseve(void)
57 {
58 #if 0
59         return strcmp(eve, o->user) == 0;
60 #endif
61         return 1;
62 }
63
64 char *eve = "eve";
65 char hostdomain[256] = "akaros.org";
66
67 static struct {
68         qlock_t qlock;
69
70         int raw;                                        /* true if we shouldn't process input */
71         struct kref ctl;                        /* number of opens to the control file */
72         int x;                                          /* index into line */
73         char line[1024];                        /* current input line */
74
75         int count;
76         int ctlpoff;
77
78         /* a place to save up characters at interrupt time before dumping them in the queue */
79         spinlock_t lockputc;
80         char istage[1024];
81         char *iw;
82         char *ir;
83         char *ie;
84 } kbd = {
85 .iw = kbd.istage,.ir = kbd.istage,.ie = kbd.istage + sizeof(kbd.istage),};
86
87 char *sysname;
88 int64_t fasthz;
89
90 static int readtime(uint32_t, char *, int);
91 static int readbintime(char *, int);
92 static int writetime(char *, int);
93 static int writebintime(char *, int);
94 static void killkid(void);
95
96 enum {
97         CMbroken,
98         CMconsole,
99         CMhalt,
100         CMnobroken,
101         CMpanic,
102         CMreboot,
103 };
104
105
106 struct cmdtab rebootmsg[] = {
107         {CMbroken, "broken", 0},
108         {CMconsole, "console", 1},
109         {CMhalt, "halt", 1},
110         {CMnobroken, "nobroken", 0},
111         {CMpanic, "panic", 0},
112         {CMreboot, "reboot", 0},
113 };
114
115 void printinit(void)
116 {
117         lineq = qopen(2 * 1024, 0, NULL, NULL);
118         if (lineq == NULL)
119                 panic("printinit");
120         qdropoverflow(lineq, 1);
121 }
122
123 int consactive(void)
124 {
125         if (serialoq)
126                 return qlen(serialoq) > 0;
127         return 0;
128 }
129
130 void prflush(void)
131 {
132         long times = 0;
133
134         while (consactive())
135                 if (times++ > 1000)
136                         break;
137 }
138
139 /*
140  * Log console output so it can be retrieved via /dev/kmesg.
141  * This is good for catching boot-time messages after the fact.
142  */
143 struct {
144         spinlock_t lk;
145         char buf[1 << 20];
146         unsigned int n;
147 } kmesg;
148
149 static void kmesgputs(char *str, int n)
150 {
151         unsigned int nn, d;
152
153         spin_lock_irqsave(&kmesg.lk);
154         /* take the tail of huge writes */
155         if (n > sizeof kmesg.buf) {
156                 d = n - sizeof kmesg.buf;
157                 str += d;
158                 n -= d;
159         }
160
161         /* slide the buffer down to make room */
162         nn = kmesg.n;
163         if (nn + n >= sizeof kmesg.buf) {
164                 d = nn + n - sizeof kmesg.buf;
165                 if (d)
166                         memmove(kmesg.buf, kmesg.buf + d, sizeof kmesg.buf - d);
167                 nn -= d;
168         }
169
170         /* copy the data in */
171         memmove(kmesg.buf + nn, str, n);
172         nn += n;
173         kmesg.n = nn;
174         spin_unlock_irqsave(&kmesg.lk);
175 }
176
177 /*
178  *   Print a string on the console.  Convert \n to \r\n for serial
179  *   line consoles.  Locking of the queues is left up to the screen
180  *   or uart code.  Multi-line messages to serial consoles may get
181  *   interspersed with other messages.
182  */
183 static void putstrn0(char *str, int n, int usewrite)
184 {
185         int m;
186         char *t;
187
188 #if 0
189         if (!islo())
190                 usewrite = 0;
191 #endif
192
193         /*
194          *  how many different output devices do we need?
195          */
196         kmesgputs(str, n);
197
198         /*
199          *  if someone is reading /dev/kprint
200          *  put the message there.
201          *  if not and there's an attached bit mapped display,
202          *  put the message there.
203          *
204          *  if there's a serial line being used as a console,
205          *  put the message there.
206          */
207         if (kprintoq != NULL && !qisclosed(kprintoq)) {
208                 if (usewrite)
209                         qwrite(kprintoq, str, n);
210                 else
211                         qiwrite(kprintoq, str, n);
212         } else if (screenputs != NULL)
213                 screenputs(str, n);
214
215         if (serialoq == NULL) {
216 #if 0
217                 uartputs(str, n);
218 #endif
219                 return;
220         }
221
222         while (n > 0) {
223                 t = memchr(str, '\n', n);
224                 if (t && !kbd.raw) {
225                         m = t - str;
226                         if (usewrite) {
227                                 qwrite(serialoq, str, m);
228                                 qwrite(serialoq, "\r\n", 2);
229                         } else {
230                                 qiwrite(serialoq, str, m);
231                                 qiwrite(serialoq, "\r\n", 2);
232                         }
233                         n -= m + 1;
234                         str = t + 1;
235                 } else {
236                         if (usewrite)
237                                 qwrite(serialoq, str, n);
238                         else
239                                 qiwrite(serialoq, str, n);
240                         break;
241                 }
242         }
243 }
244
245 void putstrn(char *str, int n)
246 {
247         putstrn0(str, n, 0);
248 }
249
250 int noprint;
251
252 int print(char *fmt, ...)
253 {
254         int n;
255         va_list arg;
256         char buf[PRINTSIZE];
257
258         if (noprint)
259                 return -1;
260
261         va_start(arg, fmt);
262         n = vsnprintf(buf, sizeof(buf), fmt, arg);
263         va_end(arg);
264         putstrn(buf, n);
265
266         return n;
267 }
268
269 /*
270  * Want to interlock iprints to avoid interlaced output on
271  * multiprocessor, but don't want to deadlock if one processor
272  * dies during print and another has something important to say.
273  * Make a good faith effort.
274  */
275 static spinlock_t iprintlock;
276 static int iprintcanlock(spinlock_t * l)
277 {
278         int i;
279
280         for (i = 0; i < 1000; i++) {
281                 if (spin_trylock(l))
282                         return 1;
283         }
284         return 0;
285 }
286
287 int iprint(char *fmt, ...)
288 {
289         int8_t s = 0;
290         int n, locked;
291         va_list arg;
292         char buf[PRINTSIZE];
293
294         disable_irqsave(&s);
295         va_start(arg, fmt);
296         n = vsnprintf(buf, sizeof(buf), fmt, arg);
297         va_end(arg);
298         locked = iprintcanlock(&iprintlock);
299         if (screenputs != NULL && iprintscreenputs)
300                 screenputs(buf, n);
301 #if 0
302         uartputs(buf, n);
303 #endif
304         if (locked)
305                 spin_unlock(&iprintlock);
306         enable_irqsave(&s);
307
308         return n;
309 }
310
311 /* libmp at least contains a few calls to sysfatal; simulate with panic */
312 void sysfatal(char *fmt, ...)
313 {
314         char err[256];
315         va_list arg;
316
317         va_start(arg, fmt);
318         vsnprintf(err, sizeof err, fmt, arg);
319         va_end(arg);
320         panic("sysfatal: %s", err);
321 }
322
323 void _assert(char *fmt)
324 {
325         panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
326 }
327
328 #if 0
329 int pprint(char *fmt, ...)
330 {
331         ERRSTACK(2);
332         int n;
333         struct chan *c;
334         va_list arg;
335         char buf[2 * PRINTSIZE];
336
337         if (up == NULL || current->fgrp == NULL)
338                 return 0;
339
340         c = current->fgrp->fd[2];
341         if (c == 0 || (c->mode != O_WRITE && c->mode != O_RDWR))
342                 return 0;
343         n = snprintf(buf, sizeof buf, "%s %lud: ", current->text, current->pid);
344         va_start(arg, fmt);
345         n = vsnprintf(buf + n, sizeof(buf), fmt, arg);
346         va_end(arg);
347
348         if (waserror())
349                 return 0;
350         devtab[c->type]->write(c, buf, n, c->offset);
351         poperror();
352
353         spin_lock(&c->lock);
354         c->offset += n;
355         spin_unlock(&c->lock);
356
357         return n;
358 }
359 #endif
360
361 static void echoscreen(char *buf, int n)
362 {
363         char *e, *p;
364         char ebuf[128];
365         int x;
366
367         p = ebuf;
368         e = ebuf + sizeof(ebuf) - 4;
369         while (n-- > 0) {
370                 if (p >= e) {
371                         screenputs(ebuf, p - ebuf);
372                         p = ebuf;
373                 }
374                 x = *buf++;
375                 if (x == 0x15) {
376                         *p++ = '^';
377                         *p++ = 'U';
378                         *p++ = '\n';
379                 } else
380                         *p++ = x;
381         }
382         if (p != ebuf)
383                 screenputs(ebuf, p - ebuf);
384 }
385
386 static void echoserialoq(char *buf, int n)
387 {
388         char *e, *p;
389         char ebuf[128];
390         int x;
391
392         p = ebuf;
393         e = ebuf + sizeof(ebuf) - 4;
394         while (n-- > 0) {
395                 if (p >= e) {
396                         qiwrite(serialoq, ebuf, p - ebuf);
397                         p = ebuf;
398                 }
399                 x = *buf++;
400                 if (x == '\n') {
401                         *p++ = '\r';
402                         *p++ = '\n';
403                 } else if (x == 0x15) {
404                         *p++ = '^';
405                         *p++ = 'U';
406                         *p++ = '\n';
407                 } else
408                         *p++ = x;
409         }
410         if (p != ebuf)
411                 qiwrite(serialoq, ebuf, p - ebuf);
412 }
413
414 static void echo(char *buf, int n)
415 {
416         static int ctrlt, pid;
417         char *e, *p;
418
419         if (n == 0)
420                 return;
421
422         e = buf + n;
423         for (p = buf; p < e; p++) {
424                 switch (*p) {
425 #if 0
426                         case 0x10:      /* ^P */
427                                 if (cpuserver && !kbd.ctlpoff) {
428                                         active.exiting = 1;
429                                         return;
430                                 }
431                                 break;
432 #endif
433                         case 0x14:      /* ^T */
434                                 ctrlt++;
435                                 if (ctrlt > 2)
436                                         ctrlt = 2;
437                                 continue;
438                 }
439
440                 if (ctrlt != 2)
441                         continue;
442
443                 /* ^T escapes */
444                 ctrlt = 0;
445                 switch (*p) {
446 #if 0
447                         case 'S':{
448                                         int8_t x = 0;
449                                         disable_irqsave(&x);
450                                         dumpstack();
451                                         procdump();
452                                         enable_irqsave(&x);
453                                         return;
454                                 }
455 #endif
456                         case 's':
457                                 dumpstack();
458                                 return;
459 #if 0
460                         case 'x':
461                                 xsummary();
462                                 ixsummary();
463                                 mallocsummary();
464                                 memorysummary();
465                                 pagersummary();
466                                 return;
467                         case 'd':
468                                 if (consdebug == NULL)
469                                         consdebug = rdb;
470                                 else
471                                         consdebug = NULL;
472                                 printd("consdebug now %#p\n", consdebug);
473                                 return;
474                         case 'D':
475                                 if (consdebug == NULL)
476                                         consdebug = rdb;
477                                 consdebug();
478                                 return;
479                         case 'p':
480                                 x = spllo();
481                                 procdump();
482                                 splx(x);
483                                 return;
484                         case 'q':
485                                 scheddump();
486                                 return;
487                         case 'k':
488                                 killbig("^t ^t k");
489                                 return;
490 #endif
491                         case 'r':
492                                 exit(0);
493                                 return;
494                 }
495         }
496
497         qwrite(kbdq, buf, n);   /* was once qproduce, YMMV */
498         if (kbd.raw)
499                 return;
500         kmesgputs(buf, n);
501         if (screenputs != NULL)
502                 echoscreen(buf, n);
503         if (serialoq)
504                 echoserialoq(buf, n);
505 }
506
507 /*
508  *  Called by a uart interrupt for console input.
509  *
510  *  turn '\r' into '\n' before putting it into the queue.
511  */
512 int kbdcr2nl(struct queue *ignored_queue, int ch)
513 {
514         char *next;
515
516         spin_lock_irqsave(&kbd.lockputc);       /* just a mutex */
517         if (ch == '\r' && !kbd.raw)
518                 ch = '\n';
519         next = kbd.iw + 1;
520         if (next >= kbd.ie)
521                 next = kbd.istage;
522         if (next != kbd.ir) {
523                 *kbd.iw = ch;
524                 kbd.iw = next;
525         }
526         spin_unlock_irqsave(&kbd.lockputc);
527         return 0;
528 }
529
530 /*
531  *  Put character, possibly a rune, into read queue at interrupt time.
532  *  Called at interrupt time to process a character.
533  */
534 int kbdputc(struct queue *unused_queue, int ch)
535 {
536         int i, n;
537         char buf[3];
538         // Akaros does not use Rune et al.
539         //Rune r;
540         int r;
541         char *next;
542
543         if (kbd.ir == NULL)
544                 return 0;       /* in case we're not inited yet */
545
546         spin_lock_irqsave(&kbd.lockputc);       /* just a mutex */
547         r = ch;
548         //n = runetochar(buf, &r);
549         // Fake Rune support.
550         n = 1;
551         buf[0] = r;
552         for (i = 0; i < n; i++) {
553                 next = kbd.iw + 1;
554                 if (next >= kbd.ie)
555                         next = kbd.istage;
556                 if (next == kbd.ir)
557                         break;
558                 *kbd.iw = buf[i];
559                 kbd.iw = next;
560         }
561         spin_unlock_irqsave(&kbd.lockputc);
562         return 0;
563 }
564
565 /*
566  *  we save up input characters till clock time to reduce
567  *  per character interrupt overhead.
568  */
569 static void kbdputcclock(void)
570 {
571         char *iw;
572
573         /* this amortizes cost of qproduce */
574         if (kbd.iw != kbd.ir) {
575                 iw = kbd.iw;
576                 if (iw < kbd.ir) {
577                         echo(kbd.ir, kbd.ie - kbd.ir);
578                         kbd.ir = kbd.istage;
579                 }
580                 if (kbd.ir != iw) {
581                         echo(kbd.ir, iw - kbd.ir);
582                         kbd.ir = iw;
583                 }
584         }
585 }
586
587 enum {
588         Qdir,
589         Qbintime,
590         Qconfig,
591         Qcons,
592         Qconsctl,
593         Qcputime,
594         Qdrivers,
595         Qhostdomain,
596         Qhostowner,
597         Qklog,
598         Qkmesg,
599         Qkprint,
600         Qnull,
601         Qosversion,
602         Qpgrpid,
603         Qpid,
604         Qppid,
605         Qreboot,
606         Qswap,
607         Qsysctl,
608         Qsysname,
609         Qsysstat,
610         Qtime,
611         Quser,
612         Qzero,
613         Qkillkid,
614 };
615
616 enum {
617         VLNUMSIZE = 22,
618         DOMLEN = 256,
619 };
620
621 static struct dirtab consdir[] = {
622         {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0555},
623         {"bintime", {Qbintime}, 24, 0664},
624         {"config", {Qconfig}, 0, 0444},
625         {"cons", {Qcons}, 0, 0660},
626         {"consctl", {Qconsctl}, 0, 0220},
627         // FIXME -- we don't have real permissions yet so we set it to 222, not 220
628         {"killkid", {Qkillkid}, 0, 0220 | /* BOGUS */ 2},
629         {"cputime", {Qcputime}, 6 * NUMSIZE, 0444},
630         {"drivers", {Qdrivers}, 0, 0444},
631         {"hostdomain", {Qhostdomain}, DOMLEN, 0664},
632         {"hostowner", {Qhostowner}, 0, 0664},
633         {"klog", {Qklog}, 0, 0440},
634         {"kmesg", {Qkmesg}, 0, 0440},
635         {"kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL | 0440},
636         {"null", {Qnull}, 0, 0666},
637         {"osversion", {Qosversion}, 0, 0444},
638         {"pgrpid", {Qpgrpid}, NUMSIZE, 0444},
639         {"pid", {Qpid}, NUMSIZE, 0444},
640         {"ppid", {Qppid}, NUMSIZE, 0444},
641         {"reboot", {Qreboot}, 0, 0660},
642         {"swap", {Qswap}, 0, 0664},
643         {"sysctl", {Qsysctl}, 0, 0666},
644         {"sysname", {Qsysname}, 0, 0664},
645         {"sysstat", {Qsysstat}, 0, 0666},
646         {"time", {Qtime}, NUMSIZE + 3 * VLNUMSIZE, 0664},
647         {"user", {Quser}, 0, 0666},
648         {"zero", {Qzero}, 0, 0444},
649 };
650
651 int consreadnum(uint32_t off, char *buf, uint32_t n, uint32_t val, int size)
652 {
653         char tmp[64];
654
655         snprintf(tmp, sizeof(tmp), "%*lud", size - 1, val);
656         tmp[size - 1] = ' ';
657         if (off >= size)
658                 return 0;
659         if (off + n > size)
660                 n = size - off;
661         memmove(buf, tmp + off, n);
662         return n;
663 }
664
665 int consreadstr(uint32_t off, char *buf, uint32_t n, char *str)
666 {
667         int size;
668
669         size = strlen(str);
670         if (off >= size)
671                 return 0;
672         if (off + n > size)
673                 n = size - off;
674         memmove(buf, str + off, n);
675         return n;
676 }
677
678 static void consinit(void)
679 {
680 #if 0
681         todinit();
682 #endif
683         /*
684          * at 115200 baud, the 1024 char buffer takes 56 ms to process,
685          * processing it every 22 ms should be fine
686          */
687 #if 0
688         addclock0link(kbdputcclock, 22);
689 #endif
690 }
691
692 static char *devname(void);
693
694 static struct chan *consattach(char *spec)
695 {
696         return devattach(devname(), spec);
697 }
698
699 static struct walkqid *conswalk(struct chan *c, struct chan *nc, char **name,
700                                                                 int nname)
701 {
702         return devwalk(c, nc, name, nname, consdir, ARRAY_SIZE(consdir), devgen);
703 }
704
705 static int consstat(struct chan *c, uint8_t * dp, int n)
706 {
707         return devstat(c, dp, n, consdir, ARRAY_SIZE(consdir), devgen);
708 }
709
710 static struct chan *consopen(struct chan *c, int omode)
711 {
712         c->aux = NULL;
713         c = devopen(c, omode, consdir, ARRAY_SIZE(consdir), devgen);
714         switch ((uint32_t) c->qid.path) {
715                 case Qconsctl:
716                         kref_get(&kbd.ctl, 1);
717                         break;
718
719                 case Qkprint:
720                         if (atomic_swap(&kprintinuse, 1) != 0) {
721                                 c->flag &= ~COPEN;
722                                 error(EADDRINUSE, "kprintinuse lock failed");
723                         }
724                         if (kprintoq == NULL) {
725                                 kprintoq = qopen(8 * 1024, Qcoalesce, 0, 0);
726                                 if (kprintoq == NULL) {
727                                         c->flag &= ~COPEN;
728                                         error(ENOMEM, "Can't allocate kprintoq");
729                                 }
730                                 qdropoverflow(kprintoq, 1);
731                         } else
732                                 qreopen(kprintoq);
733                         c->iounit = qiomaxatomic;
734                         break;
735         }
736         return c;
737 }
738
739 static void consclose(struct chan *c)
740 {
741         switch ((uint32_t) c->qid.path) {
742                         /* last close of control file turns off raw */
743                 case Qconsctl:
744                         if (c->flag & COPEN) {
745                                 if (kref_put(&kbd.ctl) == 0)
746                                         kbd.raw = 0;
747                         }
748                         break;
749
750                         /* close of kprint allows other opens */
751                 case Qkprint:
752                         if (c->flag & COPEN) {
753                                 kprintinuse = 0;
754                                 qhangup(kprintoq, NULL);
755                         }
756                         break;
757         }
758 }
759
760 static long consread(struct chan *c, void *buf, long n, int64_t off)
761 {
762         ERRSTACK(1);
763         uint32_t l;
764 #if 0
765         Mach *mp;
766 #endif
767         char *b, *bp, ch;
768         char tmp[256];                          /* must be >= 18*NUMSIZE (Qswap) */
769         int i, k, id, send;
770         int64_t offset = off;
771 #if 0
772         extern char configfile[];
773 #endif
774
775         if (n <= 0)
776                 return n;
777
778         switch ((uint32_t) c->qid.path) {
779                 case Qdir:
780                         return devdirread(c, buf, n, consdir, ARRAY_SIZE(consdir), devgen);
781
782                 case Qcons:
783                         qlock(&(&kbd)->qlock);
784                         if (waserror()) {
785                                 qunlock(&(&kbd)->qlock);
786                                 nexterror();
787                         }
788                         while (!qcanread(lineq)) {
789                                 if (qread(kbdq, &ch, 1) == 0)
790                                         continue;
791                                 send = 0;
792                                 if (ch == 0) {
793                                         /* flush output on rawoff -> rawon */
794                                         if (kbd.x > 0)
795                                                 send = !qcanread(kbdq);
796                                 } else if (kbd.raw) {
797                                         kbd.line[kbd.x++] = ch;
798                                         send = !qcanread(kbdq);
799                                 } else {
800                                         switch (ch) {
801                                                 case '\b':
802                                                         if (kbd.x > 0)
803                                                                 kbd.x--;
804                                                         break;
805                                                 case 0x15:      /* ^U */
806                                                         kbd.x = 0;
807                                                         break;
808                                                 case '\n':
809                                                 case 0x04:      /* ^D */
810                                                         send = 1;
811                                                 default:
812                                                         if (ch != 0x04)
813                                                                 kbd.line[kbd.x++] = ch;
814                                                         break;
815                                         }
816                                 }
817                                 if (send || kbd.x == sizeof kbd.line) {
818                                         qwrite(lineq, kbd.line, kbd.x);
819                                         kbd.x = 0;
820                                 }
821                         }
822                         n = qread(lineq, buf, n);
823                         qunlock(&(&kbd)->qlock);
824                         poperror();
825                         return n;
826
827 #if 0
828                 case Qcputime:
829                         k = offset;
830                         if (k >= 6 * NUMSIZE)
831                                 return 0;
832                         if (k + n > 6 * NUMSIZE)
833                                 n = 6 * NUMSIZE - k;
834                         /* easiest to format in a separate buffer and copy out */
835                         for (i = 0; i < 6 && NUMSIZE * i < k + n; i++) {
836                                 l = current->time[i];
837                                 if (i == TReal)
838                                         l = MACHP(0)->ticks - l;
839                                 l = TK2MS(l);
840                                 consreadnum(0, tmp + NUMSIZE * i, NUMSIZE, l, NUMSIZE);
841                         }
842                         memmove(buf, tmp + k, n);
843                         return n;
844 #endif
845
846                 case Qkmesg:
847                         /*
848                          * This is unlocked to avoid tying up a process
849                          * that's writing to the buffer.  kmesg.n never
850                          * gets smaller, so worst case the reader will
851                          * see a slurred buffer.
852                          */
853                         if (off >= kmesg.n)
854                                 n = 0;
855                         else {
856                                 if (off + n > kmesg.n)
857                                         n = kmesg.n - off;
858                                 memmove(buf, kmesg.buf + off, n);
859                         }
860                         return n;
861
862                 case Qkprint:
863                         return qread(kprintoq, buf, n);
864
865                 case Qpgrpid:
866                         return consreadnum((uint32_t) offset, buf, n, current->pgrp->pgrpid,
867                                                            NUMSIZE);
868
869                 case Qpid:
870                         return consreadnum((uint32_t) offset, buf, n, current->pid,
871                                                            NUMSIZE);
872
873                 case Qppid:
874                         return consreadnum((uint32_t) offset, buf, n, current->ppid,
875                                                            NUMSIZE);
876
877                 case Qtime:
878                         return readtime((uint32_t) offset, buf, n);
879
880                 case Qbintime:
881                         return readbintime(buf, n);
882
883                 case Qhostowner:
884                         return consreadstr((uint32_t) offset, buf, n, eve);
885
886                 case Qhostdomain:
887                         return consreadstr((uint32_t) offset, buf, n, hostdomain);
888
889                 case Quser:
890                         return consreadstr((uint32_t) offset, buf, n, current->user);
891
892                 case Qnull:
893                         return 0;
894
895 #if 0
896                 case Qconfig:
897                         return consreadstr((uint32_t) offset, buf, n, configfile);
898
899                 case Qsysstat:
900                         b = kzmalloc(conf.nmach * (NUMSIZE * 11 + 1) + 1, 0);   /* +1 for NUL */
901                         bp = b;
902                         for (id = 0; id < 32; id++) {
903                                 if (active.machs & (1 << id)) {
904                                         mp = MACHP(id);
905                                         consreadnum(0, bp, NUMSIZE, id, NUMSIZE);
906                                         bp += NUMSIZE;
907                                         consreadnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
908                                         bp += NUMSIZE;
909                                         consreadnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
910                                         bp += NUMSIZE;
911                                         consreadnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
912                                         bp += NUMSIZE;
913                                         consreadnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
914                                         bp += NUMSIZE;
915                                         consreadnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
916                                         bp += NUMSIZE;
917                                         consreadnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
918                                         bp += NUMSIZE;
919                                         consreadnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
920                                         bp += NUMSIZE;
921                                         consreadnum(0, bp, NUMSIZE,
922                                                                 (mp->perf.avg_inidle * 100) / mp->perf.period,
923                                                                 NUMSIZE);
924                                         bp += NUMSIZE;
925                                         consreadnum(0, bp, NUMSIZE,
926                                                                 (mp->perf.avg_inintr * 100) / mp->perf.period,
927                                                                 NUMSIZE);
928                                         bp += NUMSIZE;
929                                         *bp++ = '\n';
930                                 }
931                         }
932                         if (waserror()) {
933                                 kfree(b);
934                                 nexterror();
935                         }
936                         n = consreadstr((uint32_t) offset, buf, n, b);
937                         kfree(b);
938                         poperror();
939                         return n;
940
941                 case Qswap:
942                         snprintf(tmp, sizeof tmp,
943                                          "%lud memory\n"
944                                          "%d pagesize\n"
945                                          "%lud kernel\n"
946                                          "%lud/%lud user\n"
947                                          "%lud/%lud swap\n"
948                                          "%lud/%lud kernel malloc\n"
949                                          "%lud/%lud kernel draw\n",
950                                          conf.npage * BY2PG,
951                                          BY2PG,
952                                          conf.npage - conf.upages,
953                                          palloc.user - palloc.freecount, palloc.user,
954                                          conf.nswap - swapalloc.free, conf.nswap,
955                                          mainmem->cursize, mainmem->maxsize,
956                                          imagmem->cursize, imagmem->maxsize);
957
958                         return consreadstr((uint32_t) offset, buf, n, tmp);
959 #endif
960
961                 case Qsysname:
962                         if (sysname == NULL)
963                                 return 0;
964                         return consreadstr((uint32_t) offset, buf, n, sysname);
965
966                 case Qdrivers:
967                         b = kzmalloc(READSTR, 0);
968                         if (b == NULL)
969                                 error(ENOMEM, "allocation for /dev/drivers read failed");
970                         k = 0;
971                         for (int i = 0; &devtab[i] < __devtabend; i++)
972                                 k += snprintf(b + k, READSTR - k, "#%s\n", devtab[i].name);
973                         if (waserror()) {
974                                 kfree(b);
975                                 nexterror();
976                         }
977                         n = consreadstr((uint32_t) offset, buf, n, b);
978                         kfree(b);
979                         poperror();
980                         return n;
981
982                 case Qklog:
983                         //return qread(klogq, buf, n);
984                         /* the queue gives us some elasticity for log reading. */
985                         if (!logqueue)
986                                 logqueue = qopen(1 << 20, 0, 0, 0);
987                         if (logqueue) {
988                                 int ret;
989                                 /* atomic sets/gets are not that important in this case. */
990                                 reading_kmesg = 1;
991                                 qwrite(logqueue, logbuffer, index);
992                                 index = 0;
993                                 ret = qread(logqueue, buf, n);
994                                 reading_kmesg = 0;
995                                 return ret;
996                         }
997                         break;
998
999                 case Qzero:
1000                         memset(buf, 0, n);
1001                         return n;
1002
1003                 case Qosversion:
1004                         snprintf(tmp, sizeof tmp, "2000");
1005                         n = consreadstr((uint32_t) offset, buf, n, tmp);
1006                         return n;
1007
1008                 default:
1009                         printd("consread %#llux\n", c->qid.path);
1010                         error(EINVAL, "bad QID in consread");
1011         }
1012         return -1;      /* never reached */
1013 }
1014
1015 static long conswrite(struct chan *c, void *va, long n, int64_t off)
1016 {
1017         ERRSTACK(1);
1018         char buf[256], ch;
1019         long l, bp;
1020         char *a;
1021         //Mach *mp;
1022         int id, fd;
1023         struct chan *swc;
1024         uint32_t offset;
1025         struct cmdbuf *cb;
1026         struct cmdtab *ct;
1027         int x;
1028         uint64_t rip, rsp, cr3, flags, vcpu;
1029         int ret;
1030
1031         a = va;
1032         offset = off;
1033
1034         switch ((uint32_t) c->qid.path) {
1035                 case Qcons:
1036                         /*
1037                          * Can't page fault in putstrn, so copy the data locally.
1038                          */
1039                         l = n;
1040                         while (l > 0) {
1041                                 bp = l;
1042                                 if (bp > sizeof buf)
1043                                         bp = sizeof buf;
1044                                 memmove(buf, a, bp);
1045                                 putstrn0(buf, bp, 1);
1046                                 a += bp;
1047                                 l -= bp;
1048                         }
1049                         break;
1050
1051                 /* TODO: have it take a command about just *how* to kill the kid? */
1052                 case Qkillkid:
1053                         killkid();
1054                         break;
1055
1056                 case Qconsctl:
1057                         if (n >= sizeof(buf))
1058                                 n = sizeof(buf) - 1;
1059                         strncpy(buf, a, n);
1060                         buf[n] = 0;
1061                         for (a = buf; a;) {
1062                                 if (strncmp(a, "rawon", 5) == 0) {
1063                                         kbd.raw = 1;
1064                                         /* clumsy hack - wake up reader */
1065                                         ch = 0;
1066                                         qwrite(kbdq, &ch, 1);
1067                                 } else if (strncmp(a, "rawoff", 6) == 0) {
1068                                         kbd.raw = 0;
1069                                 } else if (strncmp(a, "ctlpon", 6) == 0) {
1070                                         kbd.ctlpoff = 0;
1071                                 } else if (strncmp(a, "ctlpoff", 7) == 0) {
1072                                         kbd.ctlpoff = 1;
1073                                 }
1074                                 if ((a = strchr(a, ' ')) != NULL)
1075                                         a++;
1076                         }
1077                         break;
1078
1079                 case Qtime:
1080                         if (!iseve())
1081                                 error(EPERM, "Hodie Natus Est Radici Frater");
1082                         return writetime(a, n);
1083
1084                 case Qbintime:
1085                         if (!iseve())
1086                                 error(EPERM, ERROR_FIXME);
1087                         return writebintime(a, n);
1088
1089 #if 0
1090                 case Qhostowner:
1091                         return hostownerwrite(a, n);
1092
1093                 case Qhostdomain:
1094                         return hostdomainwrite(a, n);
1095
1096                 case Quser:
1097                         return userwrite(a, n);
1098 #endif
1099
1100                 case Qnull:
1101                         break;
1102
1103                 case Qconfig:
1104                         error(EPERM, "Cannot write to config QID");
1105                         break;
1106
1107                 case Qsysctl:
1108                         //if (!iseve()) error(EPERM, ERROR_FIXME);
1109                         cb = parsecmd(a, n);
1110                         if (cb->nf > 1)
1111                         printd("cons sysctl cmd %s\n", cb->f[0]);
1112
1113                 case Qreboot:
1114                         if (!iseve())
1115                                 error(EPERM, ERROR_FIXME);
1116                         cb = parsecmd(a, n);
1117
1118                         if (waserror()) {
1119                                 kfree(cb);
1120                                 nexterror();
1121                         }
1122                         ct = lookupcmd(cb, rebootmsg, ARRAY_SIZE(rebootmsg));
1123                         switch (ct->index) {
1124                                 case CMhalt:
1125                                         cpu_halt();
1126                                         break;
1127                                 case CMbroken:
1128                                         keepbroken = 1;
1129                                         break;
1130                                 case CMnobroken:
1131                                         keepbroken = 0;
1132                                         break;
1133                                 case CMreboot:
1134                                         reboot();
1135                                         break;
1136                                 case CMpanic:
1137                                         *(uint32_t *) 0 = 0;
1138                                         panic("/dev/reboot");
1139                                         break;
1140                         }
1141                         poperror();
1142                         kfree(cb);
1143                         break;
1144
1145 #if 0
1146                 case Qsysstat:
1147                         for (id = 0; id < 32; id++) {
1148                                 if (active.machs & (1 << id)) {
1149                                         mp = MACHP(id);
1150                                         mp->cs = 0;
1151                                         mp->intr = 0;
1152                                         mp->syscall = 0;
1153                                         mp->pfault = 0;
1154                                         mp->tlbfault = 0;
1155                                         mp->tlbpurge = 0;
1156                                 }
1157                         }
1158                         break;
1159
1160                 case Qswap:
1161                         if (n >= sizeof buf)
1162                                 error(EINVAL, "n is bigger than sizeof buf for Qswap");
1163                         memmove(buf, va, n);    /* so we can NUL-terminate */
1164                         buf[n] = 0;
1165                         /* start a pager if not already started */
1166                         if (strncmp(buf, "start", 5) == 0) {
1167                                 kickpager();
1168                                 break;
1169                         }
1170                         if (!iseve())
1171                                 error(EPERM, ERROR_FIXME);
1172                         if (buf[0] < '0' || '9' < buf[0])
1173                                 error(EINVAL, ERROR_FIXME);
1174                         fd = strtoul(buf, 0, 0);
1175                         swc = fdtochan(fd, -1, 1, 1);
1176                         setswapchan(swc);
1177                         break;
1178 #endif
1179
1180                 case Qsysname:
1181                         if (offset != 0)
1182                                 error(EINVAL, ERROR_FIXME);
1183                         if (n <= 0 || n >= sizeof buf)
1184                                 error(EINVAL, ERROR_FIXME);
1185                         strncpy(buf, a, n);
1186                         buf[n] = 0;
1187                         if (buf[n - 1] == '\n')
1188                                 buf[n - 1] = 0;
1189                         kstrdup(&sysname, buf);
1190                         break;
1191
1192                 default:
1193                         printd("conswrite: %#llux\n", c->qid.path);
1194                         error(EINVAL, "bad QID in conswrite");
1195         }
1196         return n;
1197 }
1198
1199 struct dev consdevtab __devtab = {
1200         .name = "cons",
1201
1202         .reset = devreset,
1203         .init = consinit,
1204         .shutdown = devshutdown,
1205         .attach = consattach,
1206         .walk = conswalk,
1207         .stat = consstat,
1208         .open = consopen,
1209         .create = devcreate,
1210         .close = consclose,
1211         .read = consread,
1212         .bread = devbread,
1213         .write = conswrite,
1214         .bwrite = devbwrite,
1215         .remove = devremove,
1216         .wstat = devwstat,
1217         .power = devpower,
1218         .chaninfo = devchaninfo,
1219 };
1220
1221 static char *devname(void)
1222 {
1223         return consdevtab.name;
1224 }
1225
1226 static uint64_t uvorder = 0x0001020304050607ULL;
1227
1228 static uint8_t *le2int64_t(int64_t * to, uint8_t * f)
1229 {
1230         uint8_t *t, *o;
1231         int i;
1232
1233         t = (uint8_t *) to;
1234         o = (uint8_t *) & uvorder;
1235         for (i = 0; i < sizeof(int64_t); i++)
1236                 t[o[i]] = f[i];
1237         return f + sizeof(int64_t);
1238 }
1239
1240 static uint8_t *int64_t2le(uint8_t * t, int64_t from)
1241 {
1242         uint8_t *f, *o;
1243         int i;
1244
1245         f = (uint8_t *) & from;
1246         o = (uint8_t *) & uvorder;
1247         for (i = 0; i < sizeof(int64_t); i++)
1248                 t[i] = f[o[i]];
1249         return t + sizeof(int64_t);
1250 }
1251
1252 static long order = 0x00010203;
1253
1254 static uint8_t *le2long(long *to, uint8_t * f)
1255 {
1256         uint8_t *t, *o;
1257         int i;
1258
1259         t = (uint8_t *) & to;
1260         o = (uint8_t *) & order;
1261         for (i = 0; i < sizeof(long); i++)
1262                 t[o[i]] = f[i];
1263         return f + sizeof(long);
1264 }
1265
1266 static uint8_t *long2le(uint8_t * t, long from)
1267 {
1268         uint8_t *f, *o;
1269         int i;
1270
1271         f = (uint8_t *) & from;
1272         o = (uint8_t *) & order;
1273         for (i = 0; i < sizeof(long); i++)
1274                 t[i] = f[o[i]];
1275         return t + sizeof(long);
1276 }
1277
1278 char *Ebadtimectl = "bad time control";
1279
1280 /*
1281  *  like the old #c/time but with added info.  Return
1282  *
1283  *      secs    nanosecs        fastticks       fasthz
1284  */
1285 static int readtime(uint32_t off, char *buf, int n)
1286 {
1287         int64_t nsec, ticks;
1288         long sec;
1289         char str[7 * NUMSIZE];
1290
1291         if (fasthz == 0LL)
1292                 fasthz = __proc_global_info.tsc_freq;
1293 #if 0
1294         fastticks((uint64_t *) & fasthz);
1295         nsec = todget(&ticks);
1296 #endif
1297         ticks = read_tsc();
1298         nsec = tsc2nsec(ticks);
1299         sec = nsec / 1000000000ULL;
1300         snprintf(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
1301                          NUMSIZE - 1, sec,
1302                          VLNUMSIZE - 1, nsec, VLNUMSIZE - 1, ticks, VLNUMSIZE - 1, fasthz);
1303         return consreadstr(off, buf, n, str);
1304 }
1305
1306 /*
1307  *  set the time in seconds
1308  */
1309 static int writetime(char *buf, int n)
1310 {
1311         char b[13];
1312         long i;
1313         int64_t now;
1314
1315         if (n >= sizeof(b))
1316                 error(EINVAL, "bad size in writetime");
1317         strncpy(b, buf, n);
1318         b[n] = 0;
1319         i = strtol(b, 0, 0);
1320         if (i <= 0)
1321                 error(EINVAL, "Bad time in write");
1322         now = i * 1000000000LL;
1323 #if 0
1324         todset(now, 0, 0);
1325 #endif
1326         return n;
1327 }
1328
1329 /*
1330  *  read binary time info.  all numbers are little endian.
1331  *  ticks and nsec are syncronized.
1332  */
1333 static int readbintime(char *buf, int n)
1334 {
1335         int i;
1336         int64_t nsec, ticks;
1337         uint8_t *b = (uint8_t *) buf;
1338
1339         i = 0;
1340         if (fasthz == 0LL)
1341                 fasthz = __proc_global_info.tsc_freq;
1342 #if 0
1343         fastticks((uint64_t *) & fasthz);
1344         nsec = todget(&ticks);
1345 #endif
1346         ticks = read_tsc();
1347         nsec = tsc2nsec(ticks);
1348         if (n >= 3 * sizeof(uint64_t)) {
1349                 int64_t2le(b + 2 * sizeof(uint64_t), fasthz);
1350                 i += sizeof(uint64_t);
1351         }
1352         if (n >= 2 * sizeof(uint64_t)) {
1353                 int64_t2le(b + sizeof(uint64_t), ticks);
1354                 i += sizeof(uint64_t);
1355         }
1356         if (n >= 8) {
1357                 int64_t2le(b, nsec);
1358                 i += sizeof(int64_t);
1359         }
1360         return i;
1361 }
1362
1363 /*
1364  *  set any of the following
1365  *      - time in nsec
1366  *      - nsec trim applied over some seconds
1367  *      - clock frequency
1368  */
1369 static int writebintime(char *buf, int n)
1370 {
1371         uint8_t *p;
1372         int64_t delta = 0;
1373         long period = 0;
1374
1375         n--;
1376         p = (uint8_t *) buf + 1;
1377         switch (*buf) {
1378                 case 'n':
1379                         if (n < sizeof(int64_t))
1380                                 error(EINVAL, ERROR_FIXME);
1381                         le2int64_t(&delta, p);
1382 #if 0
1383                         todset(delta, 0, 0);
1384 #endif
1385                         break;
1386                 case 'd':
1387                         if (n < sizeof(int64_t) + sizeof(long))
1388                                 error(EINVAL, ERROR_FIXME);
1389                         p = le2int64_t(&delta, p);
1390                         le2long(&period, p);
1391 #if 0
1392                         todset(-1, delta, period);
1393 #endif
1394                         break;
1395                 case 'f':
1396                         if (n < sizeof(uint64_t))
1397                                 error(EINVAL, ERROR_FIXME);
1398                         le2int64_t(&fasthz, p);
1399                         if (fasthz <= 0)
1400                                 error(EINVAL, ERROR_FIXME);
1401 #if 0
1402                         todsetfreq(fasthz);
1403 #endif
1404                         break;
1405         }
1406         return n;
1407 }
1408
1409 /*
1410  * find_first_kid finds your immediate descendant. Not because we're
1411  * trying to give it a check from the estate, mind you. We're here on
1412  * much more unpleasant business. To make it easy to call this
1413  * multiple times without lots of fussy checking, we allow it to be
1414  * called with NULL pointers; hence find_first_kid(find_first_kid(x))
1415  * works even if x is chaste and will return NULL.
1416  */
1417 static struct proc *find_first_kid(struct proc *p)
1418 {
1419         struct proc *kid;
1420
1421         cv_lock(&p->child_wait);
1422         kid = TAILQ_FIRST(&p->children);
1423         if (kid) {
1424                 proc_incref(kid, 1);
1425                 proc_decref(p);
1426         }
1427         cv_unlock(&p->child_wait);
1428         return kid;
1429 }
1430
1431 /*
1432  * killkid manages population issues by killing your kids.  This is a
1433  * particular temporary (we think) function for ssh. As such, we are
1434  * going to make a Command Decision to never kill the top level
1435  * kid. We start on grandkids, in other words.  Hey, the parent/child
1436  * terminology was Ken's idea; go yell at him.  If you want, we can
1437  * rename this to DrownCuteKittens.
1438  *
1439  * This was hard to get right so it's way more verbose than you might think we need.
1440  * Sorry.
1441  */
1442 void killkid(void)
1443 {
1444         struct proc *check, *kid, *grandkid, *victim;
1445
1446         /* find first grandkid */
1447         proc_incref(current, 1);
1448         kid = find_first_kid(current);
1449         if (!kid) {
1450                 proc_decref(current);
1451                 return;
1452         }
1453         grandkid = find_first_kid(kid);
1454         if (!grandkid) {
1455                 proc_decref(kid);
1456                 return;
1457         }
1458         victim = grandkid;
1459         while (1) {
1460                 check = find_first_kid(victim);
1461                 if (!check)
1462                         break;
1463                 victim = check;
1464         }
1465         send_posix_signal(victim, SIGINT);
1466         proc_decref(victim);
1467 }