main.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  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. #define MAXCONF 64
  10. typedef struct Plan9ini Plan9ini;
  11. struct Plan9ini
  12. {
  13. char *name;
  14. char *val;
  15. };
  16. char *plan9inistr;
  17. Plan9ini plan9ini[MAXCONF];
  18. int nconf;
  19. Conf conf;
  20. FPsave initfp;
  21. Lock testlock;
  22. static void plan9iniinit(void);
  23. void (*_reboot)(void);
  24. void
  25. main(void)
  26. {
  27. memset(edata, 0, (ulong)end-(ulong)edata);
  28. conf.nmach = 1;
  29. machinit();
  30. confinit();
  31. xinit();
  32. trapinit();
  33. mmuinit();
  34. plan9iniinit();
  35. hwintrinit();
  36. clockinit();
  37. timerinit();
  38. console();
  39. quotefmtinstall();
  40. printinit();
  41. cpuidprint();
  42. print("\nPlan 9 from Bell Labs\n");
  43. procinit0();
  44. initseg();
  45. timersinit();
  46. links();
  47. chandevreset();
  48. pageinit();
  49. swapinit();
  50. sharedseginit();
  51. fpsave(&initfp);
  52. initfp.fpscr = 0;
  53. userinit();
  54. schedinit();
  55. }
  56. void
  57. cpuidprint(void)
  58. {
  59. char *id;
  60. id = "unknown PowerPC";
  61. switch(m->cputype) {
  62. case 8:
  63. id = "PowerPC 750";
  64. break;
  65. case 9:
  66. id = "PowerPC 604e";
  67. break;
  68. case 0x81:
  69. id = "PowerPC 8260";
  70. break;
  71. case 0x8081:
  72. id = "PowerPC 826xA";
  73. break;
  74. default:
  75. break;
  76. }
  77. print("cpu0: %s, rev 0x%lux\n", id, getpvr()&0xffff);
  78. }
  79. char*
  80. getconf(char *name)
  81. {
  82. int i;
  83. for(i = 0; i < nconf; i++)
  84. if(cistrcmp(name, plan9ini[i].name) == 0)
  85. return plan9ini[i].val;
  86. return nil;
  87. }
  88. static void
  89. plan9iniinit(void)
  90. {
  91. long i;
  92. int c;
  93. char *cp, line[MAXCONF], *p, *q;
  94. _reboot = (void (*)(void))0xff400000;
  95. /*
  96. * parse configuration args from dos file plan9.ini
  97. */
  98. /* Plan9.ini location in flash is FLASHMEM+PLAN9INI
  99. * if PLAN9INI == ~0, it's not stored in flash or there is no flash
  100. * if *cp == 0xff, flash memory is not initialized
  101. */
  102. if (PLAN9INI == ~0 || *(cp = (char*)(FLASHMEM+PLAN9INI)) == 0xff){
  103. /* No plan9.ini in flash */
  104. cp = plan9inistr;
  105. }
  106. for(i = 0; i < MAXCONF; i++){
  107. /*
  108. * Strip out '\r', change '\t' -> ' ', test for 0xff which is end of file
  109. */
  110. p = line;
  111. for(q = cp; c = (uchar)*q; q++){
  112. if(c == '\r')
  113. continue;
  114. if(c == '\t')
  115. c = ' ';
  116. if(c == 0xff || c == '\n')
  117. break;
  118. *p++ = c;
  119. }
  120. *p = 0;
  121. if (*line == 0)
  122. break;
  123. if(*line != '#' && (cp = strchr(line, '='))){
  124. *cp++ = '\0';
  125. kstrdup(&plan9ini[nconf].name, line);
  126. kstrdup(&plan9ini[nconf].val, cp);
  127. nconf++;
  128. }
  129. if (c == 0xff)
  130. break;
  131. cp = q + 1;
  132. }
  133. }
  134. /* still to do */
  135. void
  136. reboot(void*, void*, ulong)
  137. {
  138. _reboot();
  139. }
  140. void
  141. init0(void)
  142. {
  143. // char **p, *q, name[KNAMELEN];
  144. int i;
  145. char buf[2*KNAMELEN];
  146. up->nerrlab = 0;
  147. spllo();
  148. /*
  149. * These are o.k. because rootinit is null.
  150. * Then early kproc's will have a root and dot.
  151. */
  152. up->slash = namec("#/", Atodir, 0, 0);
  153. cnameclose(up->slash->name);
  154. up->slash->name = newcname("/");
  155. up->dot = cclone(up->slash);
  156. chandevinit();
  157. if(!waserror()){
  158. snprint(buf, sizeof(buf), "power %s mtx", conffile);
  159. ksetenv("terminal", buf, 0);
  160. ksetenv("cputype", "power", 0);
  161. if(cpuserver)
  162. ksetenv("service", "cpu", 0);
  163. else
  164. ksetenv("service", "terminal", 0);
  165. for(i = 0; i < nconf; i++){
  166. if(plan9ini[i].name[0] != '*')
  167. ksetenv(plan9ini[i].name, plan9ini[i].val, 0);
  168. ksetenv(plan9ini[i].name, plan9ini[i].val, 1);
  169. }
  170. poperror();
  171. }
  172. kproc("alarm", alarmkproc, 0);
  173. kproc("mmusweep", mmusweep, 0);
  174. touser((void*)(USTKTOP-8));
  175. }
  176. void
  177. userinit(void)
  178. {
  179. Proc *p;
  180. Segment *s;
  181. KMap *k;
  182. Page *pg;
  183. p = newproc();
  184. p->pgrp = newpgrp();
  185. p->egrp = smalloc(sizeof(Egrp));
  186. p->egrp->ref = 1;
  187. p->fgrp = dupfgrp(nil);
  188. p->rgrp = newrgrp();
  189. p->procmode = 0640;
  190. kstrdup(&eve, "");
  191. kstrdup(&p->text, "*init*");
  192. kstrdup(&p->user, eve);
  193. p->fpstate = FPinit;
  194. /*
  195. * Stack
  196. *
  197. * N.B. The -12 for the stack pointer is important.
  198. * 4 bytes for gotolabel's return PC
  199. */
  200. p->sched.pc = (ulong)init0;
  201. p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
  202. /*
  203. * User Stack
  204. */
  205. s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  206. p->seg[SSEG] = s;
  207. pg = newpage(1, 0, USTKTOP-BY2PG);
  208. segpage(s, pg);
  209. /*
  210. * Text
  211. */
  212. s = newseg(SG_TEXT, UTZERO, 1);
  213. s->flushme++;
  214. p->seg[TSEG] = s;
  215. pg = newpage(1, 0, UTZERO);
  216. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  217. segpage(s, pg);
  218. k = kmap(s->map[0]->pages[0]);
  219. memmove((ulong*)VA(k), initcode, sizeof initcode);
  220. kunmap(k);
  221. ready(p);
  222. }
  223. void
  224. exit(int ispanic)
  225. {
  226. int ms, once;
  227. lock(&active);
  228. if(ispanic)
  229. active.ispanic = ispanic;
  230. else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
  231. active.ispanic = 0;
  232. once = active.machs & (1<<m->machno);
  233. active.machs &= ~(1<<m->machno);
  234. active.exiting = 1;
  235. unlock(&active);
  236. if(once)
  237. print("cpu%d: exiting\n", m->machno);
  238. spllo();
  239. for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
  240. delay(TK2MS(2));
  241. if(active.machs == 0 && consactive() == 0)
  242. break;
  243. }
  244. if(active.ispanic && m->machno == 0){
  245. if(cpuserver)
  246. delay(10000);
  247. else if(conf.monitor)
  248. for(;;);
  249. }
  250. else
  251. delay(1000);
  252. }
  253. /*
  254. * set up floating point for a new process
  255. */
  256. void
  257. procsetup(Proc *p)
  258. {
  259. p->fpstate = FPinit;
  260. }
  261. /*
  262. * Save the mach dependent part of the process state.
  263. */
  264. void
  265. procsave(Proc *p)
  266. {
  267. if(p->fpstate == FPactive){
  268. if(p->state != Moribund)
  269. fpsave(&up->fpsave);
  270. p->fpstate = FPinactive;
  271. }
  272. }
  273. void
  274. confinit(void)
  275. {
  276. char *p;
  277. int userpcnt;
  278. ulong pa, kpages;
  279. /* passed in from ROM monitor: */
  280. if(p = getconf("*kernelpercent"))
  281. userpcnt = 100 - strtol(p, 0, 0);
  282. else
  283. userpcnt = 0;
  284. pa = PGROUND(PADDR(end));
  285. /* Blast Board specific */
  286. conf.npage0 = (MEM1SIZE - pa)/BY2PG;
  287. conf.base0 = pa;
  288. conf.npage1 = MEM2SIZE/BY2PG;
  289. conf.base1 = MEM2BASE;
  290. conf.npage = conf.npage0 + conf.npage1;
  291. conf.nmach = 1;
  292. conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
  293. if(cpuserver)
  294. conf.nproc *= 3;
  295. if(conf.nproc > 2000)
  296. conf.nproc = 2000;
  297. conf.nimage = 200;
  298. conf.nswap = conf.nproc*80;
  299. conf.nswppo = 4096;
  300. conf.copymode = 0; /* copy on write */
  301. if(cpuserver) {
  302. if(userpcnt < 10)
  303. userpcnt = 70;
  304. kpages = conf.npage - (conf.npage*userpcnt)/100;
  305. /*
  306. * Hack for the big boys. Only good while physmem < 4GB.
  307. * Give the kernel a max. of 16MB + enough to allocate the
  308. * page pool.
  309. * This is an overestimate as conf.upages < conf.npages.
  310. * The patch of nimage is a band-aid, scanning the whole
  311. * page list in imagereclaim just takes too long.
  312. */
  313. if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
  314. kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
  315. conf.nimage = 2000;
  316. kpages += (conf.nproc*KSTACK)/BY2PG;
  317. }
  318. } else {
  319. if(userpcnt < 10) {
  320. if(conf.npage*BY2PG < 16*MB)
  321. userpcnt = 40;
  322. else
  323. userpcnt = 60;
  324. }
  325. kpages = conf.npage - (conf.npage*userpcnt)/100;
  326. /*
  327. * Make sure terminals with low memory get at least
  328. * 4MB on the first Image chunk allocation.
  329. */
  330. if(conf.npage*BY2PG < 16*MB)
  331. imagmem->minarena = 4*1024*1024;
  332. }
  333. conf.upages = conf.npage - kpages;
  334. conf.ialloc = (kpages/2)*BY2PG;
  335. /*
  336. * Guess how much is taken by the large permanent
  337. * datastructures. Mntcache and Mntrpc are not accounted for
  338. * (probably ~300KB).
  339. */
  340. kpages *= BY2PG;
  341. kpages -= conf.upages*sizeof(Page)
  342. + conf.nproc*sizeof(Proc)
  343. + conf.nimage*sizeof(Image)
  344. + conf.nswap
  345. + conf.nswppo*sizeof(Page);
  346. mainmem->maxsize = kpages;
  347. if(!cpuserver){
  348. /*
  349. * give terminals lots of image memory, too; the dynamic
  350. * allocation will balance the load properly, hopefully.
  351. * be careful with 32-bit overflow.
  352. */
  353. imagmem->maxsize = kpages;
  354. }
  355. // conf.monitor = 1; /* BUG */
  356. }
  357. static int
  358. getcfields(char* lp, char** fields, int n, char* sep)
  359. {
  360. int i;
  361. for(i = 0; lp && *lp && i < n; i++){
  362. while(*lp && strchr(sep, *lp) != 0)
  363. *lp++ = 0;
  364. if(*lp == 0)
  365. break;
  366. fields[i] = lp;
  367. while(*lp && strchr(sep, *lp) == 0){
  368. if(*lp == '\\' && *(lp+1) == '\n')
  369. *lp++ = ' ';
  370. lp++;
  371. }
  372. }
  373. return i;
  374. }
  375. int
  376. isaconfig(char *class, int ctlrno, ISAConf *isa)
  377. {
  378. int i;
  379. char cc[KNAMELEN], *p;
  380. sprint(cc, "%s%d", class, ctlrno);
  381. p = getconf(cc);
  382. if(p == 0)
  383. return 0;
  384. isa->nopt = tokenize(p, isa->opt, NISAOPT);
  385. for(i = 0; i < isa->nopt; i++){
  386. p = isa->opt[i];
  387. if(cistrncmp(p, "type=", 5) == 0)
  388. isa->type = p + 5;
  389. else if(cistrncmp(p, "port=", 5) == 0)
  390. isa->port = strtoul(p+5, &p, 0);
  391. else if(cistrncmp(p, "irq=", 4) == 0)
  392. isa->irq = strtoul(p+4, &p, 0);
  393. else if(cistrncmp(p, "dma=", 4) == 0)
  394. isa->dma = strtoul(p+4, &p, 0);
  395. else if(cistrncmp(p, "mem=", 4) == 0)
  396. isa->mem = strtoul(p+4, &p, 0);
  397. else if(cistrncmp(p, "size=", 5) == 0)
  398. isa->size = strtoul(p+5, &p, 0);
  399. else if(cistrncmp(p, "freq=", 5) == 0)
  400. isa->freq = strtoul(p+5, &p, 0);
  401. }
  402. return 1;
  403. }
  404. int
  405. cistrcmp(char *a, char *b)
  406. {
  407. int ac, bc;
  408. for(;;){
  409. ac = *a++;
  410. bc = *b++;
  411. if(ac >= 'A' && ac <= 'Z')
  412. ac = 'a' + (ac - 'A');
  413. if(bc >= 'A' && bc <= 'Z')
  414. bc = 'a' + (bc - 'A');
  415. ac -= bc;
  416. if(ac)
  417. return ac;
  418. if(bc == 0)
  419. break;
  420. }
  421. return 0;
  422. }
  423. int
  424. cistrncmp(char *a, char *b, int n)
  425. {
  426. unsigned ac, bc;
  427. while(n > 0){
  428. ac = *a++;
  429. bc = *b++;
  430. n--;
  431. if(ac >= 'A' && ac <= 'Z')
  432. ac = 'a' + (ac - 'A');
  433. if(bc >= 'A' && bc <= 'Z')
  434. bc = 'a' + (bc - 'A');
  435. ac -= bc;
  436. if(ac)
  437. return ac;
  438. if(bc == 0)
  439. break;
  440. }
  441. return 0;
  442. }