main.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  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 "reboot.h"
  10. /*
  11. * Where configuration info is left for the loaded programme.
  12. * This will turn into a structure as more is done by the boot loader
  13. * (e.g. why parse the .ini file twice?).
  14. * There are 3584 bytes available at CONFADDR.
  15. */
  16. #define BOOTARGS ((char*)CONFADDR)
  17. #define BOOTARGSLEN (16*KiB) /* limit in devenv.c */
  18. #define MAXCONF 64
  19. #define MAXCONFLINE 160
  20. enum {
  21. Minmem = 256*MB, /* conservative default */
  22. };
  23. #define isascii(c) ((uchar)(c) > 0 && (uchar)(c) < 0177)
  24. uintptr kseg0 = KZERO;
  25. Mach* machaddr[MAXMACH];
  26. /*
  27. * Option arguments from the command line.
  28. * oargv[0] is the boot file.
  29. * Optionsinit() is called from multiboot()
  30. * or some other machine-dependent place
  31. * to set it all up.
  32. */
  33. static int oargc;
  34. static char* oargv[20];
  35. static char oargb[128];
  36. static int oargblen;
  37. static char oenv[4096];
  38. static uintptr sp; /* XXX - must go - user stack of init proc */
  39. int vflag;
  40. int normalprint;
  41. char debug[256];
  42. /* store plan9.ini contents here at least until we stash them in #ec */
  43. static char confname[MAXCONF][KNAMELEN];
  44. static char confval[MAXCONF][MAXCONFLINE];
  45. static int nconf;
  46. static int
  47. findconf(char *name)
  48. {
  49. int i;
  50. for(i = 0; i < nconf; i++)
  51. if(cistrcmp(confname[i], name) == 0)
  52. return i;
  53. return -1;
  54. }
  55. char*
  56. getconf(char *name)
  57. {
  58. int i;
  59. i = findconf(name);
  60. if(i >= 0)
  61. return confval[i];
  62. return nil;
  63. }
  64. void
  65. addconf(char *name, char *val)
  66. {
  67. int i;
  68. i = findconf(name);
  69. if(i < 0){
  70. if(val == nil || nconf >= MAXCONF)
  71. return;
  72. i = nconf++;
  73. strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
  74. }
  75. // confval[i] = val;
  76. strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
  77. }
  78. static void
  79. writeconf(void)
  80. {
  81. char *p, *q;
  82. int n;
  83. p = getconfenv();
  84. if(waserror()) {
  85. free(p);
  86. nexterror();
  87. }
  88. /* convert to name=value\n format */
  89. for(q=p; *q; q++) {
  90. q += strlen(q);
  91. *q = '=';
  92. q += strlen(q);
  93. *q = '\n';
  94. }
  95. n = q - p + 1;
  96. if(n >= BOOTARGSLEN)
  97. error("kernel configuration too large");
  98. memmove(BOOTARGS, p, n);
  99. memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
  100. poperror();
  101. free(p);
  102. }
  103. /*
  104. * assumes that we have loaded our /cfg/pxe/mac file at 0x1000 with
  105. * tftp in u-boot. no longer uses malloc, so can be called early.
  106. */
  107. static void
  108. plan9iniinit(void)
  109. {
  110. char *k, *v, *next;
  111. k = (char *)CONFADDR;
  112. if(!isascii(*k))
  113. return;
  114. for(; k && *k != '\0'; k = next) {
  115. if (!isascii(*k)) /* sanity check */
  116. break;
  117. next = strchr(k, '\n');
  118. if (next)
  119. *next++ = '\0';
  120. if (*k == '\0' || *k == '\n' || *k == '#')
  121. continue;
  122. v = strchr(k, '=');
  123. if(v == nil)
  124. continue; /* mal-formed line */
  125. *v++ = '\0';
  126. addconf(k, v);
  127. }
  128. }
  129. static void
  130. optionsinit(char* s)
  131. {
  132. char *o;
  133. strcpy(oenv, "");
  134. o = strecpy(oargb, oargb+sizeof(oargb), s)+1;
  135. if(getenv("bootargs", o, o - oargb) != nil)
  136. *(o-1) = ' ';
  137. oargblen = strlen(oargb);
  138. oargc = tokenize(oargb, oargv, nelem(oargv)-1);
  139. oargv[oargc] = nil;
  140. }
  141. char*
  142. getenv(char* name, char* buf, int n)
  143. {
  144. char *e, *p, *q;
  145. p = oenv;
  146. while(*p != 0){
  147. if((e = strchr(p, '=')) == nil)
  148. break;
  149. for(q = name; p < e; p++){
  150. if(*p != *q)
  151. break;
  152. q++;
  153. }
  154. if(p == e && *q == 0){
  155. strecpy(buf, buf+n, e+1);
  156. return buf;
  157. }
  158. p += strlen(p)+1;
  159. }
  160. return nil;
  161. }
  162. void
  163. main(void)
  164. {
  165. // int i;
  166. extern char bdata[], edata[], end[], etext[];
  167. static ulong vfy = 0xcafebabe;
  168. /* l.s has already printed "Plan 9 from Be" */
  169. // m = mach; /* now done in l.s */
  170. /* realign data seg; apparently -H0 -R4096 does not pad the text seg */
  171. if (vfy != 0xcafebabe) {
  172. // wave('<'); wave('-');
  173. memmove(bdata, etext, edata - bdata);
  174. }
  175. /*
  176. * once data segment is in place, always zero bss since we may
  177. * have been loaded by another Plan 9 kernel.
  178. */
  179. memset(edata, 0, end - edata); /* zero BSS */
  180. cacheuwbinv();
  181. l2cacheuwbinv();
  182. if (vfy != 0xcafebabe)
  183. panic("data segment misaligned");
  184. vfy = 0;
  185. wave('l');
  186. machinit();
  187. mmuinit();
  188. optionsinit("/boot/boot boot");
  189. quotefmtinstall();
  190. /* want plan9.ini to be able to affect memory sizing in confinit */
  191. plan9iniinit(); /* before we step on plan9.ini in low memory */
  192. trapinit(); /* so confinit can probe memory to size it */
  193. confinit(); /* figures out amount of memory */
  194. /* xinit prints (if it can), so finish up the banner here. */
  195. delay(500);
  196. iprint("l Labs\n\n");
  197. delay(500);
  198. xinit();
  199. mainmem->flags |= POOL_ANTAGONISM /* | POOL_PARANOIA */ ;
  200. /*
  201. * Printinit will cause the first malloc call.
  202. * (printinit->qopen->malloc) unless any of the
  203. * above (like clockinit) do an irqenable, which
  204. * will call malloc.
  205. * If the system dies here it's probably due
  206. * to malloc(->xalloc) not being initialised
  207. * correctly, or the data segment is misaligned
  208. * (it's amazing how far you can get with
  209. * things like that completely broken).
  210. *
  211. * (Should be) boilerplate from here on.
  212. */
  213. archreset(); /* configure clock signals */
  214. clockinit(); /* start clocks */
  215. timersinit();
  216. watchdoginit();
  217. delay(250); /* let uart catch up */
  218. printinit();
  219. kbdenable();
  220. cpuidprint();
  221. // chkmissing();
  222. procinit0();
  223. initseg();
  224. dmainit();
  225. links();
  226. conf.monitor = 1;
  227. screeninit();
  228. chandevreset(); /* most devices are discovered here */
  229. // i8250console(); /* too early; see init0 */
  230. pageinit();
  231. swapinit();
  232. userinit();
  233. schedinit();
  234. }
  235. void
  236. machinit(void)
  237. {
  238. if (m == 0)
  239. wave('?');
  240. // memset(m, 0, sizeof(Mach)); /* done by l.s, now contains stack */
  241. m->machno = 0;
  242. machaddr[m->machno] = m;
  243. m->ticks = 1;
  244. m->perf.period = 1;
  245. conf.nmach = 1;
  246. active.machs = 1;
  247. active.exiting = 0;
  248. up = nil;
  249. }
  250. static void
  251. shutdown(int ispanic)
  252. {
  253. int ms, once;
  254. lock(&active);
  255. if(ispanic)
  256. active.ispanic = ispanic;
  257. else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
  258. active.ispanic = 0;
  259. once = active.machs & (1<<m->machno);
  260. active.machs &= ~(1<<m->machno);
  261. active.exiting = 1;
  262. unlock(&active);
  263. if(once)
  264. iprint("cpu%d: exiting\n", m->machno);
  265. spllo();
  266. for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
  267. delay(TK2MS(2));
  268. if(active.machs == 0 && consactive() == 0)
  269. break;
  270. }
  271. delay(1000);
  272. }
  273. /*
  274. * exit kernel either on a panic or user request
  275. */
  276. void
  277. exit(int code)
  278. {
  279. shutdown(code);
  280. splhi();
  281. archreboot();
  282. }
  283. int
  284. isaconfig(char *class, int ctlrno, ISAConf *isa)
  285. {
  286. char cc[32], *p;
  287. int i;
  288. snprint(cc, sizeof cc, "%s%d", class, ctlrno);
  289. p = getconf(cc);
  290. if(p == nil)
  291. return 0;
  292. isa->type = "";
  293. isa->nopt = tokenize(p, isa->opt, NISAOPT);
  294. for(i = 0; i < isa->nopt; i++){
  295. p = isa->opt[i];
  296. if(cistrncmp(p, "type=", 5) == 0)
  297. isa->type = p + 5;
  298. else if(cistrncmp(p, "port=", 5) == 0)
  299. isa->port = strtoul(p+5, &p, 0);
  300. else if(cistrncmp(p, "irq=", 4) == 0)
  301. isa->irq = strtoul(p+4, &p, 0);
  302. else if(cistrncmp(p, "dma=", 4) == 0)
  303. isa->dma = strtoul(p+4, &p, 0);
  304. else if(cistrncmp(p, "mem=", 4) == 0)
  305. isa->mem = strtoul(p+4, &p, 0);
  306. else if(cistrncmp(p, "size=", 5) == 0)
  307. isa->size = strtoul(p+5, &p, 0);
  308. else if(cistrncmp(p, "freq=", 5) == 0)
  309. isa->freq = strtoul(p+5, &p, 0);
  310. }
  311. return 1;
  312. }
  313. /*
  314. * the new kernel is already loaded at address `code'
  315. * of size `size' and entry point `entry'.
  316. */
  317. void
  318. reboot(void *entry, void *code, ulong size)
  319. {
  320. void (*f)(ulong, ulong, ulong);
  321. print("starting reboot...");
  322. writeconf();
  323. shutdown(0);
  324. /*
  325. * should be the only processor running now
  326. */
  327. print("reboot entry %#lux code %#lux size %ld\n",
  328. PADDR(entry), PADDR(code), size);
  329. delay(100);
  330. /* turn off buffered serial console */
  331. serialoq = nil;
  332. kprintoq = nil;
  333. screenputs = nil;
  334. /* shutdown devices */
  335. chandevshutdown();
  336. /* call off the dog */
  337. clockshutdown();
  338. splhi();
  339. intrsoff();
  340. /* setup reboot trampoline function */
  341. f = (void*)REBOOTADDR;
  342. memmove(f, rebootcode, sizeof(rebootcode));
  343. cacheuwbinv();
  344. l2cacheuwbinv();
  345. /* off we go - never to return */
  346. (*f)(PADDR(entry), PADDR(code), size);
  347. iprint("loaded kernel returned!\n");
  348. delay(1000);
  349. archreboot();
  350. }
  351. /*
  352. * starting place for first process
  353. */
  354. void
  355. init0(void)
  356. {
  357. int i;
  358. char buf[2*KNAMELEN];
  359. up->nerrlab = 0;
  360. coherence();
  361. spllo();
  362. /*
  363. * These are o.k. because rootinit is null.
  364. * Then early kproc's will have a root and dot.
  365. */
  366. up->slash = namec("#/", Atodir, 0, 0);
  367. pathclose(up->slash->path);
  368. up->slash->path = newpath("/");
  369. up->dot = cclone(up->slash);
  370. dmatest(); /* needs `up' set, so can't do it earlier */
  371. chandevinit();
  372. i8250console(); /* might be redundant, but harmless */
  373. if(kbdq == nil)
  374. panic("init0: nil kbdq");
  375. if(serialoq == nil)
  376. panic("init0: nil serialoq");
  377. normalprint = 1;
  378. if(!waserror()){
  379. snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
  380. ksetenv("terminal", buf, 0);
  381. ksetenv("cputype", "arm", 0);
  382. if(cpuserver)
  383. ksetenv("service", "cpu", 0);
  384. else
  385. ksetenv("service", "terminal", 0);
  386. /* convert plan9.ini variables to #e and #ec */
  387. for(i = 0; i < nconf; i++) {
  388. ksetenv(confname[i], confval[i], 0);
  389. ksetenv(confname[i], confval[i], 1);
  390. }
  391. poperror();
  392. }
  393. kproc("alarm", alarmkproc, 0);
  394. touser(sp);
  395. }
  396. static void
  397. bootargs(uintptr base)
  398. {
  399. int i;
  400. ulong ssize;
  401. char **av, *p;
  402. /*
  403. * Push the boot args onto the stack.
  404. * The initial value of the user stack must be such
  405. * that the total used is larger than the maximum size
  406. * of the argument list checked in syscall.
  407. */
  408. i = oargblen+1;
  409. p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(up->s.args) - i));
  410. memmove(p, oargb, i);
  411. /*
  412. * Now push argc and the argv pointers.
  413. * This isn't strictly correct as the code jumped to by
  414. * touser in init9.s calls startboot (port/initcode.c) which
  415. * expects arguments
  416. * startboot(char *argv0, char **argv)
  417. * not the usual (int argc, char* argv[]), but argv0 is
  418. * unused so it doesn't matter (at the moment...).
  419. */
  420. av = (char**)(p - (oargc+2)*sizeof(char*));
  421. ssize = base + BY2PG - PTR2UINT(av);
  422. *av++ = (char*)oargc;
  423. for(i = 0; i < oargc; i++)
  424. *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
  425. *av = nil;
  426. /*
  427. * Leave space for the return PC of the
  428. * caller of initcode.
  429. */
  430. sp = USTKTOP - ssize - sizeof(void*);
  431. }
  432. /*
  433. * create the first process
  434. */
  435. void
  436. userinit(void)
  437. {
  438. Proc *p;
  439. Segment *s;
  440. KMap *k;
  441. Page *pg;
  442. /* no processes yet */
  443. up = nil;
  444. p = newproc();
  445. p->pgrp = newpgrp();
  446. p->egrp = smalloc(sizeof(Egrp));
  447. p->egrp->ref = 1;
  448. p->fgrp = dupfgrp(nil);
  449. p->rgrp = newrgrp();
  450. p->procmode = 0640;
  451. kstrdup(&eve, "");
  452. kstrdup(&p->text, "*init*");
  453. kstrdup(&p->user, eve);
  454. /*
  455. * Kernel Stack
  456. */
  457. p->sched.pc = PTR2UINT(init0);
  458. p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
  459. p->sched.sp = STACKALIGN(p->sched.sp);
  460. /*
  461. * User Stack
  462. *
  463. * Technically, newpage can't be called here because it
  464. * should only be called when in a user context as it may
  465. * try to sleep if there are no pages available, but that
  466. * shouldn't be the case here.
  467. */
  468. s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  469. s->flushme++;
  470. p->seg[SSEG] = s;
  471. pg = newpage(1, 0, USTKTOP-BY2PG);
  472. segpage(s, pg);
  473. k = kmap(pg);
  474. bootargs(VA(k));
  475. kunmap(k);
  476. /*
  477. * Text
  478. */
  479. s = newseg(SG_TEXT, UTZERO, 1);
  480. p->seg[TSEG] = s;
  481. pg = newpage(1, 0, UTZERO);
  482. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  483. segpage(s, pg);
  484. k = kmap(s->map[0]->pages[0]);
  485. memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
  486. kunmap(k);
  487. ready(p);
  488. }
  489. Conf conf; /* XXX - must go - gag */
  490. Confmem omapmem[nelem(conf.mem)] = {
  491. /*
  492. * Memory available to Plan 9:
  493. */
  494. { .base = PHYSDRAM, .limit = PHYSDRAM + Minmem, },
  495. };
  496. ulong memsize = Minmem;
  497. static int
  498. gotmem(uintptr sz)
  499. {
  500. uintptr addr;
  501. addr = PHYSDRAM + sz - BY2WD;
  502. mmuidmap(addr, 1);
  503. if (probeaddr(addr) >= 0) {
  504. memsize = sz;
  505. return 0;
  506. }
  507. return -1;
  508. }
  509. void
  510. confinit(void)
  511. {
  512. int i;
  513. ulong kpages;
  514. uintptr pa;
  515. char *p;
  516. /*
  517. * Copy the physical memory configuration to Conf.mem.
  518. */
  519. if(nelem(omapmem) > nelem(conf.mem)){
  520. iprint("memory configuration botch\n");
  521. exit(1);
  522. }
  523. if((p = getconf("*maxmem")) != nil) {
  524. memsize = strtoul(p, 0, 0) - PHYSDRAM;
  525. if (memsize < 16*MB) /* sanity */
  526. memsize = 16*MB;
  527. }
  528. /*
  529. * see if all that memory exists; if not, find out how much does.
  530. * trapinit must have been called first.
  531. */
  532. if (gotmem(memsize) < 0 && gotmem(256*MB) < 0 && gotmem(128*MB) < 0) {
  533. iprint("can't find any memory, assuming %dMB\n", Minmem / MB);
  534. memsize = Minmem;
  535. }
  536. omapmem[0].limit = PHYSDRAM + memsize;
  537. memmove(conf.mem, omapmem, sizeof(omapmem));
  538. conf.npage = 0;
  539. pa = PADDR(PGROUND(PTR2UINT(end)));
  540. /*
  541. * we assume that the kernel is at the beginning of one of the
  542. * contiguous chunks of memory and fits therein.
  543. */
  544. for(i=0; i<nelem(conf.mem); i++){
  545. /* take kernel out of allocatable space */
  546. if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
  547. conf.mem[i].base = pa;
  548. conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
  549. conf.npage += conf.mem[i].npage;
  550. }
  551. conf.upages = (conf.npage*80)/100;
  552. conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
  553. /* only one processor */
  554. conf.nmach = 1;
  555. /* set up other configuration parameters */
  556. conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
  557. if(cpuserver)
  558. conf.nproc *= 3;
  559. if(conf.nproc > 2000)
  560. conf.nproc = 2000;
  561. conf.nswap = conf.npage*3;
  562. conf.nswppo = 4096;
  563. conf.nimage = 200;
  564. conf.copymode = 0; /* copy on write */
  565. /*
  566. * Guess how much is taken by the large permanent
  567. * datastructures. Mntcache and Mntrpc are not accounted for
  568. * (probably ~300KB).
  569. */
  570. kpages = conf.npage - conf.upages;
  571. kpages *= BY2PG;
  572. kpages -= conf.upages*sizeof(Page)
  573. + conf.nproc*sizeof(Proc)
  574. + conf.nimage*sizeof(Image)
  575. + conf.nswap
  576. + conf.nswppo*sizeof(Page);
  577. mainmem->maxsize = kpages;
  578. if(!cpuserver)
  579. /*
  580. * give terminals lots of image memory, too; the dynamic
  581. * allocation will balance the load properly, hopefully.
  582. * be careful with 32-bit overflow.
  583. */
  584. imagmem->maxsize = kpages;
  585. // archconfinit();
  586. }
  587. int
  588. cmpswap(long *addr, long old, long new)
  589. {
  590. return cas32(addr, old, new);
  591. }