main.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  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. uintptr kseg0 = KZERO;
  11. Mach* machaddr[MAXMACH];
  12. /*
  13. * Option arguments from the command line.
  14. * oargv[0] is the boot file.
  15. * Optionsinit() is called from multiboot()
  16. * or some other machine-dependent place
  17. * to set it all up.
  18. */
  19. static int oargc;
  20. static char* oargv[20];
  21. static char oargb[128];
  22. static int oargblen;
  23. static char oenv[4096];
  24. static uintptr sp; /* XXX - must go - user stack of init proc */
  25. int vflag;
  26. char debug[256];
  27. static void
  28. optionsinit(char* s)
  29. {
  30. char *o;
  31. #ifdef USE_FLASH
  32. uintptr va;
  33. char *p;
  34. va = 0xf0000000;
  35. if(mmukmap(va, PHYSFLASH, 1*MiB) != 0){
  36. o = oenv;
  37. for(p = (char*)(va+256*KiB+4); *p != 0; p += strlen(p)+1)
  38. o = strecpy(o, oenv+sizeof(oenv), p)+1;
  39. mmukunmap(va, PHYSFLASH, 1*MiB);
  40. }
  41. #else
  42. strcpy(oenv, "ethaddr=00:50:43:01:c4:9e"); // TODO
  43. #endif
  44. o = strecpy(oargb, oargb+sizeof(oargb), s)+1;
  45. if(getenv("bootargs", o, o - oargb) != nil)
  46. *(o-1) = ' ';
  47. oargblen = strlen(oargb);
  48. oargc = tokenize(oargb, oargv, nelem(oargv)-1);
  49. oargv[oargc] = nil;
  50. }
  51. char*
  52. getenv(char* name, char* buf, int n)
  53. {
  54. char *e, *p, *q;
  55. p = oenv;
  56. while(*p != 0){
  57. if((e = strchr(p, '=')) == nil)
  58. break;
  59. for(q = name; p < e; p++){
  60. if(*p != *q)
  61. break;
  62. q++;
  63. }
  64. if(p == e && *q == 0){
  65. strecpy(buf, buf+n, e+1);
  66. return buf;
  67. }
  68. p += strlen(p)+1;
  69. }
  70. return nil;
  71. }
  72. #include "io.h"
  73. typedef struct Spiregs Spiregs;
  74. struct Spiregs {
  75. ulong ictl; /* interface ctl */
  76. ulong icfg; /* interface config */
  77. ulong out; /* data out */
  78. ulong in; /* data in */
  79. ulong ic; /* interrupt cause */
  80. ulong im; /* interrupt mask */
  81. ulong _pad[2];
  82. ulong dwrcfg; /* direct write config */
  83. ulong dwrhdr; /* direct write header */
  84. };
  85. enum {
  86. /* ictl bits */
  87. Csnact = 1<<0, /* serial memory activated */
  88. /* icfg bits */
  89. Bytelen = 1<<5, /* 2^(this_bit) bytes per transfer */
  90. Dirrdcmd= 1<<10, /* flag: fast read */
  91. };
  92. static void
  93. dumpbytes(uchar *bp, long max)
  94. {
  95. iprint("%#p: ", bp);
  96. for (; max > 0; max--)
  97. iprint("%02.2ux ", *bp++);
  98. iprint("...\n");
  99. }
  100. vlong probeaddr(uintptr);
  101. // linux sez environment is in nand, 128K at offset 0x40000
  102. static void
  103. spiprobe(void)
  104. {
  105. Spiregs *rp = (Spiregs *)AddrSpi;
  106. l2cacheon();
  107. rp->ictl |= Csnact;
  108. coherence();
  109. rp->icfg |= Dirrdcmd | 3<<8; /* fast reads, 4-byte addresses */
  110. rp->icfg &= ~Bytelen; /* one-byte reads */
  111. coherence();
  112. print("spi flash at %#ux: memory reads enabled\n", PHYSSPIFLASH);
  113. #ifdef AMBITIOUS
  114. uchar *p, *ep, *np;
  115. p = (uchar *)PHYSSPIFLASH;
  116. ep = p + FLASHSIZE - 64;
  117. iprint("scan: ");
  118. for (; p < ep - 1; p++) {
  119. iprint("%#p of %,ld bytes...", p, ep - p);
  120. np = memchr(p, 'e', ep - p);
  121. if (np == nil)
  122. break;
  123. p = np;
  124. if (*p == 'e' && memcmp(p, "ethaddr", 7) == 0)
  125. break;
  126. }
  127. dumpbytes(p, 64);
  128. #endif
  129. }
  130. void archconsole(void);
  131. /*
  132. * this low-level printing stuff is ugly,
  133. * but there appears to be no other way to
  134. * print until after #t is populated.
  135. */
  136. #define wave(c) { \
  137. coherence(); \
  138. while ((*(ulong *)(PHYSCONS+4*5) & (1<<5)) == 0) /* (x->lsr&LSRthre)==0? */ \
  139. ; \
  140. *(ulong *)PHYSCONS = (c); \
  141. coherence(); \
  142. }
  143. /*
  144. * entered from l.s with mmu enabled.
  145. *
  146. * we may have to realign the data segment; apparently 5l -H0 -R4096
  147. * does not pad the text segment. on the other hand, we may have been
  148. * loaded by another kernel.
  149. *
  150. * be careful not to touch the data segment until we know it's aligned.
  151. */
  152. void
  153. main(Mach* mach)
  154. {
  155. extern char bdata[], edata[], end[], etext[];
  156. static ulong vfy = 0xcafebabe;
  157. m = mach;
  158. if (vfy != 0xcafebabe)
  159. memmove(bdata, etext, edata - bdata);
  160. if (vfy != 0xcafebabe) {
  161. wave('?');
  162. panic("misaligned data segment");
  163. }
  164. memset(edata, 0, end - edata); /* zero bss */
  165. vfy = 0;
  166. wave('9');
  167. machinit();
  168. archreset();
  169. mmuinit();
  170. optionsinit("/boot/boot boot");
  171. quotefmtinstall();
  172. archconsole();
  173. wave('\n');
  174. confinit();
  175. xinit();
  176. wave('\r');
  177. /*
  178. * Printinit will cause the first malloc call.
  179. * (printinit->qopen->malloc) unless any of the
  180. * above (like clockintr) do an irqenable, which
  181. * will call malloc.
  182. * If the system dies here it's probably due
  183. * to malloc(->xalloc) not being initialised
  184. * correctly, or the data segment is misaligned
  185. * (it's amazing how far you can get with
  186. * things like that completely broken).
  187. *
  188. * (Should be) boilerplate from here on.
  189. */
  190. trapinit();
  191. clockinit();
  192. printinit();
  193. /* only now can we print */
  194. uartkirkwoodconsole();
  195. archconfinit();
  196. cpuidprint();
  197. timersinit();
  198. procinit0();
  199. initseg();
  200. links();
  201. chandevreset();
  202. spiprobe();
  203. pageinit();
  204. swapinit();
  205. userinit();
  206. schedinit();
  207. }
  208. void
  209. cpuidprint(void)
  210. {
  211. char name[64];
  212. cputype2name(name, sizeof name);
  213. print("cpu%d: %lldMHz ARM %s\n", m->machno, m->cpuhz/1000000, name);
  214. }
  215. void
  216. machinit(void)
  217. {
  218. memset(m, 0, sizeof(Mach));
  219. m->machno = 0;
  220. machaddr[m->machno] = m;
  221. m->ticks = 1;
  222. m->perf.period = 1;
  223. conf.nmach = 1;
  224. active.machs = 1;
  225. active.exiting = 0;
  226. up = nil;
  227. }
  228. static void
  229. shutdown(int ispanic)
  230. {
  231. int ms, once;
  232. lock(&active);
  233. if(ispanic)
  234. active.ispanic = ispanic;
  235. else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
  236. active.ispanic = 0;
  237. once = active.machs & (1<<m->machno);
  238. active.machs &= ~(1<<m->machno);
  239. active.exiting = 1;
  240. unlock(&active);
  241. if(once)
  242. iprint("cpu%d: exiting\n", m->machno);
  243. spllo();
  244. for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
  245. delay(TK2MS(2));
  246. if(active.machs == 0 && consactive() == 0)
  247. break;
  248. }
  249. delay(1000);
  250. }
  251. /*
  252. * exit kernel either on a panic or user request
  253. */
  254. void
  255. exit(int code)
  256. {
  257. shutdown(code);
  258. splhi();
  259. archreboot();
  260. }
  261. /*
  262. * the new kernel is already loaded at address `code'
  263. * of size `size' and entry point `entry'.
  264. */
  265. void
  266. reboot(void *entry, void *code, ulong size)
  267. {
  268. void (*f)(ulong, ulong, ulong);
  269. iprint("starting reboot...");
  270. // writeconf();
  271. shutdown(0);
  272. /*
  273. * should be the only processor running now
  274. */
  275. print("shutting down...\n");
  276. delay(200);
  277. splhi();
  278. /* turn off buffered serial console */
  279. serialoq = nil;
  280. /* shutdown devices */
  281. devtabshutdown();
  282. /* setup reboot trampoline function */
  283. f = (void*)REBOOTADDR;
  284. memmove(f, rebootcode, sizeof(rebootcode));
  285. coherence();
  286. dcflushall();
  287. icflushall();
  288. print("rebooting...");
  289. iprint("entry %#lux code %#lux size %ld\n",
  290. PADDR(entry), PADDR(code), size);
  291. delay(100); /* wait for uart to quiesce */
  292. /* off we go - never to return */
  293. coherence();
  294. dcflushall();
  295. icflushall();
  296. (*f)(PADDR(entry), PADDR(code), size);
  297. iprint("loaded kernel returned!\n");
  298. delay(500);
  299. archreboot();
  300. }
  301. /*
  302. * starting place for first process
  303. */
  304. void
  305. init0(void)
  306. {
  307. char buf[2*KNAMELEN];
  308. assert(up != nil);
  309. up->nerrlab = 0;
  310. coherence();
  311. spllo();
  312. /*
  313. * These are o.k. because rootinit is null.
  314. * Then early kproc's will have a root and dot.
  315. */
  316. up->slash = namec("#/", Atodir, 0, 0);
  317. pathclose(up->slash->path);
  318. up->slash->path = newpath("/");
  319. up->dot = cclone(up->slash);
  320. devtabinit();
  321. if(!waserror()){
  322. snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
  323. ksetenv("terminal", buf, 0);
  324. ksetenv("cputype", "arm", 0);
  325. if(cpuserver)
  326. ksetenv("service", "cpu", 0);
  327. else
  328. ksetenv("service", "terminal", 0);
  329. /* sheevaplug configuration */
  330. ksetenv("nvram", "/boot/nvram", 0);
  331. ksetenv("nvroff", "0", 0);
  332. ksetenv("nvrlen", "512", 0);
  333. ksetenv("nobootprompt", "tcp", 0);
  334. poperror();
  335. }
  336. kproc("alarm", alarmkproc, 0);
  337. touser(sp);
  338. }
  339. static void
  340. bootargs(uintptr base)
  341. {
  342. int i;
  343. ulong ssize;
  344. char **av, *p;
  345. /*
  346. * Push the boot args onto the stack.
  347. * The initial value of the user stack must be such
  348. * that the total used is larger than the maximum size
  349. * of the argument list checked in syscall.
  350. */
  351. i = oargblen+1;
  352. p = UINT2PTR(STACKALIGN(base + PGSIZE - sizeof(up->s.args) - i));
  353. memmove(p, oargb, i);
  354. /*
  355. * Now push argc and the argv pointers.
  356. * This isn't strictly correct as the code jumped to by
  357. * touser in init9.s calls startboot (port/initcode.c) which
  358. * expects arguments
  359. * startboot(char *argv0, char **argv)
  360. * not the usual (int argc, char* argv[]), but argv0 is
  361. * unused so it doesn't matter (at the moment...).
  362. */
  363. av = (char**)(p - (oargc+2)*sizeof(char*));
  364. ssize = base + PGSIZE - PTR2UINT(av);
  365. *av++ = (char*)oargc;
  366. for(i = 0; i < oargc; i++)
  367. *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
  368. *av = nil;
  369. /*
  370. * Leave space for the return PC of the
  371. * caller of initcode.
  372. */
  373. sp = USTKTOP - ssize - sizeof(void*);
  374. }
  375. /*
  376. * create the first process
  377. */
  378. void
  379. userinit(void)
  380. {
  381. Proc *p;
  382. Segment *s;
  383. KMap *k;
  384. Page *pg;
  385. /* no processes yet */
  386. up = nil;
  387. p = newproc();
  388. p->pgrp = newpgrp();
  389. p->egrp = smalloc(sizeof(Egrp));
  390. p->egrp->ref = 1;
  391. p->fgrp = dupfgrp(nil);
  392. p->rgrp = newrgrp();
  393. p->procmode = 0640;
  394. kstrdup(&eve, "");
  395. kstrdup(&p->text, "*init*");
  396. kstrdup(&p->user, eve);
  397. /*
  398. * Kernel Stack
  399. */
  400. p->sched.pc = PTR2UINT(init0);
  401. p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
  402. p->sched.sp = STACKALIGN(p->sched.sp);
  403. /*
  404. * User Stack
  405. *
  406. * Technically, newpage can't be called here because it
  407. * should only be called when in a user context as it may
  408. * try to sleep if there are no pages available, but that
  409. * shouldn't be the case here.
  410. */
  411. s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  412. p->seg[SSEG] = s;
  413. pg = newpage(1, 0, USTKTOP-BY2PG);
  414. segpage(s, pg);
  415. k = kmap(pg);
  416. bootargs(VA(k));
  417. kunmap(k);
  418. /*
  419. * Text
  420. */
  421. s = newseg(SG_TEXT, UTZERO, 1);
  422. s->flushme++;
  423. p->seg[TSEG] = s;
  424. pg = newpage(1, 0, UTZERO);
  425. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  426. segpage(s, pg);
  427. k = kmap(s->map[0]->pages[0]);
  428. memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
  429. kunmap(k);
  430. ready(p);
  431. }
  432. Conf conf; /* XXX - must go - gag */
  433. Confmem sheevamem[] = {
  434. /*
  435. * Memory available to Plan 9:
  436. */
  437. { .base = 0x00000000, .limit = 512*1024*1024, },
  438. };
  439. void
  440. confinit(void)
  441. {
  442. int i;
  443. ulong kpages;
  444. uintptr pa;
  445. /*
  446. * Copy the physical memory configuration to Conf.mem.
  447. * The physical memory configuration will be used later
  448. * to check against what the the Pico Array wants.
  449. */
  450. if(nelem(sheevamem) > nelem(conf.mem)){
  451. iprint("memory configuration botch\n");
  452. exit(1);
  453. }
  454. memmove(conf.mem, sheevamem, sizeof(sheevamem));
  455. conf.npage = 0;
  456. pa = PADDR(PGROUND(PTR2UINT(end)));
  457. /*
  458. * we assume that the kernel is at the beginning of one of the
  459. * contiguous chunks of memory and fits therein.
  460. */
  461. for(i=0; i<nelem(conf.mem); i++){
  462. /* take kernel out of allocatable space */
  463. if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
  464. conf.mem[i].base = pa;
  465. conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
  466. conf.npage += conf.mem[i].npage;
  467. }
  468. conf.upages = (conf.npage*90)/100;
  469. conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
  470. /* only one processor */
  471. conf.nmach = 1;
  472. /* set up other configuration parameters */
  473. conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
  474. if(cpuserver)
  475. conf.nproc *= 3;
  476. if(conf.nproc > 2000)
  477. conf.nproc = 2000;
  478. conf.nswap = conf.npage*3;
  479. conf.nswppo = 4096;
  480. conf.nimage = 200;
  481. conf.copymode = 0; /* copy on write */
  482. /*
  483. * Guess how much is taken by the large permanent
  484. * datastructures. Mntcache and Mntrpc are not accounted for
  485. * (probably ~300KB).
  486. */
  487. kpages = conf.npage - conf.upages;
  488. kpages *= BY2PG;
  489. kpages -= conf.upages*sizeof(Page)
  490. + conf.nproc*sizeof(Proc)
  491. + conf.nimage*sizeof(Image)
  492. + conf.nswap
  493. + conf.nswppo*sizeof(Page);
  494. mainmem->maxsize = kpages;
  495. if(!cpuserver)
  496. /*
  497. * give terminals lots of image memory, too; the dynamic
  498. * allocation will balance the load properly, hopefully.
  499. * be careful with 32-bit overflow.
  500. */
  501. imagmem->maxsize = kpages;
  502. }
  503. char*
  504. getconf(char *)
  505. {
  506. return nil;
  507. }
  508. int
  509. cmpswap(long *addr, long old, long new)
  510. {
  511. return cas32(addr, old, new);
  512. }