2 #include "../port/lib.h"
6 #include "../port/error.h"
10 void (*consdebug)(void) = nil;
11 void (*screenputs)(char*, int) = nil;
13 Queue* serialoq; /* serial console output */
14 Queue* kprintoq; /* console output, for /dev/kprint */
15 ulong kprintinuse; /* test and set whether /dev/kprint is open */
16 int iprintscreenputs = 1;
23 static int readtime(ulong, char*, int);
24 static int readbintime(char*, int);
25 static int writetime(char*, int);
26 static int writebintime(char*, int);
37 CMreboot, "reboot", 0,
51 return qlen(serialoq) > 0;
62 if(m->ticks - now >= HZ)
67 kmesgputs(char *str, int n)
72 /* take the tail of huge writes */
73 if(n > sizeof kmesg.buf){
74 d = n - sizeof kmesg.buf;
79 /* slide the buffer down to make room */
81 if(nn + n >= sizeof kmesg.buf){
82 d = nn + n - sizeof kmesg.buf;
84 memmove(kmesg.buf, kmesg.buf+d, sizeof kmesg.buf-d);
88 /* copy the data in */
89 memmove(kmesg.buf+nn, str, n);
96 * Print a string on the console. Convert \n to \r\n for serial
97 * line consoles. Locking of the queues is left up to the screen
98 * or uart code. Multi-line messages to serial consoles may get
99 * interspersed with other messages.
102 putstrn0(char *str, int n, int usewrite)
106 int (*wq)(Queue*, void*, int);
109 * how many different output devices do we need?
114 * if someone is reading /dev/kprint,
115 * put the message there.
116 * if not and there's an attached bit mapped display,
117 * put the message there.
119 * if there's a serial line being used as a console,
120 * put the message there.
122 wq = usewrite && islo() ? qwrite : qiwrite;
123 if(kprintoq != nil && !qisclosed(kprintoq))
124 (*wq)(kprintoq, str, n);
125 else if(screenputs != nil)
134 t = memchr(str, '\n', n);
137 (*wq)(serialoq, str, m);
138 (*wq)(serialoq, "\r\n", 2);
142 (*wq)(serialoq, str, n);
149 putstrn(char *str, int n)
155 print(char *fmt, ...)
162 n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
170 * Want to interlock iprints to avoid interlaced output on
171 * multiprocessor, but don't want to deadlock if one processor
172 * dies during print and another has something important to say.
173 * Make a good faith effort.
175 static Lock iprintlock;
177 iprintcanlock(Lock *l)
181 for(i=0; i<1000; i++){
184 if(l->m == MACHP(m->machno))
192 iprint(char *fmt, ...)
200 n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
202 locked = iprintcanlock(&iprintlock);
203 if(screenputs != nil && iprintscreenputs)
214 panic(char *fmt, ...)
220 kprintoq = nil; /* don't try to write to /dev/kprint */
227 strcpy(buf, "panic: ");
229 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
238 /* reboot cpu servers and headless machines when not debugging */
239 if(getconf("*debug") == nil)
240 if(cpuserver || !conf.monitor)
243 /* otherwise, just hang */
244 while(islo()) idlehands();
248 /* libmp at least contains a few calls to sysfatal; simulate with panic */
250 sysfatal(char *fmt, ...)
256 vseprint(err, err + sizeof err, fmt, arg);
258 panic("sysfatal: %s", err);
264 panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
268 pprint(char *fmt, ...)
273 char buf[2*PRINTSIZE];
275 if(up == nil || up->fgrp == nil)
279 if(c==nil || (c->flag&CMSG)!=0 || (c->mode!=OWRITE && c->mode!=ORDWR))
281 n = snprint(buf, sizeof buf, "%s %lud: ", up->text, up->pid);
283 n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
288 devtab[c->type]->write(c, buf, n, c->offset);
329 static Dirtab consdir[]={
330 ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
331 "bintime", {Qbintime}, 24, 0664,
332 "cons", {Qcons}, 0, 0660,
333 "consctl", {Qconsctl}, 0, 0220,
334 "cputime", {Qcputime}, 6*NUMSIZE, 0444,
335 "drivers", {Qdrivers}, 0, 0444,
336 "hostdomain", {Qhostdomain}, DOMLEN, 0664,
337 "hostowner", {Qhostowner}, 0, 0664,
338 "kmesg", {Qkmesg}, 0, 0440,
339 "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440,
340 "null", {Qnull}, 0, 0666,
341 "osversion", {Qosversion}, 0, 0444,
342 "pid", {Qpid}, NUMSIZE, 0444,
343 "ppid", {Qppid}, NUMSIZE, 0444,
344 "random", {Qrandom}, 0, 0444,
345 "reboot", {Qreboot}, 0, 0220,
346 "sysname", {Qsysname}, 0, 0664,
347 "sysstat", {Qsysstat}, 0, 0664,
348 "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664,
349 "user", {Quser}, 0, 0666,
350 "zero", {Qzero}, 0, 0444,
351 "config", {Qconfig}, 0, 0444,
352 "mordor", {Qmordor}, 0, 0666,
356 readnum(ulong off, char *buf, ulong n, ulong val, int size)
360 snprint(tmp, sizeof(tmp), "%*lud", size-1, val);
366 memmove(buf, tmp+off, n);
371 readstr(ulong off, char *buf, ulong n, char *str)
380 memmove(buf, str+off, n);
392 consattach(char *spec)
394 return devattach('c', spec);
398 conswalk(Chan *c, Chan *nc, char **name, int nname)
400 return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
404 consstat(Chan *c, uchar *dp, int n)
406 return devstat(c, dp, n, consdir, nelem(consdir), devgen);
410 consopen(Chan *c, int omode)
413 c = devopen(c, omode, consdir, nelem(consdir), devgen);
414 switch((ulong)c->qid.path){
416 if(tas(&kprintinuse) != 0){
421 kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
426 qnoblock(kprintoq, 1);
429 c->iounit = qiomaxatomic;
438 switch((ulong)c->qid.path){
439 /* close of kprint allows other opens */
443 qhangup(kprintoq, nil);
450 consread(Chan *c, void *buf, long n, vlong off)
458 extern char configfile[];
463 switch((ulong)c->qid.path){
465 return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
476 /* easiest to format in a separate buffer and copy out */
477 for(i=0; i<6 && NUMSIZE*i<k+n; i++){
480 l = MACHP(0)->ticks - l;
481 readnum(0, tmp+NUMSIZE*i, NUMSIZE, tk2ms(l), NUMSIZE);
483 memmove(buf, tmp+k, n);
488 * This is unlocked to avoid tying up a process
489 * that's writing to the buffer. kmesg.n never
490 * gets smaller, so worst case the reader will
491 * see a slurred buffer.
498 memmove(buf, kmesg.buf+off, n);
503 return qread(kprintoq, buf, n);
506 return readnum((ulong)offset, buf, n, up->pid, NUMSIZE);
509 return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE);
512 return readtime((ulong)offset, buf, n);
515 return readbintime(buf, n);
518 return readstr((ulong)offset, buf, n, eve);
521 return readstr((ulong)offset, buf, n, hostdomain);
524 return readstr((ulong)offset, buf, n, up->user);
530 return readstr((ulong)offset, buf, n, configfile);
533 b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */
535 for(id = 0; id < MAXMACH; id++) {
536 if(active.machs[id]) {
538 readnum(0, bp, NUMSIZE, id, NUMSIZE);
540 readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
542 readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
544 readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
546 readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
548 readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
550 readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
552 readnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
557 readnum(0, bp, NUMSIZE,
558 (mp->perf.avg_inidle*100)/l, NUMSIZE);
560 readnum(0, bp, NUMSIZE,
561 (mp->perf.avg_inintr*100)/l, NUMSIZE);
570 n = readstr((ulong)offset, buf, n, b);
578 return readstr((ulong)offset, buf, n, sysname);
581 return randomread(buf, n);
584 b = smalloc(READSTR);
586 for(i = 0; devtab[i] != nil; i++)
587 k += snprint(b+k, READSTR-k, "#%C %s\n",
588 devtab[i]->dc, devtab[i]->name);
593 n = readstr((ulong)offset, buf, n, b);
603 error("one does not simply read from mordor");
607 snprint(tmp, sizeof tmp, "2000");
608 n = readstr((ulong)offset, buf, n, tmp);
612 print("consread %#llux\n", c->qid.path);
615 return -1; /* never reached */
619 conswrite(Chan *c, void *va, long n, vlong off)
633 switch((ulong)c->qid.path){
636 * Can't page fault in putstrn, so copy the data locally.
644 putstrn0(buf, bp, 1);
656 return writetime(a, n);
661 return writebintime(a, n);
664 return hostownerwrite(a, n);
667 return hostdomainwrite(a, n);
670 return userwrite(a, n);
688 ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
691 rebootcmd(cb->nf-1, cb->f+1);
695 panic("/dev/reboot");
707 for(id = 0; id < MAXMACH; id++) {
708 if(active.machs[id]) {
723 if(n <= 0 || n >= sizeof buf)
729 kstrdup(&sysname, buf);
733 error("one does not simply write into mordor");
737 print("conswrite: %#llux\n", c->qid.path);
764 static uvlong uvorder = 0x0001020304050607ULL;
767 le2vlong(vlong *to, uchar *f)
773 o = (uchar*)&uvorder;
774 for(i = 0; i < sizeof(vlong); i++)
776 return f+sizeof(vlong);
780 vlong2le(uchar *t, vlong from)
786 o = (uchar*)&uvorder;
787 for(i = 0; i < sizeof(vlong); i++)
789 return t+sizeof(vlong);
792 static long order = 0x00010203;
795 le2long(long *to, uchar *f)
802 for(i = 0; i < sizeof(long); i++)
804 return f+sizeof(long);
808 long2le(uchar *t, long from)
815 for(i = 0; i < sizeof(long); i++)
817 return t+sizeof(long);
820 char *Ebadtimectl = "bad time control";
823 * like the old #c/time but with added info. Return
825 * secs nanosecs fastticks fasthz
828 readtime(ulong off, char *buf, int n)
834 nsec = todget(&ticks);
836 fastticks((uvlong*)&fasthz);
837 sec = nsec/1000000000ULL;
838 snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
842 VLNUMSIZE-1, fasthz);
843 return readstr(off, buf, n, str);
847 * set the time in seconds
850 writetime(char *buf, int n)
863 now = i*1000000000LL;
869 * read binary time info. all numbers are little endian.
870 * ticks and nsec are syncronized.
873 readbintime(char *buf, int n)
877 uchar *b = (uchar*)buf;
881 fastticks((uvlong*)&fasthz);
882 nsec = todget(&ticks);
883 if(n >= 3*sizeof(uvlong)){
884 vlong2le(b+2*sizeof(uvlong), fasthz);
887 if(n >= 2*sizeof(uvlong)){
888 vlong2le(b+sizeof(uvlong), ticks);
899 * set any of the following
901 * - nsec trim applied over some seconds
905 writebintime(char *buf, int n)
916 if(n < sizeof(vlong))
922 if(n < sizeof(vlong)+sizeof(long))
924 p = le2vlong(&delta, p);
926 todset(-1, delta, period);
929 if(n < sizeof(uvlong))
931 le2vlong(&fasthz, p);
945 once = active.machs[m->machno];
946 active.machs[m->machno] = 0;
950 iprint("cpu%d: exiting\n", m->machno);
952 /* wait for any other processors to shutdown */
954 for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
956 if(memchr(active.machs, 1, MAXMACH) == nil && consactive() == 0)