devcons.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414
  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. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include <authsrv.h>
  16. enum {
  17. Nconsdevs = 64, /* max number of consoles */
  18. /* Consdev flags */
  19. Ciprint = 2, /* call this fn from iprint */
  20. Cntorn = 4, /* change \n to \r\n */
  21. };
  22. typedef struct Consdev Consdev;
  23. struct Consdev {
  24. Chan *c; /* external file */
  25. Queue *q; /* i/o queue, if any */
  26. void (*fn)(char *, int); /* i/o function when no queue */
  27. int flags;
  28. };
  29. extern int printallsyscalls;
  30. void (*consdebug)(void) = nil;
  31. void (*consputs)(char *, int) = nil;
  32. void (*consuartputs)(char *, int) = nil;
  33. static void kmesgputs(char *, int);
  34. static Lock consdevslock;
  35. static int nconsdevs = 1;
  36. static Consdev consdevs[Nconsdevs] = /* keep this order */
  37. {
  38. {nil, nil, kmesgputs, 0}, /* kmesg */
  39. };
  40. static int nkeybqs;
  41. static int nkeybprocs;
  42. static Queue *keybqs[Nconsdevs];
  43. static int keybprocs[Nconsdevs];
  44. static Queue *keybq; /* unprocessed console input */
  45. static Queue *lineq; /* processed console input */
  46. int panicking;
  47. static struct
  48. {
  49. QLock QLock;
  50. int raw; /* true if we shouldn't process input */
  51. Ref ctl; /* number of opens to the control file */
  52. int x; /* index into line */
  53. char line[1024]; /* current input line */
  54. int count;
  55. int ctlpoff;
  56. /* a place to save up characters at interrupt time before dumping them in the queue */
  57. Lock lockputc;
  58. char istage[1024];
  59. char *iw;
  60. char *ir;
  61. char *ie;
  62. } kbd = {
  63. .iw = kbd.istage,
  64. .ir = kbd.istage,
  65. .ie = kbd.istage + sizeof(kbd.istage),
  66. };
  67. char *sysname;
  68. i64 fasthz;
  69. static void seedrand(void);
  70. static int readtime(u32, char *, int);
  71. static int readbintime(char *, int);
  72. static int writetime(char *, int);
  73. static int writebintime(char *, int);
  74. enum {
  75. CMhalt,
  76. CMreboot,
  77. CMpanic,
  78. };
  79. Cmdtab rebootmsg[] =
  80. {
  81. {CMhalt, "halt", 1},
  82. {CMreboot, "reboot", 0},
  83. {CMpanic, "panic", 0},
  84. };
  85. int
  86. addconsdev(Queue *q, void (*fn)(char *, int), int i, int flags)
  87. {
  88. Consdev *c;
  89. ilock(&consdevslock);
  90. if(i < 0)
  91. i = nconsdevs;
  92. else
  93. flags |= consdevs[i].flags;
  94. if(nconsdevs == Nconsdevs)
  95. panic("Nconsdevs too small");
  96. c = &consdevs[i];
  97. c->flags = flags;
  98. c->q = q;
  99. c->fn = fn;
  100. if(i == nconsdevs)
  101. nconsdevs++;
  102. iunlock(&consdevslock);
  103. return i;
  104. }
  105. void
  106. delconsdevs(void)
  107. {
  108. nconsdevs = 2; /* throw away serial consoles and kprint */
  109. consdevs[1].q = nil;
  110. }
  111. static void
  112. conskbdqproc(void *a)
  113. {
  114. char buf[64];
  115. Queue *q;
  116. int nr;
  117. q = a;
  118. while((nr = qread(q, buf, sizeof(buf))) > 0)
  119. qwrite(keybq, buf, nr);
  120. pexit("hangup", 1);
  121. }
  122. static void
  123. kickkbdq(void)
  124. {
  125. Proc *up = externup();
  126. int i;
  127. if(up != nil && nkeybqs > 1 && nkeybprocs != nkeybqs){
  128. lock(&consdevslock);
  129. if(nkeybprocs == nkeybqs){
  130. unlock(&consdevslock);
  131. return;
  132. }
  133. for(i = 0; i < nkeybqs; i++)
  134. if(keybprocs[i] == 0){
  135. keybprocs[i] = 1;
  136. kproc("conskbdq", conskbdqproc, keybqs[i]);
  137. }
  138. unlock(&consdevslock);
  139. }
  140. }
  141. int
  142. addkbdq(Queue *q, int i)
  143. {
  144. int n;
  145. ilock(&consdevslock);
  146. if(i < 0)
  147. i = nkeybqs++;
  148. if(nkeybqs == Nconsdevs)
  149. panic("Nconsdevs too small");
  150. keybqs[i] = q;
  151. n = nkeybqs;
  152. iunlock(&consdevslock);
  153. switch(n){
  154. case 1:
  155. /* if there's just one, pull directly from it. */
  156. keybq = q;
  157. break;
  158. case 2:
  159. /* later we'll merge bytes from all keybqs into a single keybq */
  160. keybq = qopen(4 * 1024, 0, 0, 0);
  161. if(keybq == nil)
  162. panic("no keybq");
  163. /* fall */
  164. default:
  165. kickkbdq();
  166. }
  167. return i;
  168. }
  169. void
  170. printinit(void)
  171. {
  172. lineq = qopen(2 * 1024, 0, nil, nil);
  173. if(lineq == nil)
  174. panic("printinit");
  175. qnoblock(lineq, 1);
  176. }
  177. int
  178. consactive(void)
  179. {
  180. int i;
  181. Queue *q;
  182. for(i = 0; i < nconsdevs; i++)
  183. if((q = consdevs[i].q) != nil && qlen(q) > 0)
  184. return 1;
  185. return 0;
  186. }
  187. /*
  188. * Log console output so it can be retrieved via /dev/kmesg.
  189. * This is good for catching boot-time messages after the fact.
  190. */
  191. struct {
  192. Lock lk;
  193. char buf[1048576];
  194. u32 n;
  195. } kmesg;
  196. static void
  197. kmesgputs(char *str, int n)
  198. {
  199. u32 nn, d;
  200. ilock(&kmesg.lk);
  201. /* take the tail of huge writes */
  202. if(n > sizeof kmesg.buf){
  203. d = n - sizeof kmesg.buf;
  204. str += d;
  205. n -= d;
  206. }
  207. /* slide the buffer down to make room */
  208. nn = kmesg.n;
  209. if(nn + n >= sizeof kmesg.buf){
  210. d = nn + n - sizeof kmesg.buf;
  211. if(d)
  212. memmove(kmesg.buf, kmesg.buf + d, sizeof kmesg.buf - d);
  213. nn -= d;
  214. }
  215. /* copy the data in */
  216. memmove(kmesg.buf + nn, str, n);
  217. nn += n;
  218. kmesg.n = nn;
  219. iunlock(&kmesg.lk);
  220. }
  221. /*
  222. * Print a string on the console. Convert \n to \r\n for serial
  223. * line consoles. Locking of the queues is left up to the screen
  224. * or uart code. Multi-line messages to serial consoles may get
  225. * interspersed with other messages.
  226. */
  227. static void
  228. putstrn0(char *str, int n, int usewrite)
  229. {
  230. kmesgputs(str, n);
  231. if(consputs != nil)
  232. consputs(str, n);
  233. if(consuartputs != nil)
  234. consuartputs(str, n);
  235. }
  236. void
  237. putstrn(char *str, int n)
  238. {
  239. static Lock lock;
  240. ilock(&lock);
  241. putstrn0(str, n, 0);
  242. iunlock(&lock);
  243. }
  244. int
  245. print(char *fmt, ...)
  246. {
  247. int n;
  248. va_list arg;
  249. char buf[PRINTSIZE];
  250. va_start(arg, fmt);
  251. n = vseprint(buf, buf + sizeof(buf), fmt, arg) - buf;
  252. va_end(arg);
  253. putstrn(buf, n);
  254. return n;
  255. }
  256. int
  257. kmprint(char *fmt, ...)
  258. {
  259. int n;
  260. va_list arg;
  261. char buf[PRINTSIZE];
  262. va_start(arg, fmt);
  263. n = vseprint(buf, buf + sizeof(buf), fmt, arg) - buf;
  264. va_end(arg);
  265. kmesgputs(buf, n);
  266. return n;
  267. }
  268. /*
  269. * Want to interlock iprints to avoid interlaced output on
  270. * multiprocessor, but don't want to deadlock if one processor
  271. * dies during print and another has something important to say.
  272. * Make a good faith effort.
  273. */
  274. static Lock iprintlock;
  275. static int
  276. iprintcanlock(Lock *l)
  277. {
  278. int i;
  279. for(i = 0; i < 1000; i++){
  280. if(canlock(l))
  281. return 1;
  282. if(l->m == machp())
  283. return 0;
  284. microdelay(100);
  285. }
  286. return 0;
  287. }
  288. int
  289. iprint(char *fmt, ...)
  290. {
  291. Mpl pl;
  292. int i, n, locked;
  293. va_list arg;
  294. char buf[PRINTSIZE];
  295. pl = splhi();
  296. va_start(arg, fmt);
  297. n = vseprint(buf, buf + sizeof(buf), fmt, arg) - buf;
  298. va_end(arg);
  299. locked = iprintcanlock(&iprintlock);
  300. for(i = 0; i < nconsdevs; i++)
  301. if((consdevs[i].flags & Ciprint) != 0){
  302. if(consdevs[i].q != nil)
  303. qiwrite(consdevs[i].q, buf, n);
  304. else
  305. consdevs[i].fn(buf, n);
  306. }
  307. if(locked)
  308. unlock(&iprintlock);
  309. splx(pl);
  310. return n;
  311. }
  312. void
  313. panic(char *fmt, ...)
  314. {
  315. int n;
  316. Mpl pl;
  317. va_list arg;
  318. char buf[PRINTSIZE];
  319. consdevs[1].q = nil; /* don't try to write to /dev/kprint */
  320. if(panicking)
  321. for(;;)
  322. ;
  323. panicking = 1;
  324. pl = splhi();
  325. seprint(buf, buf + sizeof buf, "panic: cpu%d: ", machp()->machno);
  326. va_start(arg, fmt);
  327. n = vseprint(buf + strlen(buf), buf + sizeof(buf), fmt, arg) - buf;
  328. va_end(arg);
  329. iprint("%s\n", buf);
  330. if(consdebug)
  331. (*consdebug)();
  332. splx(pl);
  333. //prflush();
  334. buf[n] = '\n';
  335. putstrn(buf, n + 1);
  336. dumpstack();
  337. stacksnippet();
  338. delay(1000); /* give time to consoles */
  339. die("wait forever");
  340. exit(1);
  341. }
  342. /* libmp at least contains a few calls to sysfatal; simulate with panic */
  343. void
  344. sysfatal(char *fmt, ...)
  345. {
  346. char err[256];
  347. va_list arg;
  348. va_start(arg, fmt);
  349. vseprint(err, err + sizeof err, fmt, arg);
  350. va_end(arg);
  351. panic("sysfatal: %s", err);
  352. }
  353. void
  354. _assert(char *fmt)
  355. {
  356. panic("assert failed at %#p: %s", getcallerpc(), fmt);
  357. }
  358. int
  359. pprint(char *fmt, ...)
  360. {
  361. Proc *up = externup();
  362. int n;
  363. Chan *c;
  364. va_list arg;
  365. char buf[2 * PRINTSIZE];
  366. if(up == nil || up->fgrp == nil)
  367. return 0;
  368. c = up->fgrp->fd[2];
  369. if(c == 0 || (c->mode != OWRITE && c->mode != ORDWR))
  370. return 0;
  371. n = snprint(buf, sizeof buf, "%s %d: ", up->text, up->pid);
  372. va_start(arg, fmt);
  373. n = vseprint(buf + n, buf + sizeof(buf), fmt, arg) - buf;
  374. va_end(arg);
  375. if(waserror())
  376. return 0;
  377. c->dev->write(c, buf, n, c->offset);
  378. poperror();
  379. lock(&c->r.l);
  380. c->offset += n;
  381. unlock(&c->r.l);
  382. return n;
  383. }
  384. static void
  385. echo(char *buf, int n)
  386. {
  387. Mpl pl;
  388. static int ctrlt;
  389. char *e, *p;
  390. if(n == 0)
  391. return;
  392. e = buf + n;
  393. for(p = buf; p < e; p++){
  394. switch(*p){
  395. case 0x10: /* ^P */
  396. if(cpuserver && !kbd.ctlpoff){
  397. active.exiting = 1;
  398. return;
  399. }
  400. break;
  401. case 0x14: /* ^T */
  402. ctrlt++;
  403. if(ctrlt > 2)
  404. ctrlt = 2;
  405. continue;
  406. }
  407. if(ctrlt != 2)
  408. continue;
  409. /* ^T escapes */
  410. ctrlt = 0;
  411. switch(*p){
  412. case 'S':
  413. pl = splhi();
  414. dumpstack();
  415. procdump();
  416. splx(pl);
  417. return;
  418. case 's':
  419. dumpstack();
  420. return;
  421. case 'x':
  422. ixsummary();
  423. mallocsummary();
  424. // memorysummary();
  425. pagersummary();
  426. return;
  427. /* case 'd':
  428. if(consdebug == nil)
  429. consdebug = rdb;
  430. else
  431. consdebug = nil;
  432. print("consdebug now %#p\n", consdebug);
  433. return;
  434. case 'D':
  435. if(consdebug == nil)
  436. consdebug = rdb;
  437. consdebug();
  438. return;*/
  439. case 'p':
  440. pl = spllo();
  441. procdump();
  442. splx(pl);
  443. return;
  444. case 'q':
  445. scheddump();
  446. return;
  447. case 'k':
  448. killbig("^t ^t k");
  449. return;
  450. case 'r':
  451. exit(0);
  452. return;
  453. }
  454. }
  455. if(keybq != nil)
  456. qproduce(keybq, buf, n);
  457. if(kbd.raw == 0)
  458. putstrn(buf, n);
  459. }
  460. /*
  461. * Called by a uart interrupt for console input.
  462. *
  463. * turn '\r' into '\n' before putting it into the queue.
  464. */
  465. int
  466. kbdcr2nl(Queue *q, int ch)
  467. {
  468. char *next;
  469. ilock(&kbd.lockputc); /* just a mutex */
  470. if(ch == '\r' && !kbd.raw)
  471. ch = '\n';
  472. next = kbd.iw + 1;
  473. if(next >= kbd.ie)
  474. next = kbd.istage;
  475. if(next != kbd.ir){
  476. *kbd.iw = ch;
  477. kbd.iw = next;
  478. }
  479. iunlock(&kbd.lockputc);
  480. return 0;
  481. }
  482. /*
  483. * Put character, possibly a rune, into read queue at interrupt time.
  484. * Called at interrupt time to process a character.
  485. */
  486. int
  487. kbdputc(Queue *q, int ch)
  488. {
  489. int i, n;
  490. char buf[3];
  491. Rune r;
  492. char *next;
  493. if(kbd.ir == nil)
  494. return 0; /* in case we're not inited yet */
  495. ilock(&kbd.lockputc); /* just a mutex */
  496. r = ch;
  497. n = runetochar(buf, &r);
  498. for(i = 0; i < n; i++){
  499. next = kbd.iw + 1;
  500. if(next >= kbd.ie)
  501. next = kbd.istage;
  502. if(next == kbd.ir)
  503. break;
  504. *kbd.iw = buf[i];
  505. kbd.iw = next;
  506. }
  507. iunlock(&kbd.lockputc);
  508. return 0;
  509. }
  510. /*
  511. * we save up input characters till clock time to reduce
  512. * per character interrupt overhead.
  513. */
  514. static void
  515. kbdputcclock(void)
  516. {
  517. char *iw;
  518. /* this amortizes cost of qproduce */
  519. if(kbd.iw != kbd.ir){
  520. iw = kbd.iw;
  521. if(iw < kbd.ir){
  522. echo(kbd.ir, kbd.ie - kbd.ir);
  523. kbd.ir = kbd.istage;
  524. }
  525. if(kbd.ir != iw){
  526. echo(kbd.ir, iw - kbd.ir);
  527. kbd.ir = iw;
  528. }
  529. }
  530. }
  531. enum {
  532. Qdir,
  533. Qbintime,
  534. Qcons,
  535. Qconsctl,
  536. Qcputime,
  537. Qdrivers,
  538. Qkmesg,
  539. Qkprint,
  540. Qhostdomain,
  541. Qhostowner,
  542. Qnull,
  543. Qosversion,
  544. Qpgrpid,
  545. Qpid,
  546. Qppid,
  547. Qrandom,
  548. Qurandom,
  549. Qreboot,
  550. Qswap,
  551. Qsysname,
  552. Qsysstat,
  553. Qtime,
  554. Quser,
  555. Qzero,
  556. Qsyscall,
  557. Qdebug,
  558. };
  559. enum {
  560. VLNUMSIZE = 22,
  561. };
  562. static Dirtab consdir[] = {
  563. {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0555},
  564. {"bintime", {Qbintime}, 24, 0664},
  565. {"cons", {Qcons}, 0, 0660},
  566. {"consctl", {Qconsctl}, 0, 0220},
  567. {"cputime", {Qcputime}, 6 * NUMSIZE, 0444},
  568. {"drivers", {Qdrivers}, 0, 0444},
  569. {"hostdomain", {Qhostdomain}, DOMLEN, 0664},
  570. {"hostowner", {Qhostowner}, 0, 0664},
  571. {"kmesg", {Qkmesg}, 0, 0440},
  572. {"kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL | 0440},
  573. {"null", {Qnull}, 0, 0666},
  574. {"osversion", {Qosversion}, 0, 0444},
  575. {"pgrpid", {Qpgrpid}, NUMSIZE, 0444},
  576. {"pid", {Qpid}, NUMSIZE, 0444},
  577. {"ppid", {Qppid}, NUMSIZE, 0444},
  578. {"random", {Qrandom}, 0, 0444},
  579. {"urandom", {Qurandom}, 0, 0444},
  580. {"reboot", {Qreboot}, 0, 0664},
  581. {"swap", {Qswap}, 0, 0664},
  582. {"sysname", {Qsysname}, 0, 0664},
  583. {"sysstat", {Qsysstat}, 0, 0666},
  584. {"time", {Qtime}, NUMSIZE + 3 * VLNUMSIZE, 0664},
  585. {"user", {Quser}, 0, 0666},
  586. {"zero", {Qzero}, 0, 0444},
  587. {"syscall", {Qsyscall}, 0, 0666},
  588. {"debug", {Qdebug}, 0, 0666},
  589. };
  590. int
  591. readnum(u32 off, char *buf, u32 n, u32 val, int size)
  592. {
  593. char tmp[64];
  594. snprint(tmp, sizeof(tmp), "%*lu", size - 1, val);
  595. tmp[size - 1] = ' ';
  596. if(off >= size)
  597. return 0;
  598. if(off + n > size)
  599. n = size - off;
  600. memmove(buf, tmp + off, n);
  601. return n;
  602. }
  603. i32
  604. readmem(i32 offset, void *buf, i32 n, void *v, i32 size)
  605. {
  606. if(offset < 0 || offset >= size)
  607. return 0;
  608. if(offset + n > size)
  609. n = size - offset;
  610. memmove(buf, v + offset, n);
  611. return n;
  612. }
  613. i32
  614. readstr(i32 offset, char *buf, i32 n, char *str)
  615. {
  616. i32 size;
  617. size = strlen(str);
  618. if(offset >= size)
  619. return 0;
  620. if(offset + n > size)
  621. n = size - offset;
  622. memmove(buf, str + offset, n);
  623. return n;
  624. }
  625. static void
  626. consinit(void)
  627. {
  628. todinit();
  629. /*
  630. * at 115200 baud, the 1024 char buffer takes 56 ms to process,
  631. * processing it every 22 ms should be fine
  632. */
  633. addclock0link(kbdputcclock, 22);
  634. kickkbdq();
  635. }
  636. static Chan *
  637. consattach(char *spec)
  638. {
  639. return devattach('c', spec);
  640. }
  641. static Walkqid *
  642. conswalk(Chan *c, Chan *nc, char **name, int nname)
  643. {
  644. return devwalk(c, nc, name, nname, consdir, nelem(consdir), devgen);
  645. }
  646. static i32
  647. consstat(Chan *c, u8 *dp, i32 n)
  648. {
  649. return devstat(c, dp, n, consdir, nelem(consdir), devgen);
  650. }
  651. static Chan *
  652. consopen(Chan *c, int omode)
  653. {
  654. c->aux = nil;
  655. c = devopen(c, omode, consdir, nelem(consdir), devgen);
  656. switch((u32)c->qid.path){
  657. case Qconsctl:
  658. incref(&kbd.ctl);
  659. break;
  660. case Qkprint:
  661. error(Egreg);
  662. }
  663. return c;
  664. }
  665. static void
  666. consclose(Chan *c)
  667. {
  668. switch((u32)c->qid.path){
  669. /* last close of control file turns off raw */
  670. case Qconsctl:
  671. if(c->flag & COPEN){
  672. if(decref(&kbd.ctl) == 0)
  673. kbd.raw = 0;
  674. }
  675. break;
  676. /* close of kprint allows other opens */
  677. case Qkprint:
  678. error(Egreg);
  679. }
  680. }
  681. static i32
  682. consread(Chan *c, void *buf, i32 n, i64 off)
  683. {
  684. Proc *up = externup();
  685. u64 l;
  686. Mach *mp;
  687. char *b, *bp, ch, *s, *e;
  688. char tmp[512]; /* Qswap is 381 bytes at clu */
  689. int i, k, id, send;
  690. i32 nread;
  691. i64 offset;
  692. if(n <= 0)
  693. return n;
  694. nread = n;
  695. offset = off;
  696. switch((u32)c->qid.path){
  697. case Qdir:
  698. return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
  699. case Qcons:
  700. qlock(&kbd.QLock);
  701. if(waserror()){
  702. qunlock(&kbd.QLock);
  703. nexterror();
  704. }
  705. while(!qcanread(lineq)){
  706. if(qread(keybq, &ch, 1) == 0)
  707. continue;
  708. send = 0;
  709. if(ch == 0){
  710. /* flush output on rawoff -> rawon */
  711. if(kbd.x > 0)
  712. send = !qcanread(keybq);
  713. } else if(kbd.raw){
  714. kbd.line[kbd.x++] = ch;
  715. send = !qcanread(keybq);
  716. } else {
  717. switch(ch){
  718. case '\b':
  719. if(kbd.x > 0)
  720. kbd.x--;
  721. break;
  722. case 0x15: /* ^U */
  723. kbd.x = 0;
  724. break;
  725. case '\n':
  726. case 0x04: /* ^D */
  727. send = 1;
  728. default:
  729. if(ch != 0x04)
  730. kbd.line[kbd.x++] = ch;
  731. break;
  732. }
  733. }
  734. if(send || kbd.x == sizeof kbd.line){
  735. qwrite(lineq, kbd.line, kbd.x);
  736. kbd.x = 0;
  737. }
  738. }
  739. n = qread(lineq, buf, n);
  740. qunlock(&kbd.QLock);
  741. poperror();
  742. return n;
  743. case Qcputime:
  744. k = offset;
  745. if(k >= 6 * NUMSIZE)
  746. return 0;
  747. if(k + n > 6 * NUMSIZE)
  748. n = 6 * NUMSIZE - k;
  749. /* easiest to format in a separate buffer and copy out */
  750. for(i = 0; i < 6 && NUMSIZE * i < k + n; i++){
  751. l = up->time[i];
  752. if(i == TReal)
  753. l = sys->ticks - l;
  754. l = TK2MS(l);
  755. readnum(0, tmp + NUMSIZE * i, NUMSIZE, l, NUMSIZE);
  756. }
  757. memmove(buf, tmp + k, n);
  758. return n;
  759. case Qkmesg:
  760. /*
  761. * This is unlocked to avoid tying up a process
  762. * that's writing to the buffer. kmesg.n never
  763. * gets smaller, so worst case the reader will
  764. * see a slurred buffer.
  765. */
  766. if(off >= kmesg.n)
  767. n = 0;
  768. else {
  769. if(off + n > kmesg.n)
  770. n = kmesg.n - off;
  771. memmove(buf, kmesg.buf + off, n);
  772. }
  773. return n;
  774. case Qkprint:
  775. error(Egreg);
  776. case Qpgrpid:
  777. return readnum(offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
  778. case Qpid:
  779. return readnum(offset, buf, n, up->pid, NUMSIZE);
  780. case Qppid:
  781. return readnum(offset, buf, n, up->parentpid, NUMSIZE);
  782. case Qtime:
  783. return readtime(offset, buf, n);
  784. case Qbintime:
  785. return readbintime(buf, n);
  786. case Qhostowner:
  787. return readstr(offset, buf, n, eve);
  788. case Qhostdomain:
  789. return readstr(offset, buf, n, hostdomain);
  790. case Quser:
  791. return readstr(offset, buf, n, up->user);
  792. case Qnull:
  793. return 0;
  794. case Qsysstat:
  795. n = MACHMAX * (NUMSIZE * 11 + 2 + 1);
  796. b = smalloc(n + 1); /* +1 for NUL */
  797. bp = b;
  798. e = bp + n;
  799. for(id = 0; id < MACHMAX; id++)
  800. if((mp = sys->machptr[id]) != nil && mp->online){
  801. readnum(0, bp, NUMSIZE, mp->machno, NUMSIZE);
  802. bp += NUMSIZE;
  803. readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
  804. bp += NUMSIZE;
  805. readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
  806. bp += NUMSIZE;
  807. readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
  808. bp += NUMSIZE;
  809. readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
  810. bp += NUMSIZE;
  811. readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
  812. bp += NUMSIZE;
  813. readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
  814. bp += NUMSIZE;
  815. readnum(0, bp, NUMSIZE, sys->load, NUMSIZE);
  816. bp += NUMSIZE;
  817. readnum(0, bp, NUMSIZE,
  818. (mp->perf.avg_inidle * 100) / mp->perf.period,
  819. NUMSIZE);
  820. bp += NUMSIZE;
  821. readnum(0, bp, NUMSIZE,
  822. (mp->perf.avg_inintr * 100) / mp->perf.period,
  823. NUMSIZE);
  824. bp += NUMSIZE;
  825. readnum(0, bp, NUMSIZE, 0, NUMSIZE); /* sched # */
  826. bp += NUMSIZE;
  827. bp = strecpy(bp, e, rolename[mp->NIX.nixtype]);
  828. *bp++ = '\n';
  829. }
  830. if(waserror()){
  831. free(b);
  832. nexterror();
  833. }
  834. n = readstr(offset, buf, nread, b);
  835. free(b);
  836. poperror();
  837. return n;
  838. case Qswap:
  839. tmp[0] = 0;
  840. s = seprintpagestats(tmp, tmp + sizeof tmp);
  841. s = seprintphysstats(s, tmp + sizeof tmp);
  842. b = buf;
  843. l = s - tmp;
  844. i = readstr(offset, b, l, tmp);
  845. b += i;
  846. n -= i;
  847. if(offset > l)
  848. offset -= l;
  849. else
  850. offset = 0;
  851. return i + mallocreadsummary(c, b, n, offset);
  852. case Qsysname:
  853. if(sysname == nil)
  854. return 0;
  855. return readstr(offset, buf, n, sysname);
  856. case Qrandom:
  857. return randomread(buf, n);
  858. case Qurandom:
  859. return urandomread(buf, n);
  860. case Qdrivers:
  861. return devtabread(c, buf, n, off);
  862. case Qzero:
  863. memset(buf, 0, n);
  864. return n;
  865. case Qosversion:
  866. snprint(tmp, sizeof tmp, "2000");
  867. n = readstr(offset, buf, n, tmp);
  868. return n;
  869. case Qdebug:
  870. s = seprint(tmp, tmp + sizeof tmp, "locks %lu\n", lockstats.locks);
  871. s = seprint(s, tmp + sizeof tmp, "glare %lu\n", lockstats.glare);
  872. s = seprint(s, tmp + sizeof tmp, "inglare %lu\n", lockstats.inglare);
  873. s = seprint(s, tmp + sizeof tmp, "qlock %lu\n", qlockstats.qlock);
  874. seprint(s, tmp + sizeof tmp, "qlockq %lu\n", qlockstats.qlockq);
  875. return readstr(offset, buf, n, tmp);
  876. break;
  877. case Qsyscall:
  878. snprint(tmp, sizeof tmp, "%s", printallsyscalls ? "on" : "off");
  879. return readstr(offset, buf, n, tmp);
  880. break;
  881. default:
  882. print("consread %#llx\n", c->qid.path);
  883. error(Egreg);
  884. }
  885. return -1; /* never reached */
  886. }
  887. static i32
  888. conswrite(Chan *c, void *va, i32 n, i64 off)
  889. {
  890. Proc *up = externup();
  891. char buf[256], ch;
  892. i32 l, bp;
  893. char *a;
  894. Mach *mp;
  895. int i;
  896. u32 offset;
  897. Cmdbuf *cb;
  898. Cmdtab *ct;
  899. a = va;
  900. offset = off;
  901. extern int printallsyscalls;
  902. switch((u32)c->qid.path){
  903. case Qcons:
  904. /*
  905. * Can't page fault in putstrn, so copy the data locally.
  906. */
  907. l = n;
  908. while(l > 0){
  909. bp = l;
  910. if(bp > sizeof buf)
  911. bp = sizeof buf;
  912. memmove(buf, a, bp);
  913. putstrn0(buf, bp, 1);
  914. a += bp;
  915. l -= bp;
  916. }
  917. break;
  918. case Qconsctl:
  919. if(n >= sizeof(buf))
  920. n = sizeof(buf) - 1;
  921. strncpy(buf, a, n);
  922. buf[n] = 0;
  923. for(a = buf; a;){
  924. if(strncmp(a, "rawon", 5) == 0){
  925. kbd.raw = 1;
  926. /* clumsy hack - wake up reader */
  927. ch = 0;
  928. qwrite(keybq, &ch, 1);
  929. } else if(strncmp(a, "rawoff", 6) == 0)
  930. kbd.raw = 0;
  931. else if(strncmp(a, "ctlpon", 6) == 0)
  932. kbd.ctlpoff = 0;
  933. else if(strncmp(a, "ctlpoff", 7) == 0)
  934. kbd.ctlpoff = 1;
  935. else if(strncmp(a, "sys", 3) == 0){
  936. printallsyscalls = !printallsyscalls;
  937. print("%sracing syscalls\n", printallsyscalls ? "T" : "Not t");
  938. }
  939. if((a = strchr(a, ' ')) != nil)
  940. a++;
  941. }
  942. break;
  943. case Qtime:
  944. if(!iseve())
  945. error(Eperm);
  946. return writetime(a, n);
  947. case Qbintime:
  948. if(!iseve())
  949. error(Eperm);
  950. return writebintime(a, n);
  951. case Qhostowner:
  952. return hostownerwrite(a, n);
  953. case Qhostdomain:
  954. return hostdomainwrite(a, n);
  955. case Quser:
  956. return userwrite(a, n);
  957. case Qnull:
  958. break;
  959. case Qreboot:
  960. if(!iseve())
  961. error(Eperm);
  962. cb = parsecmd(a, n);
  963. if(waserror()){
  964. free(cb);
  965. nexterror();
  966. }
  967. ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
  968. switch(ct->index){
  969. case CMhalt:
  970. reboot(nil, 0, 0);
  971. break;
  972. case CMreboot:
  973. rebootcmd(cb->nf - 1, cb->f + 1);
  974. break;
  975. case CMpanic:
  976. *(volatile u32 *)0 = 0;
  977. panic("/dev/reboot");
  978. }
  979. poperror();
  980. free(cb);
  981. break;
  982. case Qsysstat:
  983. for(i = 0; i < MACHMAX; i++)
  984. if((mp = sys->machptr[i]) != nil && mp->online){
  985. mp = sys->machptr[i];
  986. mp->cs = 0;
  987. mp->intr = 0;
  988. mp->syscall = 0;
  989. mp->pfault = 0;
  990. mp->tlbfault = 0; /* not updated */
  991. mp->tlbpurge = 0; /* # mmuflushtlb */
  992. }
  993. break;
  994. case Qswap:
  995. if(n >= sizeof buf)
  996. error(Egreg);
  997. memmove(buf, va, n); /* so we can NUL-terminate */
  998. buf[n] = 0;
  999. if(!iseve())
  1000. error(Eperm);
  1001. if(buf[0] < '0' || '9' < buf[0])
  1002. error(Ebadarg);
  1003. if(strncmp(buf, "start", 5) == 0){
  1004. print("request to start pager ignored\n");
  1005. break;
  1006. }
  1007. break;
  1008. case Qsysname:
  1009. if(offset != 0)
  1010. error(Ebadarg);
  1011. if(n <= 0 || n >= sizeof buf)
  1012. error(Ebadarg);
  1013. strncpy(buf, a, n);
  1014. buf[n] = 0;
  1015. if(buf[n - 1] == '\n')
  1016. buf[n - 1] = 0;
  1017. kstrdup(&sysname, buf);
  1018. break;
  1019. case Qdebug:
  1020. if(n >= sizeof(buf))
  1021. n = sizeof(buf) - 1;
  1022. strncpy(buf, a, n);
  1023. buf[n] = 0;
  1024. if(n > 0 && buf[n - 1] == '\n')
  1025. buf[n - 1] = 0;
  1026. error(Ebadctl);
  1027. break;
  1028. case Qsyscall:
  1029. if(n >= sizeof(buf))
  1030. n = sizeof(buf) - 1;
  1031. strncpy(buf, a, n);
  1032. buf[n] = 0;
  1033. if(n > 0 && buf[n - 1] == '\n')
  1034. buf[n - 1] = 0;
  1035. // Doing strncmp right is just painful and overkill here.
  1036. if(buf[0] == 'o'){
  1037. if(buf[1] == 'n' && buf[2] == 0){
  1038. printallsyscalls = 1;
  1039. break;
  1040. }
  1041. if(buf[1] == 'f' && buf[2] == 'f' && buf[3] == 0){
  1042. printallsyscalls = 0;
  1043. break;
  1044. }
  1045. }
  1046. error("#c/syscall: can only write on or off");
  1047. break;
  1048. default:
  1049. print("conswrite: %#llx\n", c->qid.path);
  1050. error(Egreg);
  1051. }
  1052. return n;
  1053. }
  1054. Dev consdevtab = {
  1055. .dc = 'c',
  1056. .name = "cons",
  1057. .reset = devreset,
  1058. .init = consinit,
  1059. .shutdown = devshutdown,
  1060. .attach = consattach,
  1061. .walk = conswalk,
  1062. .stat = consstat,
  1063. .open = consopen,
  1064. .create = devcreate,
  1065. .close = consclose,
  1066. .read = consread,
  1067. .bread = devbread,
  1068. .write = conswrite,
  1069. .bwrite = devbwrite,
  1070. .remove = devremove,
  1071. .wstat = devwstat,
  1072. };
  1073. static u32 randn;
  1074. static void
  1075. seedrand(void)
  1076. {
  1077. Proc *up = externup();
  1078. if(!waserror()){
  1079. randomread((void *)&randn, sizeof(randn));
  1080. poperror();
  1081. }
  1082. }
  1083. int
  1084. nrand(int n)
  1085. {
  1086. if(randn == 0)
  1087. seedrand();
  1088. randn = randn * 1103515245 + 12345 + sys->ticks;
  1089. return (randn >> 16) % n;
  1090. }
  1091. int
  1092. rand(void)
  1093. {
  1094. nrand(1);
  1095. return randn;
  1096. }
  1097. static u64 uvorder = 0x0001020304050607ULL;
  1098. static u8 *
  1099. le2i64(i64 *to, u8 *f)
  1100. {
  1101. u8 *t, *o;
  1102. int i;
  1103. t = (u8 *)to;
  1104. o = (u8 *)&uvorder;
  1105. for(i = 0; i < sizeof(i64); i++)
  1106. t[o[i]] = f[i];
  1107. return f + sizeof(i64);
  1108. }
  1109. static u8 *
  1110. i642le(u8 *t, i64 from)
  1111. {
  1112. u8 *f, *o;
  1113. int i;
  1114. f = (u8 *)&from;
  1115. o = (u8 *)&uvorder;
  1116. for(i = 0; i < sizeof(i64); i++)
  1117. t[i] = f[o[i]];
  1118. return t + sizeof(i64);
  1119. }
  1120. static i32 order = 0x00010203;
  1121. static u8 *
  1122. le2long(i32 *to, u8 *f)
  1123. {
  1124. u8 *t, *o;
  1125. int i;
  1126. t = (u8 *)to;
  1127. o = (u8 *)&order;
  1128. for(i = 0; i < sizeof(i32); i++)
  1129. t[o[i]] = f[i];
  1130. return f + sizeof(i32);
  1131. }
  1132. #if 0
  1133. static u8*
  1134. long2le(u8 *t, i32 from)
  1135. {
  1136. u8 *f, *o;
  1137. int i;
  1138. f = (u8*)&from;
  1139. o = (u8*)&order;
  1140. for(i = 0; i < sizeof(i32); i++)
  1141. t[i] = f[o[i]];
  1142. return t+sizeof(i32);
  1143. }
  1144. #endif
  1145. char *Ebadtimectl = "bad time control";
  1146. /*
  1147. * like the old #c/time but with added info. Return
  1148. *
  1149. * secs nanosecs fastticks fasthz
  1150. */
  1151. static int
  1152. readtime(u32 off, char *buf, int n)
  1153. {
  1154. i64 nsec, ticks;
  1155. i32 sec;
  1156. char str[7 * NUMSIZE];
  1157. nsec = todget(&ticks);
  1158. if(fasthz == 0LL)
  1159. fastticks((u64 *)&fasthz);
  1160. sec = nsec / 1000000000ULL;
  1161. snprint(str, sizeof(str), "%*lu %*llu %*llu %*llu ",
  1162. NUMSIZE - 1, sec,
  1163. VLNUMSIZE - 1, nsec,
  1164. VLNUMSIZE - 1, ticks,
  1165. VLNUMSIZE - 1, fasthz);
  1166. return readstr(off, buf, n, str);
  1167. }
  1168. /*
  1169. * set the time in seconds
  1170. */
  1171. static int
  1172. writetime(char *buf, int n)
  1173. {
  1174. char b[13];
  1175. i32 i;
  1176. i64 now;
  1177. if(n >= sizeof(b))
  1178. error(Ebadtimectl);
  1179. strncpy(b, buf, n);
  1180. b[n] = 0;
  1181. i = strtol(b, 0, 0);
  1182. if(i <= 0)
  1183. error(Ebadtimectl);
  1184. now = i * 1000000000LL;
  1185. todset(now, 0, 0);
  1186. return n;
  1187. }
  1188. /*
  1189. * read binary time info. all numbers are little endian.
  1190. * ticks and nsec are syncronized.
  1191. */
  1192. static int
  1193. readbintime(char *buf, int n)
  1194. {
  1195. int i;
  1196. i64 nsec, ticks;
  1197. u8 *b = (u8 *)buf;
  1198. i = 0;
  1199. if(fasthz == 0LL)
  1200. fastticks((u64 *)&fasthz);
  1201. nsec = todget(&ticks);
  1202. if(n >= 3 * sizeof(u64)){
  1203. i642le(b + 2 * sizeof(u64), fasthz);
  1204. i += sizeof(u64);
  1205. }
  1206. if(n >= 2 * sizeof(u64)){
  1207. i642le(b + sizeof(u64), ticks);
  1208. i += sizeof(u64);
  1209. }
  1210. if(n >= 8){
  1211. i642le(b, nsec);
  1212. i += sizeof(i64);
  1213. }
  1214. return i;
  1215. }
  1216. /*
  1217. * set any of the following
  1218. * - time in nsec
  1219. * - nsec trim applied over some seconds
  1220. * - clock frequency
  1221. */
  1222. static int
  1223. writebintime(char *buf, int n)
  1224. {
  1225. u8 *p;
  1226. i64 delta;
  1227. i32 period;
  1228. n--;
  1229. p = (u8 *)buf + 1;
  1230. switch(*buf){
  1231. case 'n':
  1232. if(n < sizeof(i64))
  1233. error(Ebadtimectl);
  1234. le2i64(&delta, p);
  1235. todset(delta, 0, 0);
  1236. break;
  1237. case 'd':
  1238. if(n < sizeof(i64) + sizeof(i32))
  1239. error(Ebadtimectl);
  1240. p = le2i64(&delta, p);
  1241. le2long(&period, p);
  1242. todset(-1, delta, period);
  1243. break;
  1244. case 'f':
  1245. if(n < sizeof(u64))
  1246. error(Ebadtimectl);
  1247. le2i64(&fasthz, p);
  1248. todsetfreq(fasthz);
  1249. break;
  1250. }
  1251. return n;
  1252. }