main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. #include "u.h"
  2. #include "tos.h"
  3. #include "../port/lib.h"
  4. #include "mem.h"
  5. #include "dat.h"
  6. #include "fns.h"
  7. #include "init.h"
  8. #include <pool.h>
  9. #include "reboot.h"
  10. /* Firmware compatibility */
  11. #define Minfirmrev 326770
  12. #define Minfirmdate "22 Jul 2012"
  13. /*
  14. * Where configuration info is left for the loaded programme.
  15. */
  16. #define BOOTARGS ((char*)CONFADDR)
  17. #define BOOTARGSLEN (MACHADDR-CONFADDR)
  18. #define MAXCONF 64
  19. #define MAXCONFLINE 160
  20. uintptr kseg0 = KZERO;
  21. Mach* machaddr[MAXMACH];
  22. Conf conf;
  23. ulong memsize = 128*1024*1024;
  24. /*
  25. * Option arguments from the command line.
  26. * oargv[0] is the boot file.
  27. */
  28. static int oargc;
  29. static char* oargv[20];
  30. static char oargb[128];
  31. static int oargblen;
  32. static uintptr sp; /* XXX - must go - user stack of init proc */
  33. /* store plan9.ini contents here at least until we stash them in #ec */
  34. static char confname[MAXCONF][KNAMELEN];
  35. static char confval[MAXCONF][MAXCONFLINE];
  36. static int nconf;
  37. typedef struct Atag Atag;
  38. struct Atag {
  39. u32int size; /* size of atag in words, including this header */
  40. u32int tag; /* atag type */
  41. union {
  42. u32int data[1]; /* actually [size-2] */
  43. /* AtagMem */
  44. struct {
  45. u32int size;
  46. u32int base;
  47. } mem;
  48. /* AtagCmdLine */
  49. char cmdline[1]; /* actually [4*(size-2)] */
  50. };
  51. };
  52. enum {
  53. AtagNone = 0x00000000,
  54. AtagCore = 0x54410001,
  55. AtagMem = 0x54410002,
  56. AtagCmdline = 0x54410009,
  57. };
  58. static int
  59. findconf(char *name)
  60. {
  61. int i;
  62. for(i = 0; i < nconf; i++)
  63. if(cistrcmp(confname[i], name) == 0)
  64. return i;
  65. return -1;
  66. }
  67. char*
  68. getconf(char *name)
  69. {
  70. int i;
  71. i = findconf(name);
  72. if(i >= 0)
  73. return confval[i];
  74. return nil;
  75. }
  76. void
  77. addconf(char *name, char *val)
  78. {
  79. int i;
  80. i = findconf(name);
  81. if(i < 0){
  82. if(val == nil || nconf >= MAXCONF)
  83. return;
  84. i = nconf++;
  85. strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
  86. }
  87. strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
  88. }
  89. static void
  90. writeconf(void)
  91. {
  92. char *p, *q;
  93. int n;
  94. p = getconfenv();
  95. if(waserror()) {
  96. free(p);
  97. nexterror();
  98. }
  99. /* convert to name=value\n format */
  100. for(q=p; *q; q++) {
  101. q += strlen(q);
  102. *q = '=';
  103. q += strlen(q);
  104. *q = '\n';
  105. }
  106. n = q - p + 1;
  107. if(n >= BOOTARGSLEN)
  108. error("kernel configuration too large");
  109. memmove(BOOTARGS, p, n);
  110. memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
  111. poperror();
  112. free(p);
  113. }
  114. static void
  115. plan9iniinit(char *s, int cmdline)
  116. {
  117. char *toks[MAXCONF];
  118. int i, c, n;
  119. char *v;
  120. if((c = *s) < ' ' || c >= 0x80)
  121. return;
  122. if(cmdline)
  123. n = tokenize(s, toks, MAXCONF);
  124. else
  125. n = getfields(s, toks, MAXCONF, 1, "\n");
  126. for(i = 0; i < n; i++){
  127. if(toks[i][0] == '#')
  128. continue;
  129. v = strchr(toks[i], '=');
  130. if(v == nil)
  131. continue;
  132. *v++ = '\0';
  133. addconf(toks[i], v);
  134. }
  135. }
  136. static void
  137. ataginit(Atag *a)
  138. {
  139. int n;
  140. if(a->tag != AtagCore){
  141. plan9iniinit((char*)a, 0);
  142. return;
  143. }
  144. while(a->tag != AtagNone){
  145. switch(a->tag){
  146. case AtagMem:
  147. /* use only first bank */
  148. if(conf.mem[0].limit == 0 && a->mem.size != 0){
  149. memsize = a->mem.size;
  150. conf.mem[0].base = a->mem.base;
  151. conf.mem[0].limit = a->mem.base + memsize;
  152. }
  153. break;
  154. case AtagCmdline:
  155. n = (a->size * sizeof(u32int)) - offsetof(Atag, cmdline[0]);
  156. if(a->cmdline + n < BOOTARGS + BOOTARGSLEN)
  157. a->cmdline[n] = 0;
  158. else
  159. BOOTARGS[BOOTARGSLEN-1] = 0;
  160. plan9iniinit(a->cmdline, 1);
  161. break;
  162. }
  163. a = (Atag*)((u32int*)a + a->size);
  164. }
  165. }
  166. void
  167. machinit(void)
  168. {
  169. m->machno = 0;
  170. machaddr[m->machno] = m;
  171. m->ticks = 1;
  172. m->perf.period = 1;
  173. conf.nmach = 1;
  174. active.machs = 1;
  175. active.exiting = 0;
  176. up = nil;
  177. }
  178. static void
  179. optionsinit(char* s)
  180. {
  181. strecpy(oargb, oargb+sizeof(oargb), s);
  182. oargblen = strlen(oargb);
  183. oargc = tokenize(oargb, oargv, nelem(oargv)-1);
  184. oargv[oargc] = nil;
  185. }
  186. void
  187. main(void)
  188. {
  189. extern char edata[], end[];
  190. uint rev;
  191. okay(1);
  192. m = (Mach*)MACHADDR;
  193. memset(edata, 0, end - edata); /* clear bss */
  194. machinit();
  195. mmuinit1();
  196. optionsinit("/boot/boot boot");
  197. quotefmtinstall();
  198. ataginit((Atag*)BOOTARGS);
  199. confinit(); /* figures out amount of memory */
  200. xinit();
  201. uartconsinit();
  202. screeninit();
  203. print("\nPlan 9 from Bell Labs\n");
  204. rev = getfirmware();
  205. print("firmware: rev %d\n", rev);
  206. if(rev < Minfirmrev){
  207. print("Sorry, firmware (start.elf) must be at least rev %d (%s)\n",
  208. Minfirmrev, Minfirmdate);
  209. for(;;)
  210. ;
  211. }
  212. trapinit();
  213. clockinit();
  214. printinit();
  215. timersinit();
  216. if(conf.monitor)
  217. swcursorinit();
  218. cpuidprint();
  219. archreset();
  220. procinit0();
  221. initseg();
  222. links();
  223. chandevreset(); /* most devices are discovered here */
  224. pageinit();
  225. swapinit();
  226. userinit();
  227. schedinit();
  228. assert(0); /* shouldn't have returned */
  229. }
  230. /*
  231. * starting place for first process
  232. */
  233. void
  234. init0(void)
  235. {
  236. int i;
  237. char buf[2*KNAMELEN];
  238. up->nerrlab = 0;
  239. coherence();
  240. spllo();
  241. /*
  242. * These are o.k. because rootinit is null.
  243. * Then early kproc's will have a root and dot.
  244. */
  245. up->slash = namec("#/", Atodir, 0, 0);
  246. pathclose(up->slash->path);
  247. up->slash->path = newpath("/");
  248. up->dot = cclone(up->slash);
  249. chandevinit();
  250. if(!waserror()){
  251. snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
  252. ksetenv("terminal", buf, 0);
  253. ksetenv("cputype", "arm", 0);
  254. if(cpuserver)
  255. ksetenv("service", "cpu", 0);
  256. else
  257. ksetenv("service", "terminal", 0);
  258. snprint(buf, sizeof(buf), "-a %s", getethermac());
  259. ksetenv("etherargs", buf, 0);
  260. /* convert plan9.ini variables to #e and #ec */
  261. for(i = 0; i < nconf; i++) {
  262. ksetenv(confname[i], confval[i], 0);
  263. ksetenv(confname[i], confval[i], 1);
  264. }
  265. poperror();
  266. }
  267. kproc("alarm", alarmkproc, 0);
  268. touser(sp);
  269. assert(0); /* shouldn't have returned */
  270. }
  271. static void
  272. bootargs(uintptr base)
  273. {
  274. int i;
  275. ulong ssize;
  276. char **av, *p;
  277. /*
  278. * Push the boot args onto the stack.
  279. * The initial value of the user stack must be such
  280. * that the total used is larger than the maximum size
  281. * of the argument list checked in syscall.
  282. */
  283. i = oargblen+1;
  284. p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(Tos) - i));
  285. memmove(p, oargb, i);
  286. /*
  287. * Now push the argv pointers.
  288. * The code jumped to by touser in lproc.s expects arguments
  289. * main(char* argv0, ...)
  290. * and calls
  291. * startboot("/boot/boot", &argv0)
  292. * not the usual (int argc, char* argv[])
  293. */
  294. av = (char**)(p - (oargc+1)*sizeof(char*));
  295. ssize = base + BY2PG - PTR2UINT(av);
  296. for(i = 0; i < oargc; i++)
  297. *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
  298. *av = nil;
  299. sp = USTKTOP - ssize;
  300. }
  301. /*
  302. * create the first process
  303. */
  304. void
  305. userinit(void)
  306. {
  307. Proc *p;
  308. Segment *s;
  309. KMap *k;
  310. Page *pg;
  311. /* no processes yet */
  312. up = nil;
  313. p = newproc();
  314. p->pgrp = newpgrp();
  315. p->egrp = smalloc(sizeof(Egrp));
  316. p->egrp->ref = 1;
  317. p->fgrp = dupfgrp(nil);
  318. p->rgrp = newrgrp();
  319. p->procmode = 0640;
  320. kstrdup(&eve, "");
  321. kstrdup(&p->text, "*init*");
  322. kstrdup(&p->user, eve);
  323. /*
  324. * Kernel Stack
  325. */
  326. p->sched.pc = PTR2UINT(init0);
  327. p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
  328. p->sched.sp = STACKALIGN(p->sched.sp);
  329. /*
  330. * User Stack
  331. *
  332. * Technically, newpage can't be called here because it
  333. * should only be called when in a user context as it may
  334. * try to sleep if there are no pages available, but that
  335. * shouldn't be the case here.
  336. */
  337. s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  338. s->flushme++;
  339. p->seg[SSEG] = s;
  340. pg = newpage(1, 0, USTKTOP-BY2PG);
  341. segpage(s, pg);
  342. k = kmap(pg);
  343. bootargs(VA(k));
  344. kunmap(k);
  345. /*
  346. * Text
  347. */
  348. s = newseg(SG_TEXT, UTZERO, 1);
  349. p->seg[TSEG] = s;
  350. pg = newpage(1, 0, UTZERO);
  351. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  352. segpage(s, pg);
  353. k = kmap(s->map[0]->pages[0]);
  354. memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
  355. kunmap(k);
  356. ready(p);
  357. }
  358. void
  359. confinit(void)
  360. {
  361. int i;
  362. ulong kpages;
  363. uintptr pa;
  364. char *p;
  365. if(0 && (p = getconf("service")) != nil){
  366. if(strcmp(p, "cpu") == 0)
  367. cpuserver = 1;
  368. else if(strcmp(p,"terminal") == 0)
  369. cpuserver = 0;
  370. }
  371. if((p = getconf("*maxmem")) != nil){
  372. memsize = strtoul(p, 0, 0) - PHYSDRAM;
  373. if (memsize < 16*MB) /* sanity */
  374. memsize = 16*MB;
  375. }
  376. getramsize(&conf.mem[0]);
  377. if(conf.mem[0].limit == 0){
  378. conf.mem[0].base = PHYSDRAM;
  379. conf.mem[0].limit = PHYSDRAM + memsize;
  380. }else if(p != nil)
  381. conf.mem[0].limit = conf.mem[0].base + memsize;
  382. conf.npage = 0;
  383. pa = PADDR(PGROUND(PTR2UINT(end)));
  384. /*
  385. * we assume that the kernel is at the beginning of one of the
  386. * contiguous chunks of memory and fits therein.
  387. */
  388. for(i=0; i<nelem(conf.mem); i++){
  389. /* take kernel out of allocatable space */
  390. if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
  391. conf.mem[i].base = pa;
  392. conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
  393. conf.npage += conf.mem[i].npage;
  394. }
  395. conf.upages = (conf.npage*80)/100;
  396. conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
  397. /* only one processor */
  398. conf.nmach = 1;
  399. /* set up other configuration parameters */
  400. conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
  401. if(cpuserver)
  402. conf.nproc *= 3;
  403. if(conf.nproc > 2000)
  404. conf.nproc = 2000;
  405. conf.nswap = conf.npage*3;
  406. conf.nswppo = 4096;
  407. conf.nimage = 200;
  408. conf.copymode = 0; /* copy on write */
  409. /*
  410. * Guess how much is taken by the large permanent
  411. * datastructures. Mntcache and Mntrpc are not accounted for
  412. * (probably ~300KB).
  413. */
  414. kpages = conf.npage - conf.upages;
  415. kpages *= BY2PG;
  416. kpages -= conf.upages*sizeof(Page)
  417. + conf.nproc*sizeof(Proc)
  418. + conf.nimage*sizeof(Image)
  419. + conf.nswap
  420. + conf.nswppo*sizeof(Page);
  421. mainmem->maxsize = kpages;
  422. if(!cpuserver)
  423. /*
  424. * give terminals lots of image memory, too; the dynamic
  425. * allocation will balance the load properly, hopefully.
  426. * be careful with 32-bit overflow.
  427. */
  428. imagmem->maxsize = kpages;
  429. }
  430. static void
  431. shutdown(int ispanic)
  432. {
  433. int ms, once;
  434. lock(&active);
  435. if(ispanic)
  436. active.ispanic = ispanic;
  437. else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
  438. active.ispanic = 0;
  439. once = active.machs & (1<<m->machno);
  440. active.machs &= ~(1<<m->machno);
  441. active.exiting = 1;
  442. unlock(&active);
  443. if(once)
  444. iprint("cpu%d: exiting\n", m->machno);
  445. spllo();
  446. for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
  447. delay(TK2MS(2));
  448. if(active.machs == 0 && consactive() == 0)
  449. break;
  450. }
  451. delay(1000);
  452. }
  453. /*
  454. * exit kernel either on a panic or user request
  455. */
  456. void
  457. exit(int code)
  458. {
  459. shutdown(code);
  460. splfhi();
  461. archreboot();
  462. }
  463. /*
  464. * stub for ../omap/devether.c
  465. */
  466. int
  467. isaconfig(char *class, int ctlrno, ISAConf *isa)
  468. {
  469. USED(ctlrno);
  470. USED(isa);
  471. return strcmp(class, "ether") == 0;
  472. }
  473. /*
  474. * the new kernel is already loaded at address `code'
  475. * of size `size' and entry point `entry'.
  476. */
  477. void
  478. reboot(void *entry, void *code, ulong size)
  479. {
  480. void (*f)(ulong, ulong, ulong);
  481. print("starting reboot...");
  482. writeconf();
  483. shutdown(0);
  484. /*
  485. * should be the only processor running now
  486. */
  487. print("reboot entry %#lux code %#lux size %ld\n",
  488. PADDR(entry), PADDR(code), size);
  489. delay(100);
  490. /* turn off buffered serial console */
  491. serialoq = nil;
  492. kprintoq = nil;
  493. screenputs = nil;
  494. /* shutdown devices */
  495. chandevshutdown();
  496. /* stop the clock (and watchdog if any) */
  497. clockshutdown();
  498. splfhi();
  499. intrsoff();
  500. /* setup reboot trampoline function */
  501. f = (void*)REBOOTADDR;
  502. memmove(f, rebootcode, sizeof(rebootcode));
  503. cacheuwbinv();
  504. /* off we go - never to return */
  505. (*f)(PADDR(entry), PADDR(code), size);
  506. iprint("loaded kernel returned!\n");
  507. delay(1000);
  508. archreboot();
  509. }
  510. int
  511. cmpswap(long *addr, long old, long new)
  512. {
  513. return cas32(addr, old, new);
  514. }