main.c 14 KB

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