main.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  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 "init.h"
  8. #include "pool.h"
  9. #include "/sys/src/boot/alphapc/conf.h"
  10. #include "axp.h"
  11. char argbuf[128]; /* arguments passed to initcode and /boot */
  12. Hwrpb *hwrpb;
  13. Bootconf *bootconf;
  14. Conf conf;
  15. FPsave initfp;
  16. /* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
  17. uvlong initfpcr = (1LL<62)|(1LL<61)|(1LL<60)|(2LL<<58)|(1LL<48);
  18. char bootargs[BOOTARGSLEN];
  19. char *confname[MAXCONF];
  20. char *confval[MAXCONF];
  21. int nconf;
  22. static void
  23. options(void)
  24. {
  25. long i, n;
  26. char *cp, *line[MAXCONF], *p, *q;
  27. cp = bootargs;
  28. strncpy(cp, bootconf->bootargs, BOOTARGSLEN);
  29. cp[BOOTARGSLEN-1] = 0;
  30. /* can't print in this routine, see below in main() */
  31. /*
  32. * Strip out '\r', change '\t' -> ' '.
  33. */
  34. p = cp;
  35. for(q = cp; *q; q++){
  36. if(*q == '\r')
  37. continue;
  38. if(*q == '\t')
  39. *q = ' ';
  40. *p++ = *q;
  41. }
  42. *p = 0;
  43. n = getfields(cp, line, MAXCONF, 1, "\n");
  44. for(i = 0; i < n; i++){
  45. if(*line[i] == '#')
  46. continue;
  47. cp = strchr(line[i], '=');
  48. if(cp == nil)
  49. continue;
  50. *cp++ = '\0';
  51. confname[nconf] = line[i];
  52. confval[nconf] = cp;
  53. nconf++;
  54. }
  55. }
  56. /* debugging only */
  57. static void
  58. dumpopts(void)
  59. {
  60. int i;
  61. print("dumpopts: found /alpha/conf options at 0x%lux\n",
  62. bootconf->bootargs);
  63. for(i = 0; i < nconf; i++)
  64. print("dumpopts: read %s=%s\n", confname[i], confval[i]);
  65. }
  66. void
  67. main(void)
  68. {
  69. hwrpb = (Hwrpb*)0x10000000;
  70. hwrpb = (Hwrpb*)(KZERO|hwrpb->phys);
  71. arginit();
  72. machinit();
  73. options();
  74. ioinit();
  75. clockinit();
  76. confinit();
  77. archinit();
  78. xinit();
  79. memholes();
  80. mmuinit();
  81. if(arch->coreinit)
  82. arch->coreinit();
  83. trapinit();
  84. screeninit();
  85. printinit();
  86. /* it's now safe to print */
  87. /* dumpopts(); /* DEBUG */
  88. kbdinit();
  89. i8250console();
  90. quotefmtinstall();
  91. print("\nPlan 9\n");
  92. cpuidprint();
  93. if(arch->corehello)
  94. arch->corehello();
  95. procinit0();
  96. initseg();
  97. timersinit();
  98. links();
  99. chandevreset();
  100. pageinit();
  101. swapinit();
  102. savefpregs(&initfp);
  103. initfp.fpstatus = 0x68028000;
  104. userinit();
  105. schedinit();
  106. }
  107. /* cpu->state bits */
  108. enum {
  109. Cpubootinprog = 1, /* boot in progress */
  110. Cpucanrestart = 2, /* restart possible */
  111. Cpuavail = 4, /* processor available */
  112. Cpuexists = 8, /* processor present */
  113. Cpuuserhalted = 0x10, /* user halted */
  114. Cpuctxtokay = 0x20, /* context valid */
  115. Cpupalokay = 0x40, /* PALcode valid */
  116. Cpupalmemokay = 0x80, /* PALcode memory valid */
  117. Cpupalloaded = 0x100, /* PALcode loaded */
  118. Cpuhaltmask = 0xff0000, /* halt request mask */
  119. Cpuhaltdflt = 0,
  120. Cpuhaltsaveexit = 0x10000,
  121. Cpuhaltcoldboot = 0x20000,
  122. Cpuhaltwarmboot = 0x30000,
  123. Cpuhaltstayhalted = 0x40000,
  124. Cpumustbezero = 0xffffffffff000000, /* 24:63 -- must be zero */
  125. };
  126. /*
  127. * initialize a processor's mach structure. each processor does this
  128. * for itself.
  129. */
  130. void
  131. machinit(void)
  132. {
  133. int n;
  134. Hwcpu *cpu;
  135. icflush();
  136. n = m->machno;
  137. memset(m, 0, sizeof(Mach));
  138. m->machno = n;
  139. active.exiting = 0;
  140. active.machs = 1;
  141. cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff + n*hwrpb->cpulen);
  142. cpu->state &= ~Cpubootinprog;
  143. if (0)
  144. cpu->state |= Cpuhaltstayhalted;
  145. }
  146. void
  147. init0(void)
  148. {
  149. int i;
  150. char buf[2*KNAMELEN];
  151. up->nerrlab = 0;
  152. spllo();
  153. /*
  154. * These are o.k. because rootinit is null.
  155. * Then early kproc's will have a root and dot.
  156. */
  157. up->slash = namec("#/", Atodir, 0, 0);
  158. pathclose(up->slash->path);
  159. up->slash->path = newpath("/");
  160. up->dot = cclone(up->slash);
  161. chandevinit();
  162. if(!waserror()){
  163. snprint(buf, sizeof(buf), "alpha %s alphapc", conffile);
  164. ksetenv("terminal", buf, 0);
  165. ksetenv("cputype", "alpha", 0);
  166. if(cpuserver)
  167. ksetenv("service", "cpu", 0);
  168. else
  169. ksetenv("service", "terminal", 0);
  170. for(i = 0; i < nconf; i++)
  171. if(confname[i]){
  172. if(confname[i][0] != '*')
  173. ksetenv(confname[i], confval[i], 0);
  174. ksetenv(confname[i], confval[i], 1);
  175. }
  176. poperror();
  177. }
  178. kproc("alarm", alarmkproc, 0);
  179. touser((uchar*)(USTKTOP - sizeof(argbuf)));
  180. }
  181. void
  182. userinit(void)
  183. {
  184. Proc *p;
  185. Segment *s;
  186. KMap *k;
  187. char **av;
  188. Page *pg;
  189. p = newproc();
  190. p->pgrp = newpgrp();
  191. p->egrp = smalloc(sizeof(Egrp));
  192. p->egrp->ref = 1;
  193. p->fgrp = dupfgrp(nil);
  194. p->rgrp = newrgrp();
  195. p->procmode = 0640;
  196. kstrdup(&eve, "");
  197. kstrdup(&p->text, "*init*");
  198. kstrdup(&p->user, eve);
  199. procsetup(p);
  200. /*
  201. * Kernel Stack
  202. */
  203. p->sched.pc = (ulong)init0;
  204. p->sched.sp = (ulong)p->kstack+KSTACK-MAXSYSARG*BY2WD;
  205. /*
  206. * User Stack, pass input arguments to boot process
  207. */
  208. s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  209. p->seg[SSEG] = s;
  210. pg = newpage(1, 0, USTKTOP-BY2PG);
  211. segpage(s, pg);
  212. k = kmap(pg);
  213. for(av = (char**)argbuf; *av; av++)
  214. *av += (USTKTOP - sizeof(argbuf)) - (ulong)argbuf;
  215. memmove((uchar*)VA(k) + BY2PG - sizeof(argbuf), argbuf, sizeof argbuf);
  216. kunmap(k);
  217. /*
  218. * Text
  219. */
  220. s = newseg(SG_TEXT, UTZERO, 1);
  221. s->flushme++;
  222. p->seg[TSEG] = s;
  223. pg = newpage(1, 0, UTZERO);
  224. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  225. segpage(s, pg);
  226. k = kmap(s->map[0]->pages[0]);
  227. memmove((uchar*)VA(k), initcode, sizeof initcode);
  228. kunmap(k);
  229. ready(p);
  230. }
  231. void
  232. procsetup(Proc *p)
  233. {
  234. p->fpstate = FPinit;
  235. fpenab(0);
  236. }
  237. void
  238. procsave(Proc *p)
  239. {
  240. if(p->fpstate == FPactive){
  241. if(p->state == Moribund)
  242. fpenab(0);
  243. else
  244. savefpregs(&up->fpsave);
  245. p->fpstate = FPinactive;
  246. }
  247. /*
  248. * Switch to the prototype page tables for this processor.
  249. * While this processor is in the scheduler, the process could run
  250. * on another processor and exit, returning the page tables to
  251. * the free list where they could be reallocated and overwritten.
  252. * When this processor eventually has to get an entry from the
  253. * trashed page tables it will crash.
  254. */
  255. mmupark();
  256. }
  257. void
  258. setupboot(int halt)
  259. {
  260. int n = 0; // cpu id of primary cpu, not just m->machno
  261. Hwcpu *cpu = (Hwcpu*)((ulong)hwrpb + hwrpb->cpuoff + n*hwrpb->cpulen);
  262. cpu->state &= ~(Cpucanrestart | Cpuhaltmask);
  263. cpu->state |= (halt? Cpuhaltstayhalted: Cpuhaltwarmboot);
  264. }
  265. /* from ../pc */
  266. static void
  267. shutdown(int ispanic)
  268. {
  269. int ms, once;
  270. lock(&active);
  271. if(ispanic)
  272. active.ispanic = ispanic;
  273. else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
  274. active.ispanic = 0;
  275. once = active.machs & (1<<m->machno);
  276. active.machs &= ~(1<<m->machno);
  277. active.exiting = 1;
  278. unlock(&active);
  279. if(once)
  280. print("cpu%d: exiting\n", m->machno);
  281. spllo();
  282. for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
  283. delay(TK2MS(2));
  284. if(active.machs == 0 && consactive() == 0)
  285. break;
  286. }
  287. if(active.ispanic && m->machno == 0) {
  288. if(cpuserver)
  289. delay(10000);
  290. else
  291. for (;;)
  292. continue;
  293. } else
  294. delay(1000);
  295. }
  296. /* from ../pc: */
  297. void
  298. reboot(void *entry, void *code, ulong size)
  299. {
  300. // writeconf(); // pass kernel environment to next kernel
  301. shutdown(0);
  302. /*
  303. * should be the only processor running now
  304. */
  305. print("shutting down...\n");
  306. delay(200);
  307. splhi();
  308. /* turn off buffered serial console */
  309. serialoq = nil;
  310. /* shutdown devices */
  311. chandevshutdown();
  312. #ifdef FUTURE
  313. {
  314. ulong *pdb;
  315. /*
  316. * Modify the machine page table to directly map the low 4MB of memory
  317. * This allows the reboot code to turn off the page mapping
  318. */
  319. pdb = m->pdb;
  320. pdb[PDX(0)] = pdb[PDX(KZERO)];
  321. mmuflushtlb(PADDR(pdb));
  322. }
  323. /* setup reboot trampoline function */
  324. {
  325. void (*f)(ulong, ulong, ulong) = (void*)REBOOTADDR;
  326. memmove(f, rebootcode, sizeof(rebootcode));
  327. #else
  328. USED(entry, code, size);
  329. #endif
  330. print("rebooting...\n");
  331. #ifdef FUTURE
  332. /* off we go - never to return */
  333. (*f)(PADDR(entry), PADDR(code), size);
  334. }
  335. #endif
  336. setupboot(0); // reboot, don't halt
  337. exit(0);
  338. }
  339. void
  340. exit(int ispanic)
  341. {
  342. canlock(&active);
  343. active.machs &= ~(1<<m->machno);
  344. active.exiting = 1;
  345. unlock(&active);
  346. spllo();
  347. print("cpu %d exiting\n", m->machno);
  348. do
  349. delay(100);
  350. while(consactive());
  351. splhi();
  352. delay(1000); /* give serial fifo time to finish flushing */
  353. if (getconf("*debug") != nil) {
  354. USED(ispanic);
  355. delay(60*1000); /* give us time to read the screen */
  356. }
  357. if(arch->coredetach)
  358. arch->coredetach();
  359. setupboot(1); // set up to halt
  360. for (; ; )
  361. firmware();
  362. // on PC is just:
  363. if (0) {
  364. shutdown(ispanic);
  365. // arch->reset();
  366. }
  367. }
  368. void
  369. confinit(void)
  370. {
  371. ulong ktop, kpages;
  372. Bank *b, *eb;
  373. extern void _main(void);
  374. int userpcnt;
  375. char *p;
  376. if(p = getconf("*kernelpercent"))
  377. userpcnt = 100 - strtol(p, 0, 0);
  378. else
  379. userpcnt = 0;
  380. /*
  381. * The console firmware divides memory into 1 or more banks.
  382. * FInd the bank with the kernel in it.
  383. */
  384. b = bootconf->bank;
  385. eb = b+bootconf->nbank;
  386. ktop = PGROUND((ulong)end);
  387. ktop = PADDR(ktop);
  388. while(b < eb) {
  389. if(b->min < ktop && ktop < b->max)
  390. break;
  391. b++;
  392. }
  393. if(b == eb)
  394. panic("confinit");
  395. /*
  396. * Split the bank of memory into 2 banks to fool the allocator into
  397. * allocating low memory pages from bank 0 for any peripherals
  398. * which only have a 24bit address counter.
  399. */
  400. conf.mem[0].npage = (8*1024*1024)/BY2PG;
  401. conf.mem[0].base = 0;
  402. conf.mem[1].npage = (b->max-8*1024*1024)/BY2PG;
  403. conf.mem[1].base = 8*1024*1024;
  404. conf.npage = conf.mem[0].npage+conf.mem[1].npage;
  405. conf.upages = (conf.npage*70)/100;
  406. conf.mem[0].npage -= ktop/BY2PG;
  407. conf.mem[0].base += ktop;
  408. conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
  409. /*
  410. * Fix up the bank we found to be the remnant, below the kernel.
  411. * This, and the other banks, will be passed to xhole() later.
  412. * BUG: conf.upages needs to be adjusted, but how? In practice,
  413. * we only have 1 bank, and the remnant is small.
  414. */
  415. b->max = (uvlong)_main & ~(BY2PG-1);
  416. conf.nmach = 1;
  417. conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
  418. if(cpuserver)
  419. conf.nproc *= 3;
  420. if(conf.nproc > 2000)
  421. conf.nproc = 2000;
  422. conf.nimage = 200;
  423. conf.nswap = conf.nproc*80;
  424. conf.nswppo = 4096;
  425. conf.copymode = 0; /* copy on write */
  426. if(cpuserver) {
  427. if(userpcnt < 10)
  428. userpcnt = 70;
  429. kpages = conf.npage - (conf.npage*userpcnt)/100;
  430. /*
  431. * Hack for the big boys. Only good while physmem < 4GB.
  432. * Give the kernel a max. of 16MB + enough to allocate the
  433. * page pool.
  434. * This is an overestimate as conf.upages < conf.npages.
  435. * The patch of nimage is a band-aid, scanning the whole
  436. * page list in imagereclaim just takes too long.
  437. */
  438. if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
  439. kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
  440. conf.nimage = 2000;
  441. kpages += (conf.nproc*KSTACK)/BY2PG;
  442. }
  443. } else {
  444. if(userpcnt < 10) {
  445. if(conf.npage*BY2PG < 16*MB)
  446. userpcnt = 40;
  447. else
  448. userpcnt = 60;
  449. }
  450. kpages = conf.npage - (conf.npage*userpcnt)/100;
  451. /*
  452. * Make sure terminals with low memory get at least
  453. * 4MB on the first Image chunk allocation.
  454. */
  455. if(conf.npage*BY2PG < 16*MB)
  456. imagmem->minarena = 4*1024*1024;
  457. }
  458. conf.upages = conf.npage - kpages;
  459. conf.ialloc = (kpages/2)*BY2PG;
  460. /*
  461. * Guess how much is taken by the large permanent
  462. * datastructures. Mntcache and Mntrpc are not accounted for
  463. * (probably ~300KB).
  464. */
  465. kpages *= BY2PG;
  466. kpages -= conf.upages*sizeof(Page)
  467. + conf.nproc*sizeof(Proc)
  468. + conf.nimage*sizeof(Image)
  469. + conf.nswap
  470. + conf.nswppo*sizeof(Page);
  471. mainmem->maxsize = kpages;
  472. if(!cpuserver){
  473. /*
  474. * give terminals lots of image memory, too; the dynamic
  475. * allocation will balance the load properly, hopefully.
  476. * be careful with 32-bit overflow.
  477. */
  478. imagmem->maxsize = kpages;
  479. }
  480. // conf.monitor = 1; /* BUG */
  481. }
  482. void
  483. memholes(void)
  484. {
  485. Bank *b, *eb;
  486. b = bootconf->bank;
  487. eb = b+bootconf->nbank;
  488. while(b < eb) {
  489. if(b->min < (1LL<<32) && b->max < (1LL<<32))
  490. xhole(b->min, b->max-b->min);
  491. b++;
  492. }
  493. }
  494. char *sp;
  495. char *
  496. pusharg(char *p)
  497. {
  498. int n;
  499. n = strlen(p)+1;
  500. sp -= n;
  501. memmove(sp, p, n);
  502. return sp;
  503. }
  504. void
  505. arginit(void)
  506. {
  507. char **av;
  508. av = (char**)argbuf;
  509. sp = argbuf + sizeof(argbuf);
  510. *av++ = pusharg("boot");
  511. *av = 0;
  512. }
  513. char *
  514. getconf(char *name)
  515. {
  516. int n;
  517. for(n = 0; n < nconf; n++)
  518. if(cistrcmp(confname[n], name) == 0) {
  519. return confval[n];
  520. }
  521. return 0;
  522. }
  523. int
  524. isaconfig(char *class, int ctlrno, ISAConf *isa)
  525. {
  526. char cc[32], *p;
  527. int i, n;
  528. snprint(cc, sizeof cc, "%s%d", class, ctlrno);
  529. for(n = 0; n < nconf; n++){
  530. if(cistrcmp(confname[n], cc) != 0)
  531. continue;
  532. isa->nopt = tokenize(confval[n], isa->opt, NISAOPT);
  533. for(i = 0; i < isa->nopt; i++){
  534. p = isa->opt[i];
  535. if(cistrncmp(p, "type=", 5) == 0)
  536. isa->type = p + 5;
  537. else if(cistrncmp(p, "port=", 5) == 0)
  538. isa->port = strtoul(p+5, &p, 0);
  539. else if(cistrncmp(p, "irq=", 4) == 0)
  540. isa->irq = strtoul(p+4, &p, 0);
  541. else if(cistrncmp(p, "dma=", 4) == 0)
  542. isa->dma = strtoul(p+4, &p, 0);
  543. else if(cistrncmp(p, "mem=", 4) == 0)
  544. isa->mem = strtoul(p+4, &p, 0);
  545. else if(cistrncmp(p, "size=", 5) == 0)
  546. isa->size = strtoul(p+5, &p, 0);
  547. else if(cistrncmp(p, "freq=", 5) == 0)
  548. isa->freq = strtoul(p+5, &p, 0);
  549. }
  550. return 1;
  551. }
  552. return 0;
  553. }
  554. int
  555. cistrcmp(char *a, char *b)
  556. {
  557. int ac, bc;
  558. for(;;){
  559. ac = *a++;
  560. bc = *b++;
  561. if(ac >= 'A' && ac <= 'Z')
  562. ac = 'a' + (ac - 'A');
  563. if(bc >= 'A' && bc <= 'Z')
  564. bc = 'a' + (bc - 'A');
  565. ac -= bc;
  566. if(ac)
  567. return ac;
  568. if(bc == 0)
  569. break;
  570. }
  571. return 0;
  572. }
  573. int
  574. cistrncmp(char *a, char *b, int n)
  575. {
  576. unsigned ac, bc;
  577. while(n > 0){
  578. ac = *a++;
  579. bc = *b++;
  580. n--;
  581. if(ac >= 'A' && ac <= 'Z')
  582. ac = 'a' + (ac - 'A');
  583. if(bc >= 'A' && bc <= 'Z')
  584. bc = 'a' + (bc - 'A');
  585. ac -= bc;
  586. if(ac)
  587. return ac;
  588. if(bc == 0)
  589. break;
  590. }
  591. return 0;
  592. }
  593. int
  594. getcfields(char* lp, char** fields, int n, char* sep)
  595. {
  596. int i;
  597. for(i = 0; lp && *lp && i < n; i++){
  598. while(*lp && strchr(sep, *lp) != 0)
  599. *lp++ = 0;
  600. if(*lp == 0)
  601. break;
  602. fields[i] = lp;
  603. while(*lp && strchr(sep, *lp) == 0){
  604. if(*lp == '\\' && *(lp+1) == '\n')
  605. *lp++ = ' ';
  606. lp++;
  607. }
  608. }
  609. return i;
  610. }