main.c 13 KB

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