main.c 13 KB

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