main.c 8.8 KB

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