main.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  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 "arm.h"
  10. #include "reboot.h"
  11. /*
  12. * Where configuration info is left for the loaded programme.
  13. * This will turn into a structure as more is done by the boot loader
  14. * (e.g. why parse the .ini file twice?).
  15. * There are 3584 bytes available at CONFADDR.
  16. */
  17. #define BOOTARGS ((char*)CONFADDR)
  18. #define BOOTARGSLEN (16*KiB) /* limit in devenv.c */
  19. #define MAXCONF 64
  20. #define MAXCONFLINE 160
  21. enum {
  22. Minmem = 256*MB, /* conservative default */
  23. };
  24. #define isascii(c) ((uchar)(c) > 0 && (uchar)(c) < 0177)
  25. extern char bdata[], edata[], end[], etext[];
  26. uintptr kseg0 = KZERO;
  27. Mach* machaddr[MAXMACH];
  28. uchar *l2pages;
  29. Memcache cachel[8]; /* arm arch v7 supports 1-7 */
  30. /*
  31. * these are used by the cache.v7.s routines.
  32. */
  33. Lowmemcache *cacheconf;
  34. /*
  35. * Option arguments from the command line.
  36. * oargv[0] is the boot file.
  37. * Optionsinit() is called from multiboot()
  38. * or some other machine-dependent place
  39. * to set it all up.
  40. */
  41. static int oargc;
  42. static char* oargv[20];
  43. static char oargb[128];
  44. static int oargblen;
  45. static char oenv[4096];
  46. static uintptr sp; /* XXX - must go - user stack of init proc */
  47. int vflag;
  48. int normalprint;
  49. char debug[256];
  50. static Lock testlock;
  51. /* store plan9.ini contents here at least until we stash them in #ec */
  52. static char confname[MAXCONF][KNAMELEN];
  53. static char confval[MAXCONF][MAXCONFLINE];
  54. static int nconf;
  55. static int
  56. findconf(char *name)
  57. {
  58. int i;
  59. for(i = 0; i < nconf; i++)
  60. if(cistrcmp(confname[i], name) == 0)
  61. return i;
  62. return -1;
  63. }
  64. char*
  65. getconf(char *name)
  66. {
  67. int i;
  68. i = findconf(name);
  69. if(i >= 0)
  70. return confval[i];
  71. return nil;
  72. }
  73. void
  74. addconf(char *name, char *val)
  75. {
  76. int i;
  77. i = findconf(name);
  78. if(i < 0){
  79. if(val == nil || nconf >= MAXCONF)
  80. return;
  81. i = nconf++;
  82. strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
  83. }
  84. // confval[i] = val;
  85. strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
  86. }
  87. static void
  88. writeconf(void)
  89. {
  90. char *p, *q;
  91. int n;
  92. p = getconfenv();
  93. if(waserror()) {
  94. free(p);
  95. nexterror();
  96. }
  97. /* convert to name=value\n format */
  98. for(q=p; *q; q++) {
  99. q += strlen(q);
  100. *q = '=';
  101. q += strlen(q);
  102. *q = '\n';
  103. }
  104. n = q - p + 1;
  105. if(n >= BOOTARGSLEN)
  106. error("kernel configuration too large");
  107. memmove(BOOTARGS, p, n);
  108. memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
  109. poperror();
  110. free(p);
  111. }
  112. /*
  113. * assumes that we have loaded our /cfg/pxe/mac file at CONFADDR
  114. * (usually 0x1000) with tftp in u-boot. no longer uses malloc, so
  115. * can be called early.
  116. */
  117. static void
  118. plan9iniinit(void)
  119. {
  120. char *k, *v, *next;
  121. k = (char *)CONFADDR;
  122. if(!isascii(*k))
  123. return;
  124. for(; k && *k != '\0'; k = next) {
  125. if (!isascii(*k)) /* sanity check */
  126. break;
  127. next = strchr(k, '\n');
  128. if (next)
  129. *next++ = '\0';
  130. if (*k == '\0' || *k == '\n' || *k == '#')
  131. continue;
  132. v = strchr(k, '=');
  133. if(v == nil)
  134. continue; /* mal-formed line */
  135. *v++ = '\0';
  136. addconf(k, v);
  137. }
  138. }
  139. static void
  140. optionsinit(char* s)
  141. {
  142. char *o;
  143. strcpy(oenv, "");
  144. o = strecpy(oargb, oargb+sizeof(oargb), s)+1;
  145. if(getenv("bootargs", o, o - oargb) != nil)
  146. *(o-1) = ' ';
  147. oargblen = strlen(oargb);
  148. oargc = tokenize(oargb, oargv, nelem(oargv)-1);
  149. oargv[oargc] = nil;
  150. }
  151. char*
  152. getenv(char* name, char* buf, int n)
  153. {
  154. char *e, *p, *q;
  155. p = oenv;
  156. while(*p != 0){
  157. if((e = strchr(p, '=')) == nil)
  158. break;
  159. for(q = name; p < e; p++){
  160. if(*p != *q)
  161. break;
  162. q++;
  163. }
  164. if(p == e && *q == 0){
  165. strecpy(buf, buf+n, e+1);
  166. return buf;
  167. }
  168. p += strlen(p)+1;
  169. }
  170. return nil;
  171. }
  172. /* enable scheduling of this cpu */
  173. void
  174. machon(uint cpu)
  175. {
  176. ulong cpubit;
  177. cpubit = 1 << cpu;
  178. lock(&active);
  179. if ((active.machs & cpubit) == 0) { /* currently off? */
  180. conf.nmach++;
  181. active.machs |= cpubit;
  182. }
  183. unlock(&active);
  184. }
  185. /* disable scheduling of this cpu */
  186. void
  187. machoff(uint cpu)
  188. {
  189. ulong cpubit;
  190. cpubit = 1 << cpu;
  191. lock(&active);
  192. if (active.machs & cpubit) { /* currently on? */
  193. conf.nmach--;
  194. active.machs &= ~cpubit;
  195. }
  196. unlock(&active);
  197. }
  198. void
  199. machinit(void)
  200. {
  201. Mach *m0;
  202. if (m == 0) {
  203. serialputc('?');
  204. serialputc('m');
  205. serialputc('0');
  206. }
  207. if(machaddr[m->machno] != m) {
  208. serialputc('?');
  209. serialputc('m');
  210. serialputc('m');
  211. }
  212. if (canlock(&testlock)) {
  213. serialputc('?');
  214. serialputc('l');
  215. panic("cpu%d: locks don't work", m->machno);
  216. }
  217. m->ticks = 1;
  218. m->perf.period = 1;
  219. m0 = MACHP(0);
  220. if (m->machno != 0) {
  221. /* synchronise with cpu 0 */
  222. m->ticks = m0->ticks;
  223. m->fastclock = m0->fastclock;
  224. m->cpuhz = m0->cpuhz;
  225. m->delayloop = m0->delayloop;
  226. }
  227. if (m->machno != 0 &&
  228. (m->fastclock == 0 || m->cpuhz == 0 || m->delayloop == 0))
  229. panic("buggered cpu 0 Mach");
  230. machon(m->machno);
  231. fpoff();
  232. }
  233. /* l.s has already zeroed Mach, which now contains our stack. */
  234. void
  235. mach0init(void)
  236. {
  237. if (m == 0) {
  238. serialputc('?');
  239. serialputc('m');
  240. }
  241. conf.nmach = 0;
  242. m->machno = 0;
  243. machaddr[0] = m;
  244. lock(&testlock); /* hold this forever */
  245. machinit();
  246. active.exiting = 0;
  247. l1cache->wbse(&active, sizeof active);
  248. up = nil;
  249. }
  250. /*
  251. * count CPU's, set up their mach structures and l1 ptes.
  252. * we're running on cpu 0 and our data structures were
  253. * statically allocated.
  254. */
  255. void
  256. launchinit(void)
  257. {
  258. int mach;
  259. Mach *mm;
  260. PTE *l1;
  261. for(mach = 1; mach < MAXMACH; mach++){
  262. machaddr[mach] = mm = mallocalign(MACHSIZE, MACHSIZE, 0, 0);
  263. l1 = mallocalign(L1SIZE, L1SIZE, 0, 0);
  264. if(mm == nil || l1 == nil)
  265. panic("launchinit");
  266. memset(mm, 0, MACHSIZE);
  267. mm->machno = mach;
  268. memmove(l1, (void *)L1, L1SIZE); /* clone cpu0's l1 table */
  269. l1cache->wbse(l1, L1SIZE);
  270. mm->mmul1 = l1;
  271. l1cache->wbse(mm, MACHSIZE);
  272. }
  273. l1cache->wbse(machaddr, sizeof machaddr);
  274. conf.nmach = 1;
  275. }
  276. void
  277. dump(void *vaddr, int words)
  278. {
  279. ulong *addr;
  280. addr = vaddr;
  281. while (words-- > 0)
  282. iprint("%.8lux%c", *addr++, words % 8 == 0? '\n': ' ');
  283. }
  284. static void
  285. cacheinit(void)
  286. {
  287. allcacheinfo(cachel);
  288. cacheconf = (Lowmemcache *)CACHECONF;
  289. cacheconf->l1waysh = cachel[1].waysh;
  290. cacheconf->l1setsh = cachel[1].setsh;
  291. /* on the tegra 2, l2 is unarchitected */
  292. cacheconf->l2waysh = cachel[2].waysh;
  293. cacheconf->l2setsh = cachel[2].setsh;
  294. l2pl310init();
  295. allcacheson();
  296. allcache->wb();
  297. }
  298. void
  299. l2pageinit(void)
  300. {
  301. l2pages = KADDR(PHYSDRAM + DRAMSIZE - RESRVDHIMEM);
  302. }
  303. /*
  304. * at entry, l.s has set m for cpu0 and printed "Plan 9 from Be"
  305. * but has not zeroed bss.
  306. */
  307. void
  308. main(void)
  309. {
  310. int cpu;
  311. static ulong vfy = 0xcafebabe;
  312. up = nil;
  313. if (vfy != 0xcafebabe) {
  314. serialputc('?');
  315. serialputc('d');
  316. panic("data segment misaligned");
  317. }
  318. memset(edata, 0, end - edata);
  319. /*
  320. * we can't lock until smpon has run, but we're supposed to wait
  321. * until l1 & l2 are on. too bad. l1 is on, l2 will soon be.
  322. */
  323. smpon();
  324. iprint("ll Labs ");
  325. cacheinit();
  326. /*
  327. * data segment is aligned, bss is zeroed, caches' characteristics
  328. * are known. begin initialisation.
  329. */
  330. mach0init();
  331. l2pageinit();
  332. mmuinit();
  333. optionsinit("/boot/boot boot");
  334. quotefmtinstall();
  335. /* want plan9.ini to be able to affect memory sizing in confinit */
  336. plan9iniinit(); /* before we step on plan9.ini in low memory */
  337. /* l2 looks for *l2off= in plan9.ini */
  338. l2cache->on(); /* l2->on requires locks to work, thus smpon */
  339. l2cache->info(&cachel[2]);
  340. allcache->on();
  341. cortexa9cachecfg();
  342. trapinit(); /* so confinit can probe memory to size it */
  343. confinit(); /* figures out amount of memory */
  344. /* xinit prints (if it can), so finish up the banner here. */
  345. delay(100);
  346. navailcpus = getncpus();
  347. iprint("(mp arm; %d cpus)\n\n", navailcpus);
  348. delay(100);
  349. for (cpu = 1; cpu < navailcpus; cpu++)
  350. stopcpu(cpu);
  351. xinit();
  352. irqtooearly = 0; /* now that xinit and trapinit have run */
  353. mainmem->flags |= POOL_ANTAGONISM /* | POOL_PARANOIA */ ;
  354. /*
  355. * Printinit will cause the first malloc call.
  356. * (printinit->qopen->malloc) unless any of the
  357. * above (like clockinit) do an irqenable, which
  358. * will call malloc.
  359. * If the system dies here it's probably due
  360. * to malloc(->xalloc) not being initialised
  361. * correctly, or the data segment is misaligned
  362. * (it's amazing how far you can get with
  363. * things like that completely broken).
  364. *
  365. * (Should be) boilerplate from here on.
  366. */
  367. archreset(); /* cfg clock signals, print cache cfg */
  368. clockinit(); /* start clocks */
  369. timersinit();
  370. delay(50); /* let uart catch up */
  371. printinit();
  372. kbdenable();
  373. cpuidprint();
  374. chkmissing();
  375. procinit0();
  376. initseg();
  377. // dmainit();
  378. links();
  379. conf.monitor = 1;
  380. // screeninit();
  381. iprint("pcireset...");
  382. pcireset(); /* this tends to hang after a reboot */
  383. iprint("ok\n");
  384. chandevreset(); /* most devices are discovered here */
  385. // i8250console(); /* too early; see init0 */
  386. pageinit(); /* prints "1020M memory: ⋯ */
  387. swapinit();
  388. userinit();
  389. /*
  390. * starting a cpu will eventually result in it calling schedinit,
  391. * so everything necessary to run user processes should be set up
  392. * before starting secondary cpus.
  393. */
  394. launchinit();
  395. /* SMP & FW are already on when we get here; u-boot set them? */
  396. for (cpu = 1; cpu < navailcpus; cpu++)
  397. if (startcpu(cpu) < 0)
  398. panic("cpu%d didn't start", cpu);
  399. l1diag();
  400. schedinit();
  401. panic("cpu%d: schedinit returned", m->machno);
  402. }
  403. static void
  404. shutdown(int ispanic)
  405. {
  406. int ms, once;
  407. lock(&active);
  408. if(ispanic)
  409. active.ispanic = ispanic;
  410. else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
  411. active.ispanic = 0;
  412. once = active.machs & (1<<m->machno);
  413. /*
  414. * setting exiting will make hzclock() on each processor call exit(0),
  415. * which calls shutdown(0) and idles non-bootstrap cpus and returns
  416. * on bootstrap processors (to permit a reboot). clearing our bit
  417. * in machs avoids calling exit(0) from hzclock() on this processor.
  418. */
  419. active.machs &= ~(1<<m->machno);
  420. active.exiting = 1;
  421. unlock(&active);
  422. if(once) {
  423. delay(m->machno*1000); /* stagger them */
  424. iprint("cpu%d: exiting\n", m->machno);
  425. }
  426. spllo();
  427. if (m->machno == 0)
  428. ms = 5*1000;
  429. else
  430. ms = 2*1000;
  431. for(; ms > 0; ms -= TK2MS(2)){
  432. delay(TK2MS(2));
  433. if(active.machs == 0 && consactive() == 0)
  434. break;
  435. }
  436. delay(500);
  437. }
  438. /*
  439. * exit kernel either on a panic or user request
  440. */
  441. void
  442. exit(int code)
  443. {
  444. shutdown(code);
  445. splhi();
  446. if (m->machno == 0)
  447. archreboot();
  448. else {
  449. intrcpushutdown();
  450. stopcpu(m->machno);
  451. for (;;)
  452. idlehands();
  453. }
  454. }
  455. int
  456. isaconfig(char *class, int ctlrno, ISAConf *isa)
  457. {
  458. char cc[32], *p;
  459. int i;
  460. snprint(cc, sizeof cc, "%s%d", class, ctlrno);
  461. p = getconf(cc);
  462. if(p == nil)
  463. return 0;
  464. isa->type = "";
  465. isa->nopt = tokenize(p, isa->opt, NISAOPT);
  466. for(i = 0; i < isa->nopt; i++){
  467. p = isa->opt[i];
  468. if(cistrncmp(p, "type=", 5) == 0)
  469. isa->type = p + 5;
  470. else if(cistrncmp(p, "port=", 5) == 0)
  471. isa->port = strtoul(p+5, &p, 0);
  472. else if(cistrncmp(p, "irq=", 4) == 0)
  473. isa->irq = strtoul(p+4, &p, 0);
  474. else if(cistrncmp(p, "dma=", 4) == 0)
  475. isa->dma = strtoul(p+4, &p, 0);
  476. else if(cistrncmp(p, "mem=", 4) == 0)
  477. isa->mem = strtoul(p+4, &p, 0);
  478. else if(cistrncmp(p, "size=", 5) == 0)
  479. isa->size = strtoul(p+5, &p, 0);
  480. else if(cistrncmp(p, "freq=", 5) == 0)
  481. isa->freq = strtoul(p+5, &p, 0);
  482. }
  483. return 1;
  484. }
  485. /*
  486. * the new kernel is already loaded at address `code'
  487. * of size `size' and entry point `entry'.
  488. */
  489. void
  490. reboot(void *entry, void *code, ulong size)
  491. {
  492. int cpu, nmach, want, ms;
  493. void (*f)(ulong, ulong, ulong);
  494. nmach = conf.nmach;
  495. writeconf();
  496. /*
  497. * the boot processor is cpu0. execute this function on it
  498. * so that the new kernel has the same cpu0.
  499. */
  500. if (m->machno != 0) {
  501. procwired(up, 0);
  502. sched();
  503. }
  504. if (m->machno != 0)
  505. print("on cpu%d (not 0)!\n", m->machno);
  506. /*
  507. * the other cpus could be holding locks that will never get
  508. * released (e.g., in the print path) if we put them into
  509. * reset now, so force them to shutdown gracefully first.
  510. */
  511. for (want = 0, cpu = 1; cpu < navailcpus; cpu++)
  512. want |= 1 << cpu;
  513. active.stopped = 0;
  514. shutdown(0);
  515. for (ms = 15*1000; ms > 0 && active.stopped != want; ms -= 10)
  516. delay(10);
  517. delay(20);
  518. if (active.stopped != want) {
  519. for (cpu = 1; cpu < nmach; cpu++)
  520. stopcpu(cpu); /* make really sure */
  521. delay(20);
  522. }
  523. /*
  524. * should be the only processor running now
  525. */
  526. pcireset();
  527. // print("reboot entry %#lux code %#lux size %ld\n",
  528. // PADDR(entry), PADDR(code), size);
  529. /* turn off buffered serial console */
  530. serialoq = nil;
  531. kprintoq = nil;
  532. screenputs = nil;
  533. /* shutdown devices */
  534. chandevshutdown();
  535. /* call off the dog */
  536. clockshutdown();
  537. splhi();
  538. intrshutdown();
  539. /* setup reboot trampoline function */
  540. f = (void*)REBOOTADDR;
  541. memmove(f, rebootcode, sizeof(rebootcode));
  542. cachedwb();
  543. l2cache->wbinv();
  544. l2cache->off();
  545. cacheuwbinv();
  546. /* off we go - never to return */
  547. (*f)(PADDR(entry), PADDR(code), size);
  548. iprint("loaded kernel returned!\n");
  549. archreboot();
  550. }
  551. /*
  552. * starting place for first process
  553. */
  554. void
  555. init0(void)
  556. {
  557. int i;
  558. char buf[2*KNAMELEN];
  559. up->nerrlab = 0;
  560. coherence();
  561. spllo();
  562. /*
  563. * These are o.k. because rootinit is null.
  564. * Then early kproc's will have a root and dot.
  565. */
  566. up->slash = namec("#/", Atodir, 0, 0);
  567. pathclose(up->slash->path);
  568. up->slash->path = newpath("/");
  569. up->dot = cclone(up->slash);
  570. chandevinit();
  571. i8250console(); /* might be redundant, but harmless */
  572. if(kbdq == nil)
  573. panic("init0: nil kbdq");
  574. if(serialoq == nil)
  575. panic("init0: nil serialoq");
  576. normalprint = 1;
  577. if(!waserror()){
  578. snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
  579. ksetenv("terminal", buf, 0);
  580. ksetenv("cputype", "arm", 0);
  581. if(cpuserver)
  582. ksetenv("service", "cpu", 0);
  583. else
  584. ksetenv("service", "terminal", 0);
  585. /* convert plan9.ini variables to #e and #ec */
  586. for(i = 0; i < nconf; i++) {
  587. ksetenv(confname[i], confval[i], 0);
  588. ksetenv(confname[i], confval[i], 1);
  589. }
  590. poperror();
  591. }
  592. kproc("alarm", alarmkproc, 0);
  593. // kproc("startcpusproc", startcpusproc, nil);
  594. touser(sp);
  595. }
  596. static void
  597. bootargs(uintptr base)
  598. {
  599. int i;
  600. ulong ssize;
  601. char **av, *p;
  602. /*
  603. * Push the boot args onto the stack.
  604. * The initial value of the user stack must be such
  605. * that the total used is larger than the maximum size
  606. * of the argument list checked in syscall.
  607. */
  608. i = oargblen+1;
  609. p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(up->s.args) - i));
  610. memmove(p, oargb, i);
  611. /*
  612. * Now push argc and the argv pointers.
  613. * This isn't strictly correct as the code jumped to by
  614. * touser in init9.s calls startboot (port/initcode.c) which
  615. * expects arguments
  616. * startboot(char *argv0, char **argv)
  617. * not the usual (int argc, char* argv[]), but argv0 is
  618. * unused so it doesn't matter (at the moment...).
  619. */
  620. av = (char**)(p - (oargc+2)*sizeof(char*));
  621. ssize = base + BY2PG - PTR2UINT(av);
  622. *av++ = (char*)oargc;
  623. for(i = 0; i < oargc; i++)
  624. *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
  625. *av = nil;
  626. /*
  627. * Leave space for the return PC of the
  628. * caller of initcode.
  629. */
  630. sp = USTKTOP - ssize - sizeof(void*);
  631. }
  632. /*
  633. * create the first process
  634. */
  635. void
  636. userinit(void)
  637. {
  638. Proc *p;
  639. Segment *s;
  640. KMap *k;
  641. Page *pg;
  642. /* no processes yet */
  643. up = nil;
  644. p = newproc();
  645. p->pgrp = newpgrp();
  646. p->egrp = smalloc(sizeof(Egrp));
  647. p->egrp->ref = 1;
  648. p->fgrp = dupfgrp(nil);
  649. p->rgrp = newrgrp();
  650. p->procmode = 0640;
  651. kstrdup(&eve, "");
  652. kstrdup(&p->text, "*init*");
  653. kstrdup(&p->user, eve);
  654. /*
  655. * Kernel Stack
  656. */
  657. p->sched.pc = PTR2UINT(init0);
  658. p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
  659. p->sched.sp = STACKALIGN(p->sched.sp);
  660. /*
  661. * User Stack
  662. *
  663. * Technically, newpage can't be called here because it
  664. * should only be called when in a user context as it may
  665. * try to sleep if there are no pages available, but that
  666. * shouldn't be the case here.
  667. */
  668. s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
  669. s->flushme++;
  670. p->seg[SSEG] = s;
  671. pg = newpage(1, 0, USTKTOP-BY2PG);
  672. segpage(s, pg);
  673. k = kmap(pg);
  674. bootargs(VA(k));
  675. kunmap(k);
  676. /*
  677. * Text
  678. */
  679. s = newseg(SG_TEXT, UTZERO, 1);
  680. p->seg[TSEG] = s;
  681. pg = newpage(1, 0, UTZERO);
  682. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  683. segpage(s, pg);
  684. k = kmap(s->map[0]->pages[0]);
  685. memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
  686. kunmap(k);
  687. ready(p);
  688. }
  689. Conf conf; /* XXX - must go - gag */
  690. Confmem tsmem[nelem(conf.mem)] = {
  691. /*
  692. * Memory available to Plan 9:
  693. */
  694. { .base = PHYSDRAM, .limit = PHYSDRAM + Minmem, },
  695. };
  696. ulong memsize = DRAMSIZE;
  697. static int
  698. gotmem(uintptr sz)
  699. {
  700. uintptr addr;
  701. /* back off a little from the end */
  702. addr = (uintptr)KADDR(PHYSDRAM + sz - BY2WD);
  703. if (probeaddr(addr) >= 0) { /* didn't trap? memory present */
  704. memsize = sz;
  705. return 0;
  706. }
  707. return -1;
  708. }
  709. void
  710. confinit(void)
  711. {
  712. int i;
  713. ulong kpages;
  714. uintptr pa;
  715. char *p;
  716. /*
  717. * Copy the physical memory configuration to Conf.mem.
  718. */
  719. if(nelem(tsmem) > nelem(conf.mem)){
  720. iprint("memory configuration botch\n");
  721. exit(1);
  722. }
  723. if(0 && (p = getconf("*maxmem")) != nil) {
  724. memsize = strtoul(p, 0, 0) - PHYSDRAM;
  725. if (memsize < 16*MB) /* sanity */
  726. memsize = 16*MB;
  727. }
  728. /*
  729. * see if all that memory exists; if not, find out how much does.
  730. * trapinit must have been called first.
  731. */
  732. if (gotmem(memsize - RESRVDHIMEM) < 0)
  733. panic("can't find 1GB of memory");
  734. tsmem[0].limit = PHYSDRAM + memsize;
  735. memmove(conf.mem, tsmem, sizeof(tsmem));
  736. conf.npage = 0;
  737. pa = PADDR(PGROUND(PTR2UINT(end)));
  738. /*
  739. * we assume that the kernel is at the beginning of one of the
  740. * contiguous chunks of memory and fits therein.
  741. */
  742. for(i=0; i<nelem(conf.mem); i++){
  743. /* take kernel out of allocatable space */
  744. if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
  745. conf.mem[i].base = pa;
  746. conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
  747. conf.npage += conf.mem[i].npage;
  748. }
  749. conf.upages = (conf.npage*80)/100;
  750. conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
  751. /* set up other configuration parameters */
  752. conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
  753. if(cpuserver)
  754. conf.nproc *= 3;
  755. if(conf.nproc > 2000)
  756. conf.nproc = 2000;
  757. conf.nswap = conf.npage*3;
  758. conf.nswppo = 4096;
  759. conf.nimage = 200;
  760. /*
  761. * it's simpler on mp systems to take page-faults early,
  762. * on reference, rather than later, on write, which might
  763. * require tlb shootdowns.
  764. */
  765. conf.copymode = 1; /* copy on reference */
  766. /*
  767. * Guess how much is taken by the large permanent
  768. * datastructures. Mntcache and Mntrpc are not accounted for
  769. * (probably ~300KB).
  770. */
  771. kpages = conf.npage - conf.upages;
  772. kpages *= BY2PG;
  773. kpages -= conf.upages*sizeof(Page)
  774. + conf.nproc*sizeof(Proc)
  775. + conf.nimage*sizeof(Image)
  776. + conf.nswap
  777. + conf.nswppo*sizeof(Page);
  778. mainmem->maxsize = kpages;
  779. if(!cpuserver)
  780. /*
  781. * give terminals lots of image memory, too; the dynamic
  782. * allocation will balance the load properly, hopefully.
  783. * be careful with 32-bit overflow.
  784. */
  785. imagmem->maxsize = kpages;
  786. // archconfinit();
  787. }
  788. int
  789. cmpswap(long *addr, long old, long new)
  790. {
  791. return cas((int *)addr, old, new);
  792. }
  793. void
  794. advertwfi(void) /* advertise my wfi status */
  795. {
  796. ilock(&active);
  797. active.wfi |= 1 << m->machno;
  798. iunlock(&active);
  799. }
  800. void
  801. unadvertwfi(void) /* do not advertise my wfi status */
  802. {
  803. ilock(&active);
  804. active.wfi &= ~(1 << m->machno);
  805. iunlock(&active);
  806. }
  807. void
  808. idlehands(void)
  809. {
  810. #ifdef use_ipi
  811. int advertised;
  812. /* don't go into wfi until my local timer is ticking */
  813. if (m->ticks <= 1)
  814. return;
  815. advertised = 0;
  816. m->inidlehands++;
  817. /* avoid recursion via ilock, advertise iff this cpu is initialised */
  818. if (m->inidlehands == 1 && m->syscall > 0) {
  819. advertwfi();
  820. advertised = 1;
  821. }
  822. wfi();
  823. if (advertised)
  824. unadvertwfi();
  825. m->inidlehands--;
  826. #endif
  827. }
  828. void
  829. wakewfi(void)
  830. {
  831. #ifdef use_ipi
  832. uint cpu;
  833. /*
  834. * find any cpu other than me currently in wfi.
  835. * need not be exact.
  836. */
  837. cpu = BI2BY*BY2WD - 1 - clz(active.wfi & ~(1 << m->machno));
  838. if (cpu < MAXMACH)
  839. intrcpu(cpu);
  840. #endif
  841. }