qio: remove qproduce()
[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         struct vmctl vmctl;
1031
1032         a = va;
1033         offset = off;
1034
1035         switch ((uint32_t) c->qid.path) {
1036                 case Qcons:
1037                         /*
1038                          * Can't page fault in putstrn, so copy the data locally.
1039                          */
1040                         l = n;
1041                         while (l > 0) {
1042                                 bp = l;
1043                                 if (bp > sizeof buf)
1044                                         bp = sizeof buf;
1045                                 memmove(buf, a, bp);
1046                                 putstrn0(buf, bp, 1);
1047                                 a += bp;
1048                                 l -= bp;
1049                         }
1050                         break;
1051
1052                 /* TODO: have it take a command about just *how* to kill the kid? */
1053                 case Qkillkid:
1054                         killkid();
1055                         break;
1056
1057                 case Qconsctl:
1058                         if (n >= sizeof(buf))
1059                                 n = sizeof(buf) - 1;
1060                         strncpy(buf, a, n);
1061                         buf[n] = 0;
1062                         for (a = buf; a;) {
1063                                 if (strncmp(a, "rawon", 5) == 0) {
1064                                         kbd.raw = 1;
1065                                         /* clumsy hack - wake up reader */
1066                                         ch = 0;
1067                                         qwrite(kbdq, &ch, 1);
1068                                 } else if (strncmp(a, "rawoff", 6) == 0) {
1069                                         kbd.raw = 0;
1070                                 } else if (strncmp(a, "ctlpon", 6) == 0) {
1071                                         kbd.ctlpoff = 0;
1072                                 } else if (strncmp(a, "ctlpoff", 7) == 0) {
1073                                         kbd.ctlpoff = 1;
1074                                 }
1075                                 if ((a = strchr(a, ' ')) != NULL)
1076                                         a++;
1077                         }
1078                         break;
1079
1080                 case Qtime:
1081                         if (!iseve())
1082                                 error(EPERM, "Hodie Natus Est Radici Frater");
1083                         return writetime(a, n);
1084
1085                 case Qbintime:
1086                         if (!iseve())
1087                                 error(EPERM, ERROR_FIXME);
1088                         return writebintime(a, n);
1089
1090 #if 0
1091                 case Qhostowner:
1092                         return hostownerwrite(a, n);
1093
1094                 case Qhostdomain:
1095                         return hostdomainwrite(a, n);
1096
1097                 case Quser:
1098                         return userwrite(a, n);
1099 #endif
1100
1101                 case Qnull:
1102                         break;
1103
1104                 case Qconfig:
1105                         error(EPERM, "Cannot write to config QID");
1106                         break;
1107
1108                 case Qsysctl:
1109                         //if (!iseve()) error(EPERM, ERROR_FIXME);
1110                         cb = parsecmd(a, n);
1111                         if (cb->nf > 1)
1112                         printd("cons sysctl cmd %s\n", cb->f[0]);
1113
1114                 case Qreboot:
1115                         if (!iseve())
1116                                 error(EPERM, ERROR_FIXME);
1117                         cb = parsecmd(a, n);
1118
1119                         if (waserror()) {
1120                                 kfree(cb);
1121                                 nexterror();
1122                         }
1123                         ct = lookupcmd(cb, rebootmsg, ARRAY_SIZE(rebootmsg));
1124                         switch (ct->index) {
1125                                 case CMhalt:
1126                                         cpu_halt();
1127                                         break;
1128                                 case CMbroken:
1129                                         keepbroken = 1;
1130                                         break;
1131                                 case CMnobroken:
1132                                         keepbroken = 0;
1133                                         break;
1134                                 case CMreboot:
1135                                         reboot();
1136                                         break;
1137                                 case CMpanic:
1138                                         *(uint32_t *) 0 = 0;
1139                                         panic("/dev/reboot");
1140                                         break;
1141                         }
1142                         poperror();
1143                         kfree(cb);
1144                         break;
1145
1146 #if 0
1147                 case Qsysstat:
1148                         for (id = 0; id < 32; id++) {
1149                                 if (active.machs & (1 << id)) {
1150                                         mp = MACHP(id);
1151                                         mp->cs = 0;
1152                                         mp->intr = 0;
1153                                         mp->syscall = 0;
1154                                         mp->pfault = 0;
1155                                         mp->tlbfault = 0;
1156                                         mp->tlbpurge = 0;
1157                                 }
1158                         }
1159                         break;
1160
1161                 case Qswap:
1162                         if (n >= sizeof buf)
1163                                 error(EINVAL, "n is bigger than sizeof buf for Qswap");
1164                         memmove(buf, va, n);    /* so we can NUL-terminate */
1165                         buf[n] = 0;
1166                         /* start a pager if not already started */
1167                         if (strncmp(buf, "start", 5) == 0) {
1168                                 kickpager();
1169                                 break;
1170                         }
1171                         if (!iseve())
1172                                 error(EPERM, ERROR_FIXME);
1173                         if (buf[0] < '0' || '9' < buf[0])
1174                                 error(EINVAL, ERROR_FIXME);
1175                         fd = strtoul(buf, 0, 0);
1176                         swc = fdtochan(fd, -1, 1, 1);
1177                         setswapchan(swc);
1178                         break;
1179 #endif
1180
1181                 case Qsysname:
1182                         if (offset != 0)
1183                                 error(EINVAL, ERROR_FIXME);
1184                         if (n <= 0 || n >= sizeof buf)
1185                                 error(EINVAL, ERROR_FIXME);
1186                         strncpy(buf, a, n);
1187                         buf[n] = 0;
1188                         if (buf[n - 1] == '\n')
1189                                 buf[n - 1] = 0;
1190                         kstrdup(&sysname, buf);
1191                         break;
1192
1193                 default:
1194                         printd("conswrite: %#llux\n", c->qid.path);
1195                         error(EINVAL, "bad QID in conswrite");
1196         }
1197         return n;
1198 }
1199
1200 struct dev consdevtab __devtab = {
1201         .name = "cons",
1202
1203         .reset = devreset,
1204         .init = consinit,
1205         .shutdown = devshutdown,
1206         .attach = consattach,
1207         .walk = conswalk,
1208         .stat = consstat,
1209         .open = consopen,
1210         .create = devcreate,
1211         .close = consclose,
1212         .read = consread,
1213         .bread = devbread,
1214         .write = conswrite,
1215         .bwrite = devbwrite,
1216         .remove = devremove,
1217         .wstat = devwstat,
1218         .power = devpower,
1219         .chaninfo = devchaninfo,
1220 };
1221
1222 static char *devname(void)
1223 {
1224         return consdevtab.name;
1225 }
1226
1227 static uint64_t uvorder = 0x0001020304050607ULL;
1228
1229 static uint8_t *le2int64_t(int64_t * to, uint8_t * f)
1230 {
1231         uint8_t *t, *o;
1232         int i;
1233
1234         t = (uint8_t *) to;
1235         o = (uint8_t *) & uvorder;
1236         for (i = 0; i < sizeof(int64_t); i++)
1237                 t[o[i]] = f[i];
1238         return f + sizeof(int64_t);
1239 }
1240
1241 static uint8_t *int64_t2le(uint8_t * t, int64_t from)
1242 {
1243         uint8_t *f, *o;
1244         int i;
1245
1246         f = (uint8_t *) & from;
1247         o = (uint8_t *) & uvorder;
1248         for (i = 0; i < sizeof(int64_t); i++)
1249                 t[i] = f[o[i]];
1250         return t + sizeof(int64_t);
1251 }
1252
1253 static long order = 0x00010203;
1254
1255 static uint8_t *le2long(long *to, uint8_t * f)
1256 {
1257         uint8_t *t, *o;
1258         int i;
1259
1260         t = (uint8_t *) & to;
1261         o = (uint8_t *) & order;
1262         for (i = 0; i < sizeof(long); i++)
1263                 t[o[i]] = f[i];
1264         return f + sizeof(long);
1265 }
1266
1267 static uint8_t *long2le(uint8_t * t, long from)
1268 {
1269         uint8_t *f, *o;
1270         int i;
1271
1272         f = (uint8_t *) & from;
1273         o = (uint8_t *) & order;
1274         for (i = 0; i < sizeof(long); i++)
1275                 t[i] = f[o[i]];
1276         return t + sizeof(long);
1277 }
1278
1279 char *Ebadtimectl = "bad time control";
1280
1281 /*
1282  *  like the old #c/time but with added info.  Return
1283  *
1284  *      secs    nanosecs        fastticks       fasthz
1285  */
1286 static int readtime(uint32_t off, char *buf, int n)
1287 {
1288         int64_t nsec, ticks;
1289         long sec;
1290         char str[7 * NUMSIZE];
1291
1292         if (fasthz == 0LL)
1293                 fasthz = __proc_global_info.tsc_freq;
1294 #if 0
1295         fastticks((uint64_t *) & fasthz);
1296         nsec = todget(&ticks);
1297 #endif
1298         ticks = read_tsc();
1299         nsec = tsc2nsec(ticks);
1300         sec = nsec / 1000000000ULL;
1301         snprintf(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
1302                          NUMSIZE - 1, sec,
1303                          VLNUMSIZE - 1, nsec, VLNUMSIZE - 1, ticks, VLNUMSIZE - 1, fasthz);
1304         return consreadstr(off, buf, n, str);
1305 }
1306
1307 /*
1308  *  set the time in seconds
1309  */
1310 static int writetime(char *buf, int n)
1311 {
1312         char b[13];
1313         long i;
1314         int64_t now;
1315
1316         if (n >= sizeof(b))
1317                 error(EINVAL, "bad size in writetime");
1318         strncpy(b, buf, n);
1319         b[n] = 0;
1320         i = strtol(b, 0, 0);
1321         if (i <= 0)
1322                 error(EINVAL, "Bad time in write");
1323         now = i * 1000000000LL;
1324 #if 0
1325         todset(now, 0, 0);
1326 #endif
1327         return n;
1328 }
1329
1330 /*
1331  *  read binary time info.  all numbers are little endian.
1332  *  ticks and nsec are syncronized.
1333  */
1334 static int readbintime(char *buf, int n)
1335 {
1336         int i;
1337         int64_t nsec, ticks;
1338         uint8_t *b = (uint8_t *) buf;
1339
1340         i = 0;
1341         if (fasthz == 0LL)
1342                 fasthz = __proc_global_info.tsc_freq;
1343 #if 0
1344         fastticks((uint64_t *) & fasthz);
1345         nsec = todget(&ticks);
1346 #endif
1347         ticks = read_tsc();
1348         nsec = tsc2nsec(ticks);
1349         if (n >= 3 * sizeof(uint64_t)) {
1350                 int64_t2le(b + 2 * sizeof(uint64_t), fasthz);
1351                 i += sizeof(uint64_t);
1352         }
1353         if (n >= 2 * sizeof(uint64_t)) {
1354                 int64_t2le(b + sizeof(uint64_t), ticks);
1355                 i += sizeof(uint64_t);
1356         }
1357         if (n >= 8) {
1358                 int64_t2le(b, nsec);
1359                 i += sizeof(int64_t);
1360         }
1361         return i;
1362 }
1363
1364 /*
1365  *  set any of the following
1366  *      - time in nsec
1367  *      - nsec trim applied over some seconds
1368  *      - clock frequency
1369  */
1370 static int writebintime(char *buf, int n)
1371 {
1372         uint8_t *p;
1373         int64_t delta = 0;
1374         long period = 0;
1375
1376         n--;
1377         p = (uint8_t *) buf + 1;
1378         switch (*buf) {
1379                 case 'n':
1380                         if (n < sizeof(int64_t))
1381                                 error(EINVAL, ERROR_FIXME);
1382                         le2int64_t(&delta, p);
1383 #if 0
1384                         todset(delta, 0, 0);
1385 #endif
1386                         break;
1387                 case 'd':
1388                         if (n < sizeof(int64_t) + sizeof(long))
1389                                 error(EINVAL, ERROR_FIXME);
1390                         p = le2int64_t(&delta, p);
1391                         le2long(&period, p);
1392 #if 0
1393                         todset(-1, delta, period);
1394 #endif
1395                         break;
1396                 case 'f':
1397                         if (n < sizeof(uint64_t))
1398                                 error(EINVAL, ERROR_FIXME);
1399                         le2int64_t(&fasthz, p);
1400                         if (fasthz <= 0)
1401                                 error(EINVAL, ERROR_FIXME);
1402 #if 0
1403                         todsetfreq(fasthz);
1404 #endif
1405                         break;
1406         }
1407         return n;
1408 }
1409
1410 /*
1411  * find_first_kid finds your immediate descendant. Not because we're
1412  * trying to give it a check from the estate, mind you. We're here on
1413  * much more unpleasant business. To make it easy to call this
1414  * multiple times without lots of fussy checking, we allow it to be
1415  * called with NULL pointers; hence find_first_kid(find_first_kid(x))
1416  * works even if x is chaste and will return NULL.
1417  */
1418 static struct proc *find_first_kid(struct proc *p)
1419 {
1420         struct proc *kid;
1421
1422         cv_lock(&p->child_wait);
1423         kid = TAILQ_FIRST(&p->children);
1424         if (kid) {
1425                 proc_incref(kid, 1);
1426                 proc_decref(p);
1427         }
1428         cv_unlock(&p->child_wait);
1429         return kid;
1430 }
1431
1432 /*
1433  * killkid manages population issues by killing your kids.  This is a
1434  * particular temporary (we think) function for ssh. As such, we are
1435  * going to make a Command Decision to never kill the top level
1436  * kid. We start on grandkids, in other words.  Hey, the parent/child
1437  * terminology was Ken's idea; go yell at him.  If you want, we can
1438  * rename this to DrownCuteKittens.
1439  *
1440  * This was hard to get right so it's way more verbose than you might think we need.
1441  * Sorry.
1442  */
1443 void killkid(void)
1444 {
1445         struct proc *check, *kid, *grandkid, *victim;
1446
1447         /* find first grandkid */
1448         proc_incref(current, 1);
1449         kid = find_first_kid(current);
1450         if (!kid) {
1451                 proc_decref(current);
1452                 return;
1453         }
1454         grandkid = find_first_kid(kid);
1455         if (!grandkid) {
1456                 proc_decref(kid);
1457                 return;
1458         }
1459         victim = grandkid;
1460         while (1) {
1461                 check = find_first_kid(victim);
1462                 if (!check)
1463                         break;
1464                 victim = check;
1465         }
1466         send_posix_signal(victim, SIGINT);
1467         proc_decref(victim);
1468 }