main.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  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 "../ip/ip.h"
  10. #include <tos.h>
  11. #include <bootexec.h>
  12. #include "reboot.h"
  13. typedef struct mipsexec Mipsexec;
  14. /*
  15. * Option arguments from the command line.
  16. * oargv[0] is the boot file.
  17. */
  18. static int oargc;
  19. static char* oargv[20];
  20. static char oargb[128];
  21. static int oargblen;
  22. static uintptr sp; /* XXX - must go - user stack of init proc */
  23. /*
  24. * software tlb simulation
  25. */
  26. static Softtlb stlb[MAXMACH][STLBSIZE];
  27. Conf conf;
  28. FPsave initfp;
  29. int normalprint;
  30. char *
  31. getconf(char *)
  32. {
  33. return nil; /* stub */
  34. }
  35. static void
  36. optionsinit(char* s)
  37. {
  38. strecpy(oargb, oargb+sizeof(oargb), s);
  39. oargblen = strlen(oargb);
  40. oargc = tokenize(oargb, oargv, nelem(oargv)-1);
  41. oargv[oargc] = nil;
  42. }
  43. static void
  44. prcpuid(void)
  45. {
  46. ulong cpuid, cfg1;
  47. char *cpu;
  48. cpuid = prid();
  49. if (((cpuid>>16) & MASK(8)) == 0) /* vendor */
  50. cpu = "old mips";
  51. else if (((cpuid>>16) & MASK(8)) == 1)
  52. switch ((cpuid>>8) & MASK(8)) { /* processor */
  53. case 0x93:
  54. cpu = "mips 24k";
  55. break;
  56. case 0x96:
  57. cpu = "mips 24ke";
  58. break;
  59. default:
  60. cpu = "mips";
  61. break;
  62. }
  63. else
  64. cpu = "other mips";
  65. delay(20);
  66. print("cpu%d: %ldMHz %s %se v%ld.%ld rev %ld, ",
  67. m->machno, m->hz / Mhz, cpu, getconfig() & (1<<15)? "b": "l",
  68. (cpuid>>5) & MASK(3), (cpuid>>2) & MASK(3), cpuid & MASK(2));
  69. delay(200);
  70. cfg1 = getconfig1();
  71. print("%s fpu\n", (cfg1 & 1? "has": "no"));
  72. print("cpu%d: %ld tlb entries, using %dK pages\n", m->machno,
  73. ((cfg1>>25) & MASK(6)) + 1, BY2PG/1024);
  74. delay(50);
  75. print("cpu%d: l1 i cache: %d sets 4 ways 32 bytes/line\n", m->machno,
  76. 64 << ((cfg1>>22) & MASK(3)));
  77. delay(50);
  78. print("cpu%d: l1 d cache: %d sets 4 ways 32 bytes/line\n", m->machno,
  79. 64 << ((cfg1>>13) & MASK(3)));
  80. delay(500);
  81. if (0)
  82. print("cpu%d: cycle counter res = %ld\n",
  83. m->machno, gethwreg3());
  84. }
  85. static void
  86. fmtinit(void)
  87. {
  88. printinit();
  89. quotefmtinstall();
  90. /* ipreset installs these when chandevreset runs */
  91. fmtinstall('i', eipfmt);
  92. fmtinstall('I', eipfmt);
  93. fmtinstall('E', eipfmt);
  94. fmtinstall('V', eipfmt);
  95. fmtinstall('M', eipfmt);
  96. }
  97. static int
  98. ckpagemask(ulong mask, ulong size)
  99. {
  100. int s;
  101. ulong pm;
  102. s = splhi();
  103. setpagemask(mask);
  104. pm = getpagemask();
  105. splx(s);
  106. if(pm != mask){
  107. iprint("page size %ldK not supported on this cpu; "
  108. "mask %#lux read back as %#lux\n", size/1024, mask, pm);
  109. return -1;
  110. }
  111. return 0;
  112. }
  113. /* called from rebootcmd() */
  114. int
  115. parsemipsboothdr(Chan *c, ulong magic, Execvals *evp)
  116. {
  117. long extra;
  118. Mipsexec me;
  119. /*
  120. * BOOT_MAGIC is sometimes defined like this:
  121. * #define BOOT_MAGIC (0x160<<16) || magic == ((0x160<<16)|3)
  122. * so we can only use it in a fairly stylized manner.
  123. */
  124. if(magic == BOOT_MAGIC) {
  125. c->offset = 0; /* back up */
  126. readn(c, &me, sizeof me);
  127. /* if binary is -H1, read an extra long */
  128. if (l2be(me.amagic) == 0407 && me.nscns == 0)
  129. readn(c, &extra, sizeof extra);
  130. evp->entry = l2be(me.mentry);
  131. evp->textsize = l2be(me.tsize);
  132. evp->datasize = l2be(me.dsize);
  133. return 0;
  134. } else
  135. return -1;
  136. }
  137. void
  138. main(void)
  139. {
  140. stopwdog(); /* tranquilise the dog */
  141. optionsinit("/boot/boot boot");
  142. confinit();
  143. savefpregs(&initfp);
  144. machinit(); /* calls clockinit */
  145. active.exiting = 0;
  146. active.machs = 1;
  147. kmapinit();
  148. xinit();
  149. timersinit();
  150. fmtinit();
  151. vecinit();
  152. normalprint = 1;
  153. print("\nPlan 9\n");
  154. prcpuid();
  155. if (PTECACHABILITY == PTENONCOHERWT)
  156. print("caches configured as write-through\n");
  157. if (0)
  158. xsummary();
  159. ckpagemask(PGSZ, BY2PG);
  160. tlbinit();
  161. machwire();
  162. pageinit();
  163. procinit0();
  164. initseg();
  165. links();
  166. chandevreset();
  167. swapinit();
  168. userinit();
  169. sicwdog();
  170. parseboothdr = parsemipsboothdr;
  171. schedinit();
  172. panic("schedinit returned");
  173. }
  174. /*
  175. * initialize a processor's mach structure. each processor does this
  176. * for itself.
  177. */
  178. void
  179. machinit(void)
  180. {
  181. /* Ensure CU1 is off */
  182. clrfpintr();
  183. m->stb = &stlb[m->machno][0];
  184. clockinit();
  185. }
  186. /*
  187. * setup MIPS trap vectors
  188. */
  189. void
  190. vecinit(void)
  191. {
  192. memmove((ulong*)UTLBMISS, (ulong*)vector0, 0x80);
  193. memmove((ulong*)XEXCEPTION, (ulong*)vector0, 0x80);
  194. memmove((ulong*)CACHETRAP, (ulong*)vector100, 0x80);
  195. memmove((ulong*)EXCEPTION, (ulong*)vector180, 0x80);
  196. memmove((ulong*)(KSEG0+0x200), (ulong*)vector180, 0x80);
  197. icflush((ulong*)UTLBMISS, 4*1024);
  198. setstatus(getstatus() & ~BEV);
  199. }
  200. void
  201. init0(void)
  202. {
  203. char buf[128];
  204. up->nerrlab = 0;
  205. spllo();
  206. /*
  207. * These are o.k. because rootinit is null.
  208. * Then early kproc's will have a root and dot.
  209. */
  210. up->slash = namec("#/", Atodir, 0, 0);
  211. pathclose(up->slash->path);
  212. up->slash->path = newpath("/");
  213. up->dot = cclone(up->slash);
  214. chandevinit();
  215. if(!waserror()){
  216. ksetenv("cputype", "mips", 0);
  217. snprint(buf, sizeof buf, "mips %s rb450g", conffile);
  218. ksetenv("terminal", buf, 0);
  219. if(cpuserver)
  220. ksetenv("service", "cpu", 0);
  221. else
  222. ksetenv("service", "terminal", 0);
  223. /*
  224. * we don't have a good way to read our cfg file in
  225. * RouterBOOT, so set the configuration here.
  226. */
  227. ksetenv("nobootprompt", "tcp", 0);
  228. ksetenv("nvram", "/boot/nvram", 0);
  229. poperror();
  230. }
  231. kproc("alarm", alarmkproc, 0);
  232. i8250console();
  233. touser(sp);
  234. }
  235. FPsave initfp;
  236. static void
  237. bootargs(uintptr base)
  238. {
  239. int i;
  240. ulong ssize;
  241. char **av, *p;
  242. /*
  243. * Push the boot args onto the stack.
  244. * The initial value of the user stack must be such
  245. * that the total used is larger than the maximum size
  246. * of the argument list checked in syscall.
  247. */
  248. i = oargblen+1;
  249. p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(Tos) - i));
  250. memmove(p, oargb, i);
  251. /*
  252. * Now push the argv pointers.
  253. * The code jumped to by touser in lproc.s expects arguments
  254. * main(char* argv0, ...)
  255. * and calls
  256. * startboot("/boot/boot", &argv0)
  257. * not the usual (int argc, char* argv[])
  258. */
  259. av = (char**)(p - (oargc+1)*sizeof(char*));
  260. ssize = base + BY2PG - PTR2UINT(av);
  261. for(i = 0; i < oargc; i++)
  262. *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
  263. *av = nil;
  264. sp = USTKTOP - ssize;
  265. }
  266. void
  267. userinit(void)
  268. {
  269. Proc *p;
  270. KMap *k;
  271. Page *pg;
  272. Segment *s;
  273. p = newproc();
  274. p->pgrp = newpgrp();
  275. p->egrp = smalloc(sizeof(Egrp));
  276. p->egrp->ref = 1;
  277. p->fgrp = dupfgrp(nil);
  278. p->rgrp = newrgrp();
  279. p->procmode = 0640;
  280. kstrdup(&eve, "");
  281. kstrdup(&p->text, "*init*");
  282. kstrdup(&p->user, eve);
  283. p->fpstate = FPinit;
  284. p->fpsave.fpstatus = initfp.fpstatus;
  285. /*
  286. * Kernel Stack
  287. */
  288. p->sched.pc = (ulong)init0;
  289. p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
  290. p->sched.sp = STACKALIGN(p->sched.sp);
  291. /*
  292. * User Stack
  293. *
  294. * Technically, newpage can't be called here because it
  295. * should only be called when in a user context as it may
  296. * try to sleep if there are no pages available, but that
  297. * shouldn't be the case here.
  298. */
  299. s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  300. p->seg[SSEG] = s;
  301. pg = newpage(1, 0, USTKTOP-BY2PG);
  302. segpage(s, pg);
  303. k = kmap(pg);
  304. bootargs(VA(k));
  305. kunmap(k);
  306. /*
  307. * Text
  308. */
  309. s = newseg(SG_TEXT, UTZERO, 1);
  310. s->flushme++;
  311. p->seg[TSEG] = s;
  312. pg = newpage(1, 0, UTZERO);
  313. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  314. segpage(s, pg);
  315. k = kmap(s->map[0]->pages[0]);
  316. memset((void *)VA(k), 0, BY2PG);
  317. memmove((ulong*)VA(k), initcode, sizeof initcode);
  318. kunmap(k);
  319. ready(p);
  320. }
  321. void
  322. procrestore(Proc *p)
  323. {
  324. uvlong t;
  325. if(p->kp)
  326. return;
  327. cycles(&t);
  328. p->pcycles -= t;
  329. }
  330. /*
  331. * Save the mach dependent part of the process state.
  332. */
  333. void
  334. procsave(Proc *p)
  335. {
  336. uvlong t;
  337. cycles(&t);
  338. p->pcycles += t;
  339. /* no fpu, so no fp state to save */
  340. }
  341. static void
  342. writeconf(void)
  343. {
  344. char *p, *q;
  345. int n;
  346. p = getconfenv();
  347. if(waserror()) {
  348. free(p);
  349. nexterror();
  350. }
  351. /* convert to name=value\n format */
  352. for(q=p; *q; q++) {
  353. q += strlen(q);
  354. *q = '=';
  355. q += strlen(q);
  356. *q = '\n';
  357. }
  358. n = q - p + 1;
  359. #ifdef BOOTARGS_EXIST
  360. if(n >= BOOTARGSLEN)
  361. error("kernel configuration too large");
  362. memmove(BOOTARGS, p, n);
  363. memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
  364. #endif
  365. USED(n);
  366. poperror();
  367. free(p);
  368. }
  369. static void
  370. shutdown(int ispanic)
  371. {
  372. int ms, once;
  373. ilock(&active);
  374. if(ispanic)
  375. active.ispanic = ispanic;
  376. else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
  377. active.ispanic = 0;
  378. once = active.machs & (1<<m->machno);
  379. /*
  380. * setting exiting will make hzclock() on each processor call exit(0),
  381. * which calls shutdown(0) and idles non-bootstrap cpus and returns
  382. * on bootstrap processors (to permit a reboot). clearing our bit
  383. * in machs avoids calling exit(0) from hzclock() on this processor.
  384. */
  385. active.machs &= ~(1<<m->machno);
  386. active.exiting = 1;
  387. iunlock(&active);
  388. if(once) {
  389. delay(m->machno*1000); /* stagger them */
  390. iprint("cpu%d: exiting\n", m->machno);
  391. }
  392. spllo();
  393. ms = MAXMACH * 1000;
  394. for(; ms > 0; ms -= TK2MS(2)){
  395. delay(TK2MS(2));
  396. if(active.machs == 0 && consactive() == 0)
  397. break;
  398. }
  399. delay(100);
  400. }
  401. /*
  402. * the new kernel is already loaded at address `code'
  403. * of size `size' and entry point `entry'.
  404. */
  405. void
  406. reboot(void *entry, void *code, ulong size)
  407. {
  408. void (*f)(ulong, ulong, ulong);
  409. writeconf();
  410. /*
  411. * the boot processor is cpu0. execute this function on it
  412. * so that the new kernel has the same cpu0.
  413. */
  414. if (m->machno != 0) {
  415. procwired(up, 0);
  416. sched();
  417. }
  418. if (m->machno != 0)
  419. print("on cpu%d (not 0)!\n", m->machno);
  420. shutdown(0);
  421. /*
  422. * should be the only processor running now
  423. */
  424. // iprint("reboot: entry %#p code %#p size %ld\n", entry, code, size);
  425. // iprint("code[0] = %#lux\n", *(ulong *)code);
  426. /* turn off buffered serial console */
  427. serialoq = nil;
  428. kprintoq = nil;
  429. screenputs = nil;
  430. /* shutdown devices */
  431. chandevshutdown();
  432. /* call off the dog */
  433. clockshutdown();
  434. splhi();
  435. intrshutdown();
  436. /* is the watchdog tied into the usb machinery? */
  437. // *Reset |= Rstusbohcidll | Rstusbhost | Rstusbphy;
  438. // Rstge0mac | Rstge0phy |
  439. // Rstge1mac | Rstge1phy;
  440. /* setup reboot trampoline function */
  441. f = (void*)REBOOTADDR;
  442. memmove(f, rebootcode, sizeof(rebootcode));
  443. icflush(f, sizeof(rebootcode));
  444. setstatus(BEV); /* also, kernel mode, no interrupts */
  445. coherence();
  446. /* off we go - never to return */
  447. (*f)((ulong)entry, (ulong)code, size);
  448. panic("loaded kernel returned!");
  449. }
  450. void
  451. exit(int type)
  452. {
  453. int timer;
  454. void (*fnp)(void);
  455. stopwdog();
  456. delay(1000);
  457. lock(&active);
  458. active.machs &= ~(1<<m->machno);
  459. active.exiting = 1;
  460. unlock(&active);
  461. spllo();
  462. print("cpu %d exiting\n", m->machno);
  463. timer = 0;
  464. while(active.machs || consactive()) {
  465. if(timer++ > 400)
  466. break;
  467. delay(10);
  468. }
  469. delay(1000);
  470. splhi();
  471. USED(type);
  472. setstatus(BEV);
  473. coherence();
  474. iprint("exit: awaiting reset\n");
  475. wdogreset(); /* wake the dog with v. short timeout */
  476. // *Reset |= Rstfullchip;
  477. // *Reset |= Rstcpucold;
  478. delay(1000); /* await a reset */
  479. iprint("exit: jumping to rom\n");
  480. fnp = (void (*)(void))ROM;
  481. (*fnp)();
  482. iprint("exit: looping\n");
  483. for (;;)
  484. ;
  485. }
  486. void
  487. idlehands(void)
  488. {
  489. stopwdog();
  490. idle();
  491. sicwdog(); /* wake the dog */
  492. }
  493. void
  494. confinit(void)
  495. {
  496. ulong kpages, ktop;
  497. /*
  498. * divide memory twixt user pages and kernel.
  499. */
  500. conf.mem[0].base = ktop = PADDR(PGROUND((ulong)end));
  501. /* fixed memory on routerboard */
  502. conf.mem[0].npage = MEMSIZE/BY2PG - ktop/BY2PG;
  503. conf.npage = conf.mem[0].npage;
  504. conf.nuart = 1;
  505. kpages = conf.npage - (conf.npage*80)/100;
  506. if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
  507. kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
  508. kpages += (conf.nproc*KSTACK)/BY2PG;
  509. }
  510. conf.upages = conf.npage - kpages;
  511. conf.ialloc = (kpages/2)*BY2PG;
  512. kpages *= BY2PG;
  513. kpages -= conf.upages*sizeof(Page)
  514. + conf.nproc*sizeof(Proc)
  515. + conf.nimage*sizeof(Image)
  516. + conf.nswap
  517. + conf.nswppo*sizeof(Page);
  518. mainmem->maxsize = kpages;
  519. /*
  520. * set up CPU's mach structure
  521. * cpu0's was zeroed in l.s and our stack is in Mach, so don't zero it.
  522. */
  523. m->machno = 0;
  524. m->speed = 680; /* initial guess at MHz, for rb450g */
  525. m->hz = m->speed * Mhz;
  526. conf.nmach = 1;
  527. /* set up other configuration parameters */
  528. conf.nproc = 2000;
  529. conf.nswap = 262144;
  530. conf.nswppo = 4096;
  531. conf.nimage = 200;
  532. conf.copymode = 0; /* copy on write */
  533. }