main.c 13 KB

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