main.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "ureg.h"
  8. #include "init.h"
  9. #include "pool.h"
  10. #include "reboot.h"
  11. #include "mp.h"
  12. Mach *m;
  13. /*
  14. * Where configuration info is left for the loaded programme.
  15. * This will turn into a structure as more is done by the boot loader
  16. * (e.g. why parse the .ini file twice?).
  17. * There are 3584 bytes available at CONFADDR.
  18. */
  19. #define BOOTLINE ((char*)CONFADDR)
  20. #define BOOTLINELEN 64
  21. #define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
  22. #define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
  23. #define MAXCONF 64
  24. char bootdisk[KNAMELEN];
  25. Conf conf;
  26. char *confname[MAXCONF];
  27. char *confval[MAXCONF];
  28. int nconf;
  29. uchar *sp; /* user stack of init proc */
  30. int delaylink;
  31. int always_idle;
  32. static void
  33. options(void)
  34. {
  35. long i, n;
  36. char *cp, *line[MAXCONF], *p, *q;
  37. /*
  38. * parse configuration args from dos file plan9.ini
  39. */
  40. cp = BOOTARGS; /* where b.com leaves its config */
  41. cp[BOOTARGSLEN-1] = 0;
  42. /*
  43. * Strip out '\r', change '\t' -> ' '.
  44. */
  45. p = cp;
  46. for(q = cp; *q; q++){
  47. if(*q == '\r')
  48. continue;
  49. if(*q == '\t')
  50. *q = ' ';
  51. *p++ = *q;
  52. }
  53. *p = 0;
  54. n = getfields(cp, line, MAXCONF, 1, "\n");
  55. for(i = 0; i < n; i++){
  56. if(*line[i] == '#')
  57. continue;
  58. cp = strchr(line[i], '=');
  59. if(cp == nil)
  60. continue;
  61. *cp++ = '\0';
  62. confname[nconf] = line[i];
  63. confval[nconf] = cp;
  64. nconf++;
  65. }
  66. }
  67. extern void mmuinit0(void);
  68. extern void (*i8237alloc)(void);
  69. void
  70. main(void)
  71. {
  72. mach0init();
  73. options();
  74. ioinit();
  75. i8250console();
  76. quotefmtinstall();
  77. screeninit();
  78. print("\nPlan 9\n");
  79. trapinit0();
  80. mmuinit0();
  81. kbdinit();
  82. i8253init();
  83. cpuidentify();
  84. meminit();
  85. confinit();
  86. archinit();
  87. xinit();
  88. if(i8237alloc != nil)
  89. i8237alloc();
  90. trapinit();
  91. printinit();
  92. cpuidprint();
  93. mmuinit();
  94. if(arch->intrinit) /* launches other processors on an mp */
  95. arch->intrinit();
  96. timersinit();
  97. mathinit();
  98. kbdenable();
  99. if(arch->clockenable)
  100. arch->clockenable();
  101. procinit0();
  102. initseg();
  103. if(delaylink){
  104. bootlinks();
  105. pcimatch(0, 0, 0);
  106. }else
  107. links();
  108. conf.monitor = 1;
  109. chandevreset();
  110. pageinit();
  111. i8253link();
  112. swapinit();
  113. userinit();
  114. active.thunderbirdsarego = 1;
  115. schedinit();
  116. }
  117. void
  118. mach0init(void)
  119. {
  120. conf.nmach = 1;
  121. MACHP(0) = (Mach*)CPU0MACH;
  122. m->pdb = (ulong*)CPU0PDB;
  123. m->gdt = (Segdesc*)CPU0GDT;
  124. machinit();
  125. active.machs = 1;
  126. active.exiting = 0;
  127. }
  128. void
  129. machinit(void)
  130. {
  131. int machno;
  132. ulong *pdb;
  133. Segdesc *gdt;
  134. machno = m->machno;
  135. pdb = m->pdb;
  136. gdt = m->gdt;
  137. memset(m, 0, sizeof(Mach));
  138. m->machno = machno;
  139. m->pdb = pdb;
  140. m->gdt = gdt;
  141. m->perf.period = 1;
  142. /*
  143. * For polled uart output at boot, need
  144. * a default delay constant. 100000 should
  145. * be enough for a while. Cpuidentify will
  146. * calculate the real value later.
  147. */
  148. m->loopconst = 100000;
  149. }
  150. void
  151. init0(void)
  152. {
  153. int i;
  154. char buf[2*KNAMELEN];
  155. up->nerrlab = 0;
  156. spllo();
  157. /*
  158. * These are o.k. because rootinit is null.
  159. * Then early kproc's will have a root and dot.
  160. */
  161. up->slash = namec("#/", Atodir, 0, 0);
  162. pathclose(up->slash->path);
  163. up->slash->path = newpath("/");
  164. up->dot = cclone(up->slash);
  165. chandevinit();
  166. if(!waserror()){
  167. snprint(buf, sizeof(buf), "%s %s", arch->id, conffile);
  168. ksetenv("terminal", buf, 0);
  169. ksetenv("cputype", "386", 0);
  170. if(cpuserver)
  171. ksetenv("service", "cpu", 0);
  172. else
  173. ksetenv("service", "terminal", 0);
  174. for(i = 0; i < nconf; i++){
  175. if(confname[i][0] != '*')
  176. ksetenv(confname[i], confval[i], 0);
  177. ksetenv(confname[i], confval[i], 1);
  178. }
  179. poperror();
  180. }
  181. kproc("alarm", alarmkproc, 0);
  182. touser(sp);
  183. }
  184. void
  185. userinit(void)
  186. {
  187. void *v;
  188. Proc *p;
  189. Segment *s;
  190. Page *pg;
  191. p = newproc();
  192. p->pgrp = newpgrp();
  193. p->egrp = smalloc(sizeof(Egrp));
  194. p->egrp->ref = 1;
  195. p->fgrp = dupfgrp(nil);
  196. p->rgrp = newrgrp();
  197. p->procmode = 0640;
  198. kstrdup(&eve, "");
  199. kstrdup(&p->text, "*init*");
  200. kstrdup(&p->user, eve);
  201. p->fpstate = FPinit;
  202. fpoff();
  203. /*
  204. * Kernel Stack
  205. *
  206. * N.B. make sure there's enough space for syscall to check
  207. * for valid args and
  208. * 4 bytes for gotolabel's return PC
  209. */
  210. p->sched.pc = (ulong)init0;
  211. p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
  212. /*
  213. * User Stack
  214. *
  215. * N.B. cannot call newpage() with clear=1, because pc kmap
  216. * requires up != nil. use tmpmap instead.
  217. */
  218. s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  219. p->seg[SSEG] = s;
  220. pg = newpage(0, 0, USTKTOP-BY2PG);
  221. v = tmpmap(pg);
  222. memset(v, 0, BY2PG);
  223. segpage(s, pg);
  224. bootargs(v);
  225. tmpunmap(v);
  226. /*
  227. * Text
  228. */
  229. s = newseg(SG_TEXT, UTZERO, 1);
  230. s->flushme++;
  231. p->seg[TSEG] = s;
  232. pg = newpage(0, 0, UTZERO);
  233. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  234. segpage(s, pg);
  235. v = tmpmap(pg);
  236. memset(v, 0, BY2PG);
  237. memmove(v, initcode, sizeof initcode);
  238. tmpunmap(v);
  239. ready(p);
  240. }
  241. uchar *
  242. pusharg(char *p)
  243. {
  244. int n;
  245. n = strlen(p)+1;
  246. sp -= n;
  247. memmove(sp, p, n);
  248. return sp;
  249. }
  250. void
  251. bootargs(void *base)
  252. {
  253. int i, ac;
  254. uchar *av[32];
  255. uchar **lsp;
  256. char *cp = BOOTLINE;
  257. char buf[64];
  258. sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD;
  259. ac = 0;
  260. av[ac++] = pusharg("/386/9dos");
  261. /* when boot is changed to only use rc, this code can go away */
  262. cp[BOOTLINELEN-1] = 0;
  263. buf[0] = 0;
  264. if(strncmp(cp, "fd", 2) == 0){
  265. sprint(buf, "local!#f/fd%lddisk", strtol(cp+2, 0, 0));
  266. av[ac++] = pusharg(buf);
  267. } else if(strncmp(cp, "sd", 2) == 0){
  268. sprint(buf, "local!#S/sd%c%c/fs", *(cp+2), *(cp+3));
  269. av[ac++] = pusharg(buf);
  270. } else if(strncmp(cp, "ether", 5) == 0)
  271. av[ac++] = pusharg("-n");
  272. /* 4 byte word align stack */
  273. sp = (uchar*)((ulong)sp & ~3);
  274. /* build argc, argv on stack */
  275. sp -= (ac+1)*sizeof(sp);
  276. lsp = (uchar**)sp;
  277. for(i = 0; i < ac; i++)
  278. *lsp++ = av[i] + ((USTKTOP - BY2PG) - (ulong)base);
  279. *lsp = 0;
  280. sp += (USTKTOP - BY2PG) - (ulong)base - sizeof(ulong);
  281. }
  282. char*
  283. getconf(char *name)
  284. {
  285. int i;
  286. for(i = 0; i < nconf; i++)
  287. if(cistrcmp(confname[i], name) == 0)
  288. return confval[i];
  289. return 0;
  290. }
  291. static void
  292. writeconf(void)
  293. {
  294. char *p, *q;
  295. int n;
  296. p = getconfenv();
  297. if(waserror()) {
  298. free(p);
  299. nexterror();
  300. }
  301. /* convert to name=value\n format */
  302. for(q=p; *q; q++) {
  303. q += strlen(q);
  304. *q = '=';
  305. q += strlen(q);
  306. *q = '\n';
  307. }
  308. n = q - p + 1;
  309. if(n >= BOOTARGSLEN)
  310. error("kernel configuration too large");
  311. memset(BOOTLINE, 0, BOOTLINELEN);
  312. memmove(BOOTARGS, p, n);
  313. poperror();
  314. free(p);
  315. }
  316. void
  317. confinit(void)
  318. {
  319. char *p;
  320. int i, userpcnt;
  321. ulong kpages;
  322. if(p = getconf("*kernelpercent"))
  323. userpcnt = 100 - strtol(p, 0, 0);
  324. else
  325. userpcnt = 0;
  326. conf.npage = 0;
  327. for(i=0; i<nelem(conf.mem); i++)
  328. conf.npage += conf.mem[i].npage;
  329. conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
  330. if(cpuserver)
  331. conf.nproc *= 3;
  332. if(conf.nproc > 2000)
  333. conf.nproc = 2000;
  334. conf.nimage = 200;
  335. conf.nswap = conf.nproc*80;
  336. conf.nswppo = 4096;
  337. if(cpuserver) {
  338. if(userpcnt < 10)
  339. userpcnt = 70;
  340. kpages = conf.npage - (conf.npage*userpcnt)/100;
  341. /*
  342. * Hack for the big boys. Only good while physmem < 4GB.
  343. * Give the kernel fixed max + enough to allocate the
  344. * page pool.
  345. * This is an overestimate as conf.upages < conf.npages.
  346. * The patch of nimage is a band-aid, scanning the whole
  347. * page list in imagereclaim just takes too long.
  348. */
  349. if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
  350. kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
  351. conf.nimage = 2000;
  352. kpages += (conf.nproc*KSTACK)/BY2PG;
  353. }
  354. } else {
  355. if(userpcnt < 10) {
  356. if(conf.npage*BY2PG < 16*MB)
  357. userpcnt = 40;
  358. else
  359. userpcnt = 60;
  360. }
  361. kpages = conf.npage - (conf.npage*userpcnt)/100;
  362. /*
  363. * Make sure terminals with low memory get at least
  364. * 4MB on the first Image chunk allocation.
  365. */
  366. if(conf.npage*BY2PG < 16*MB)
  367. imagmem->minarena = 4*1024*1024;
  368. }
  369. /*
  370. * can't go past the end of virtual memory
  371. * (ulong)-KZERO is 2^32 - KZERO
  372. */
  373. if(kpages > ((ulong)-KZERO)/BY2PG)
  374. kpages = ((ulong)-KZERO)/BY2PG;
  375. conf.upages = conf.npage - kpages;
  376. conf.ialloc = (kpages/2)*BY2PG;
  377. /*
  378. * Guess how much is taken by the large permanent
  379. * datastructures. Mntcache and Mntrpc are not accounted for
  380. * (probably ~300KB).
  381. */
  382. kpages *= BY2PG;
  383. kpages -= conf.upages*sizeof(Page)
  384. + conf.nproc*sizeof(Proc)
  385. + conf.nimage*sizeof(Image)
  386. + conf.nswap
  387. + conf.nswppo*sizeof(Page);
  388. mainmem->maxsize = kpages;
  389. if(!cpuserver){
  390. /*
  391. * give terminals lots of image memory, too; the dynamic
  392. * allocation will balance the load properly, hopefully.
  393. * be careful with 32-bit overflow.
  394. */
  395. imagmem->maxsize = kpages;
  396. }
  397. }
  398. static char* mathmsg[] =
  399. {
  400. nil, /* handled below */
  401. "denormalized operand",
  402. "division by zero",
  403. "numeric overflow",
  404. "numeric underflow",
  405. "precision loss",
  406. };
  407. static void
  408. mathstate(ulong *stsp, ulong *pcp, ulong *ctlp)
  409. {
  410. ulong sts, fpc, ctl;
  411. FPsave *f = &up->fpsave;
  412. if(fpsave == fpx87save){
  413. sts = f->status;
  414. fpc = f->pc;
  415. ctl = f->control;
  416. } else {
  417. sts = f->fsw;
  418. fpc = f->fpuip;
  419. ctl = f->fcw;
  420. }
  421. if(stsp)
  422. *stsp = sts;
  423. if(pcp)
  424. *pcp = fpc;
  425. if(ctlp)
  426. *ctlp = ctl;
  427. }
  428. static void
  429. mathnote(void)
  430. {
  431. int i;
  432. ulong status, pc;
  433. char *msg, note[ERRMAX];
  434. mathstate(&status, &pc, nil);
  435. /*
  436. * Some attention should probably be paid here to the
  437. * exception masks and error summary.
  438. */
  439. msg = "unknown exception";
  440. for(i = 1; i <= 5; i++){
  441. if(!((1<<i) & status))
  442. continue;
  443. msg = mathmsg[i];
  444. break;
  445. }
  446. if(status & 0x01){
  447. if(status & 0x40){
  448. if(status & 0x200)
  449. msg = "stack overflow";
  450. else
  451. msg = "stack underflow";
  452. }else
  453. msg = "invalid operation";
  454. }
  455. snprint(note, sizeof note, "sys: fp: %s fppc=%#lux status=%#lux",
  456. msg, pc, status);
  457. postnote(up, 1, note, NDebug);
  458. }
  459. /*
  460. * sse fp save and restore buffers have to be 16-byte (FPalign) aligned,
  461. * so we shuffle the data up and down as needed or make copies.
  462. */
  463. void
  464. fpssesave(FPsave *fps)
  465. {
  466. FPsave *afps;
  467. afps = (FPsave *)ROUND(((uintptr)fps), FPalign);
  468. fpssesave0(afps);
  469. if (fps != afps) /* not aligned? shuffle down from aligned buffer */
  470. memmove(fps, afps, sizeof(FPssestate) - FPalign);
  471. }
  472. void
  473. fpsserestore(FPsave *fps)
  474. {
  475. FPsave *afps;
  476. afps = (FPsave *)ROUND(((uintptr)fps), FPalign);
  477. if (fps != afps) {
  478. if (m->fpsavalign == nil)
  479. m->fpsavalign = mallocalign(sizeof(FPssestate),
  480. FPalign, 0, 0);
  481. if (m->fpsavalign)
  482. afps = m->fpsavalign;
  483. /* copy or shuffle up to make aligned */
  484. memmove(afps, fps, sizeof(FPssestate) - FPalign);
  485. }
  486. fpsserestore0(afps);
  487. /* if we couldn't make a copy, shuffle regs back down */
  488. if (fps != afps && afps != m->fpsavalign)
  489. memmove(fps, afps, sizeof(FPssestate) - FPalign);
  490. }
  491. /*
  492. * math coprocessor error
  493. */
  494. static void
  495. matherror(Ureg *ur, void*)
  496. {
  497. ulong status, pc;
  498. /*
  499. * a write cycle to port 0xF0 clears the interrupt latch attached
  500. * to the error# line from the 387
  501. */
  502. if(!(m->cpuiddx & 0x01))
  503. outb(0xF0, 0xFF);
  504. /*
  505. * save floating point state to check out error
  506. */
  507. fpenv(&up->fpsave);
  508. mathnote();
  509. if((ur->pc & 0xf0000000) == KZERO){
  510. mathstate(&status, &pc, nil);
  511. panic("fp: status %#lux fppc=%#lux pc=%#lux", status, pc, ur->pc);
  512. }
  513. }
  514. /*
  515. * math coprocessor emulation fault
  516. */
  517. static void
  518. mathemu(Ureg *ureg, void*)
  519. {
  520. ulong status, control;
  521. if(up->fpstate & FPillegal){
  522. /* someone did floating point in a note handler */
  523. postnote(up, 1, "sys: floating point in note handler", NDebug);
  524. return;
  525. }
  526. switch(up->fpstate){
  527. case FPinit:
  528. fpinit();
  529. up->fpstate = FPactive;
  530. break;
  531. case FPinactive:
  532. /*
  533. * Before restoring the state, check for any pending
  534. * exceptions, there's no way to restore the state without
  535. * generating an unmasked exception.
  536. * More attention should probably be paid here to the
  537. * exception masks and error summary.
  538. */
  539. mathstate(&status, nil, &control);
  540. if((status & ~control) & 0x07F){
  541. mathnote();
  542. break;
  543. }
  544. fprestore(&up->fpsave);
  545. up->fpstate = FPactive;
  546. break;
  547. case FPactive:
  548. panic("math emu pid %ld %s pc %#lux",
  549. up->pid, up->text, ureg->pc);
  550. break;
  551. }
  552. }
  553. /*
  554. * math coprocessor segment overrun
  555. */
  556. static void
  557. mathover(Ureg*, void*)
  558. {
  559. pexit("math overrun", 0);
  560. }
  561. void
  562. mathinit(void)
  563. {
  564. trapenable(VectorCERR, matherror, 0, "matherror");
  565. if(X86FAMILY(m->cpuidax) == 3)
  566. intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror");
  567. trapenable(VectorCNA, mathemu, 0, "mathemu");
  568. trapenable(VectorCSO, mathover, 0, "mathover");
  569. }
  570. /*
  571. * set up floating point for a new process
  572. */
  573. void
  574. procsetup(Proc*p)
  575. {
  576. p->fpstate = FPinit;
  577. fpoff();
  578. }
  579. void
  580. procrestore(Proc *p)
  581. {
  582. uvlong t;
  583. if(p->kp)
  584. return;
  585. cycles(&t);
  586. p->pcycles -= t;
  587. }
  588. /*
  589. * Save the mach dependent part of the process state.
  590. */
  591. void
  592. procsave(Proc *p)
  593. {
  594. uvlong t;
  595. cycles(&t);
  596. p->pcycles += t;
  597. if(p->fpstate == FPactive){
  598. if(p->state == Moribund)
  599. fpclear();
  600. else{
  601. /*
  602. * Fpsave() stores without handling pending
  603. * unmasked exeptions. Postnote() can't be called
  604. * here as sleep() already has up->rlock, so
  605. * the handling of pending exceptions is delayed
  606. * until the process runs again and generates an
  607. * emulation fault to activate the FPU.
  608. */
  609. fpsave(&p->fpsave);
  610. }
  611. p->fpstate = FPinactive;
  612. }
  613. /*
  614. * While this processor is in the scheduler, the process could run
  615. * on another processor and exit, returning the page tables to
  616. * the free list where they could be reallocated and overwritten.
  617. * When this processor eventually has to get an entry from the
  618. * trashed page tables it will crash.
  619. *
  620. * If there's only one processor, this can't happen.
  621. * You might think it would be a win not to do this in that case,
  622. * especially on VMware, but it turns out not to matter.
  623. */
  624. mmuflushtlb(PADDR(m->pdb));
  625. }
  626. static void
  627. shutdown(int ispanic)
  628. {
  629. int ms, once;
  630. lock(&active);
  631. if(ispanic)
  632. active.ispanic = ispanic;
  633. else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
  634. active.ispanic = 0;
  635. once = active.machs & (1<<m->machno);
  636. /*
  637. * setting exiting will make hzclock() on each processor call exit(0),
  638. * which calls shutdown(0) and arch->reset(), which on mp systems is
  639. * mpshutdown, which idles non-bootstrap cpus and returns on bootstrap
  640. * processors (to permit a reboot). clearing our bit in machs avoids
  641. * calling exit(0) from hzclock() on this processor.
  642. */
  643. active.machs &= ~(1<<m->machno);
  644. active.exiting = 1;
  645. unlock(&active);
  646. if(once)
  647. iprint("cpu%d: exiting\n", m->machno);
  648. /* wait for any other processors to shutdown */
  649. spllo();
  650. for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
  651. delay(TK2MS(2));
  652. if(active.machs == 0 && consactive() == 0)
  653. break;
  654. }
  655. if(active.ispanic){
  656. if(!cpuserver)
  657. for(;;)
  658. halt();
  659. if(getconf("*debug"))
  660. delay(5*60*1000);
  661. else
  662. delay(10000);
  663. }else
  664. delay(1000);
  665. }
  666. void
  667. reboot(void *entry, void *code, ulong size)
  668. {
  669. void (*f)(ulong, ulong, ulong);
  670. ulong *pdb;
  671. writeconf();
  672. /*
  673. * the boot processor is cpu0. execute this function on it
  674. * so that the new kernel has the same cpu0. this only matters
  675. * because the hardware has a notion of which processor was the
  676. * boot processor and we look at it at start up.
  677. */
  678. if (m->machno != 0) {
  679. procwired(up, 0);
  680. sched();
  681. }
  682. if(conf.nmach > 1) {
  683. /*
  684. * the other cpus could be holding locks that will never get
  685. * released (e.g., in the print path) if we put them into
  686. * reset now, so force them to shutdown gracefully first.
  687. */
  688. lock(&active);
  689. active.rebooting = 1;
  690. unlock(&active);
  691. shutdown(0);
  692. if(arch->resetothers)
  693. arch->resetothers();
  694. delay(20);
  695. }
  696. /*
  697. * should be the only processor running now
  698. */
  699. active.machs = 0;
  700. if (m->machno != 0)
  701. print("on cpu%d (not 0)!\n", m->machno);
  702. print("shutting down...\n");
  703. delay(200);
  704. splhi();
  705. /* turn off buffered serial console */
  706. serialoq = nil;
  707. /* shutdown devices */
  708. chandevshutdown();
  709. arch->introff();
  710. /*
  711. * Modify the machine page table to directly map the low 4MB of memory
  712. * This allows the reboot code to turn off the page mapping
  713. */
  714. pdb = m->pdb;
  715. pdb[PDX(0)] = pdb[PDX(KZERO)];
  716. mmuflushtlb(PADDR(pdb));
  717. /* setup reboot trampoline function */
  718. f = (void*)REBOOTADDR;
  719. memmove(f, rebootcode, sizeof(rebootcode));
  720. print("rebooting...\n");
  721. /* off we go - never to return */
  722. coherence();
  723. (*f)(PADDR(entry), PADDR(code), size);
  724. }
  725. void
  726. exit(int ispanic)
  727. {
  728. shutdown(ispanic);
  729. arch->reset();
  730. }
  731. int
  732. isaconfig(char *class, int ctlrno, ISAConf *isa)
  733. {
  734. char cc[32], *p;
  735. int i;
  736. snprint(cc, sizeof cc, "%s%d", class, ctlrno);
  737. p = getconf(cc);
  738. if(p == nil)
  739. return 0;
  740. isa->type = "";
  741. isa->nopt = tokenize(p, isa->opt, NISAOPT);
  742. for(i = 0; i < isa->nopt; i++){
  743. p = isa->opt[i];
  744. if(cistrncmp(p, "type=", 5) == 0)
  745. isa->type = p + 5;
  746. else if(cistrncmp(p, "port=", 5) == 0)
  747. isa->port = strtoul(p+5, &p, 0);
  748. else if(cistrncmp(p, "irq=", 4) == 0)
  749. isa->irq = strtoul(p+4, &p, 0);
  750. else if(cistrncmp(p, "dma=", 4) == 0)
  751. isa->dma = strtoul(p+4, &p, 0);
  752. else if(cistrncmp(p, "mem=", 4) == 0)
  753. isa->mem = strtoul(p+4, &p, 0);
  754. else if(cistrncmp(p, "size=", 5) == 0)
  755. isa->size = strtoul(p+5, &p, 0);
  756. else if(cistrncmp(p, "freq=", 5) == 0)
  757. isa->freq = strtoul(p+5, &p, 0);
  758. }
  759. return 1;
  760. }
  761. int
  762. cistrcmp(char *a, char *b)
  763. {
  764. int ac, bc;
  765. for(;;){
  766. ac = *a++;
  767. bc = *b++;
  768. if(ac >= 'A' && ac <= 'Z')
  769. ac = 'a' + (ac - 'A');
  770. if(bc >= 'A' && bc <= 'Z')
  771. bc = 'a' + (bc - 'A');
  772. ac -= bc;
  773. if(ac)
  774. return ac;
  775. if(bc == 0)
  776. break;
  777. }
  778. return 0;
  779. }
  780. int
  781. cistrncmp(char *a, char *b, int n)
  782. {
  783. unsigned ac, bc;
  784. while(n > 0){
  785. ac = *a++;
  786. bc = *b++;
  787. n--;
  788. if(ac >= 'A' && ac <= 'Z')
  789. ac = 'a' + (ac - 'A');
  790. if(bc >= 'A' && bc <= 'Z')
  791. bc = 'a' + (bc - 'A');
  792. ac -= bc;
  793. if(ac)
  794. return ac;
  795. if(bc == 0)
  796. break;
  797. }
  798. return 0;
  799. }
  800. /*
  801. * put the processor in the halt state if we've no processes to run.
  802. * an interrupt will get us going again.
  803. */
  804. void
  805. idlehands(void)
  806. {
  807. /*
  808. * we used to halt only on single-core setups. halting in an smp system
  809. * can result in a startup latency for processes that become ready.
  810. * if always_idle is zero, we care more about saving energy
  811. * than reducing this latency.
  812. *
  813. * the performance loss with always_idle == 0 seems to be slight
  814. * and it reduces lock contention (thus system time and real time)
  815. * on many-core systems with large values of NPROC.
  816. */
  817. if(conf.nmach == 1 || always_idle == 0)
  818. halt();
  819. }