main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "init.h"
  15. #include "io.h"
  16. static int initialTCs = 16;; /* default # of TCs */
  17. Conf conf; /* XXX - must go - gag */
  18. extern void crapoptions(void); /* XXX - must go */
  19. extern void confsetenv(void); /* XXX - must go */
  20. static uintptr sp; /* XXX - must go - user stack of init proc */
  21. uintptr kseg0 = KZERO;
  22. Sys* sys = nil;
  23. usize sizeofSys = sizeof(Sys);
  24. /*
  25. * Option arguments from the command line.
  26. * oargv[0] is the boot file.
  27. * Optionsinit() is called from multiboot() to
  28. * set it all up.
  29. */
  30. static int oargc;
  31. static char* oargv[20];
  32. static char oargb[128];
  33. static int oargblen;
  34. static int maxcores = 1024; /* max # of cores given as an argument */
  35. char dbgflg[256];
  36. static int vflag = 0;
  37. void
  38. optionsinit(char* s)
  39. {
  40. oargblen = strecpy(oargb, oargb+sizeof(oargb), s) - oargb;
  41. oargc = tokenize(oargb, oargv, nelem(oargv)-1);
  42. oargv[oargc] = nil;
  43. }
  44. static void
  45. options(int argc, char* argv[])
  46. {
  47. char *p;
  48. int n, o;
  49. /*
  50. * Process flags.
  51. * Flags [A-Za-z] may be optionally followed by
  52. * an integer level between 1 and 127 inclusive
  53. * (no space between flag and level).
  54. * '--' ends flag processing.
  55. */
  56. while(--argc > 0 && (*++argv)[0] == '-' && (*argv)[1] != '-'){
  57. while(o = *++argv[0]){
  58. if(!(o >= 'A' && o <= 'Z') && !(o >= 'a' && o <= 'z'))
  59. continue;
  60. n = strtol(argv[0]+1, &p, 0);
  61. if(p == argv[0]+1 || n < 1 || n > 127)
  62. n = 1;
  63. argv[0] = p-1;
  64. dbgflg[o] = n;
  65. }
  66. }
  67. vflag = dbgflg['v'];
  68. if(argc > 0){
  69. maxcores = strtol(argv[0], 0, 0);
  70. argc--;
  71. argv++;
  72. }
  73. if(argc > 0){
  74. initialTCs = strtol(argv[0], 0, 0);
  75. //argc--;
  76. //argv++;
  77. }
  78. }
  79. extern void setmachsched(Mach*);
  80. void
  81. squidboy(int apicno)
  82. {
  83. char *n[] = {
  84. [NIXAC] "AC",
  85. [NIXTC] "TC",
  86. [NIXKC] "KC"
  87. };
  88. vlong hz;
  89. sys->machptr[machp()->machno] = m;
  90. setmachsched(m);
  91. /*
  92. * Need something for initial delays
  93. * until a timebase is worked out.
  94. */
  95. m->cpuhz = 2000000000ll;
  96. m->cpumhz = 2000;
  97. m->perf.period = 1;
  98. m->nixtype = NIXAC;
  99. DBG("Hello Squidboy %d %d\n", apicno, machp()->machno);
  100. vsvminit(MACHSTKSZ, m->nixtype);
  101. /*
  102. * Beware the Curse of The Non-Interruptable Were-Temporary.
  103. */
  104. hz = archhz();
  105. if(hz == 0)
  106. ndnr();
  107. m->cpuhz = hz;
  108. m->cyclefreq = hz;
  109. m->cpumhz = hz/1000000ll;
  110. mmuinit();
  111. if(!apiconline())
  112. ndnr();
  113. fpuinit();
  114. acmodeset(m->nixtype);
  115. m->splpc = 0;
  116. m->online = 1;
  117. /*
  118. * CAUTION: no time sync done, etc.
  119. */
  120. DBG("Wait for the thunderbirds!\n");
  121. while(!active.thunderbirdsarego)
  122. ;
  123. wrmsr(0x10, sys->epoch);
  124. m->rdtsc = rdtsc();
  125. print("cpu%d color %d role %s tsc %lld\n",
  126. machp()->machno, corecolor(machp()->machno), n[m->nixtype], m->rdtsc);
  127. switch(m->nixtype){
  128. case NIXAC:
  129. acmmuswitch();
  130. acinit();
  131. adec(&active.nbooting);
  132. ainc(&active.nonline); /* this was commented out */
  133. acsched();
  134. panic("squidboy");
  135. break;
  136. case NIXTC:
  137. /*
  138. * We only need the idt and syscall entry point actually.
  139. * At boot time the boot processor might set our role after
  140. * we have decided to become an AC.
  141. */
  142. vsvminit(MACHSTKSZ, NIXTC);
  143. /*
  144. * Enable the timer interrupt.
  145. */
  146. apicpri(0);
  147. timersinit();
  148. adec(&active.nbooting);
  149. ainc(&active.nonline); /* this was commented out */
  150. schedinit();
  151. break;
  152. }
  153. panic("squidboy returns (type %d)", m->nixtype);
  154. }
  155. static void
  156. testiccs(void)
  157. {
  158. int i;
  159. Mach *mp;
  160. extern void testicc(int);
  161. /* setup arguments for all */
  162. for(i = 1; i < MACHMAX; i++)
  163. if((mp = sys->machptr[i]) != nil && mp->online != 0)
  164. if(mp->nixtype == NIXAC)
  165. testicc(i);
  166. print("bootcore: all cores done\n");
  167. }
  168. /*
  169. * Rendezvous with other cores. Set roles for those that came
  170. * up online, and wait until they are initialized.
  171. * Sync TSC with them.
  172. * We assume other processors that could boot had time to
  173. * set online to 1 by now.
  174. */
  175. static void
  176. nixsquids(void)
  177. {
  178. Mach *mp;
  179. int i;
  180. uint64_t now, start;
  181. for(i = 1; i < MACHMAX; i++)
  182. if((mp = sys->machptr[i]) != nil && mp->online != 0){
  183. /*
  184. * Inter-core calls. A ensure *mp->iccall and mp->icargs
  185. * go into different cache lines.
  186. */
  187. mp->icc = mallocalign(sizeof *m->icc, ICCLNSZ, 0, 0);
  188. mp->icc->fn = nil;
  189. if(i < initialTCs){
  190. conf.nmach++;
  191. mp->nixtype = NIXTC;
  192. }
  193. ainc(&active.nbooting);
  194. }
  195. sys->epoch = rdtsc();
  196. mfence();
  197. wrmsr(0x10, sys->epoch);
  198. m->rdtsc = rdtsc();
  199. active.thunderbirdsarego = 1;
  200. start = fastticks2us(fastticks(nil));
  201. do{
  202. now = fastticks2us(fastticks(nil));
  203. }while(active.nbooting > 0 && now - start < 1000000)
  204. ;
  205. if(active.nbooting > 0)
  206. print("cpu0: %d cores couldn't start\n", active.nbooting);
  207. active.nbooting = 0;
  208. }
  209. void
  210. DONE(void)
  211. {
  212. print("DONE\n");
  213. prflush();
  214. delay(10000);
  215. ndnr();
  216. }
  217. void
  218. HERE(void)
  219. {
  220. print("here\n");
  221. prflush();
  222. delay(5000);
  223. }
  224. void
  225. main(uint32_t ax, uint32_t bx)
  226. {
  227. int64_t hz;
  228. memset(edata, 0, end - edata);
  229. /*
  230. * ilock via i8250enable via i8250console
  231. * needs machp()->machno, sys->machptr[] set, and
  232. * also 'up' set to nil.
  233. */
  234. cgapost(sizeof(uintptr)*8);
  235. memset(m, 0, sizeof(Mach));
  236. machp()->machno = 0;
  237. m->online = 1;
  238. m->nixtype = NIXTC;
  239. sys->machptr[machp()->machno] = &sys->mach;
  240. m->stack = PTR2UINT(sys->machstk);
  241. m->vsvm = sys->vsvmpage;
  242. up = nil;
  243. active.nonline = 1;
  244. active.exiting = 0;
  245. active.nbooting = 0;
  246. asminit();
  247. multiboot(ax, bx, 0);
  248. options(oargc, oargv);
  249. crapoptions();
  250. /*
  251. * Need something for initial delays
  252. * until a timebase is worked out.
  253. */
  254. m->cpuhz = 2000000000ll;
  255. m->cpumhz = 2000;
  256. cgainit();
  257. i8250console("0");
  258. consputs = cgaconsputs;
  259. vsvminit(MACHSTKSZ, NIXTC);
  260. conf.nmach = 1;
  261. fmtinit();
  262. print("\nNIX\n");
  263. if(vflag){
  264. print("&ax = %#p, ax = %#x, bx = %#x\n", &ax, ax, bx);
  265. multiboot(ax, bx, vflag);
  266. }
  267. m->perf.period = 1;
  268. if((hz = archhz()) != 0ll){
  269. m->cpuhz = hz;
  270. m->cyclefreq = hz;
  271. m->cpumhz = hz/1000000ll;
  272. }
  273. /*
  274. * Mmuinit before meminit because it
  275. * flushes the TLB via machp()->pml4->pa.
  276. */
  277. mmuinit();
  278. ioinit();
  279. kbdinit();
  280. meminit();
  281. confinit();
  282. archinit();
  283. mallocinit();
  284. /*
  285. * Acpiinit will cause the first malloc
  286. * call to happen.
  287. * If the system dies here it's probably due
  288. * to malloc not being initialised
  289. * correctly, or the data segment is misaligned
  290. * (it's amazing how far you can get with
  291. * things like that completely broken).
  292. */
  293. acpiinit();
  294. umeminit();
  295. trapinit();
  296. printinit();
  297. /*
  298. * This is necessary with GRUB and QEMU.
  299. * Without it an interrupt can occur at a weird vector,
  300. * because the vector base is likely different, causing
  301. * havoc. Do it before any APIC initialisation.
  302. */
  303. i8259init(32);
  304. procinit0();
  305. mpsinit(maxcores);
  306. apiconline();
  307. sipi();
  308. timersinit();
  309. kbdenable();
  310. fpuinit();
  311. psinit(conf.nproc);
  312. initimage();
  313. links();
  314. devtabreset();
  315. pageinit();
  316. swapinit();
  317. userinit();
  318. nixsquids();
  319. testiccs();
  320. print("schedinit...\n");
  321. schedinit();
  322. }
  323. void
  324. init0(void)
  325. {
  326. char buf[2*KNAMELEN];
  327. up->nerrlab = 0;
  328. // if(consuart == nil)
  329. // i8250console("0");
  330. spllo();
  331. /*
  332. * These are o.k. because rootinit is null.
  333. * Then early kproc's will have a root and dot.
  334. */
  335. up->slash = namec("#/", Atodir, 0, 0);
  336. pathclose(up->slash->path);
  337. up->slash->path = newpath("/");
  338. up->dot = cclone(up->slash);
  339. devtabinit();
  340. if(!waserror()){
  341. snprint(buf, sizeof(buf), "%s %s", "AMD64", conffile);
  342. ksetenv("terminal", buf, 0);
  343. ksetenv("cputype", "amd64", 0);
  344. if(cpuserver)
  345. ksetenv("service", "cpu", 0);
  346. else
  347. ksetenv("service", "terminal", 0);
  348. ksetenv("pgsz", "2097152", 0);
  349. confsetenv();
  350. poperror();
  351. }
  352. kproc("alarm", alarmkproc, 0);
  353. touser(sp);
  354. }
  355. void
  356. bootargs(uintptr base)
  357. {
  358. int i;
  359. uint32_t ssize;
  360. char **av, *p;
  361. /*
  362. * Push the boot args onto the stack.
  363. * Make sure the validaddr check in syscall won't fail
  364. * because there are fewer than the maximum number of
  365. * args by subtracting sizeof(up->arg).
  366. */
  367. i = oargblen+1;
  368. p = UINT2PTR(STACKALIGN(base + BIGPGSZ - sizeof(up->arg) - i));
  369. memmove(p, oargb, i);
  370. /*
  371. * Now push argc and the argv pointers.
  372. * This isn't strictly correct as the code jumped to by
  373. * touser in init9.[cs] calls startboot (port/initcode.c) which
  374. * expects arguments
  375. * startboot(char* argv0, char* argv[])
  376. * not the usual (int argc, char* argv[]), but argv0 is
  377. * unused so it doesn't matter (at the moment...).
  378. */
  379. av = (char**)(p - (oargc+2)*sizeof(char*));
  380. ssize = base + BIGPGSZ - PTR2UINT(av);
  381. *av++ = (char*)oargc;
  382. for(i = 0; i < oargc; i++)
  383. *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BIGPGSZ);
  384. *av = nil;
  385. sp = USTKTOP - ssize;
  386. }
  387. void
  388. userinit(void)
  389. {
  390. Proc *p;
  391. Segment *s;
  392. KMap *k;
  393. Page *pg;
  394. p = newproc();
  395. p->pgrp = newpgrp();
  396. p->egrp = smalloc(sizeof(Egrp));
  397. p->egrp->ref = 1;
  398. p->fgrp = dupfgrp(nil);
  399. p->rgrp = newrgrp();
  400. p->procmode = 0640;
  401. kstrdup(&eve, "");
  402. kstrdup(&p->text, "*init*");
  403. kstrdup(&p->user, eve);
  404. /*
  405. * Kernel Stack
  406. *
  407. * N.B. make sure there's enough space for syscall to check
  408. * for valid args and
  409. * space for gotolabel's return PC
  410. * AMD64 stack must be quad-aligned.
  411. */
  412. p->sched.pc = PTR2UINT(init0);
  413. p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->arg)-sizeof(uintptr));
  414. p->sched.sp = STACKALIGN(p->sched.sp);
  415. /*
  416. * User Stack
  417. *
  418. * Technically, newpage can't be called here because it
  419. * should only be called when in a user context as it may
  420. * try to sleep if there are no pages available, but that
  421. * shouldn't be the case here.
  422. */
  423. s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BIGPGSZ);
  424. p->seg[SSEG] = s;
  425. pg = newpage(1, 0, USTKTOP-BIGPGSZ, BIGPGSZ, -1);
  426. segpage(s, pg);
  427. k = kmap(pg);
  428. bootargs(VA(k));
  429. kunmap(k);
  430. /*
  431. * Text
  432. */
  433. s = newseg(SG_TEXT, UTZERO, 1);
  434. s->flushme++;
  435. p->seg[TSEG] = s;
  436. pg = newpage(1, 0, UTZERO, BIGPGSZ, -1);
  437. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  438. segpage(s, pg);
  439. k = kmap(s->map[0]->pages[0]);
  440. memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
  441. kunmap(k);
  442. ready(p);
  443. }
  444. void
  445. confinit(void)
  446. {
  447. int i;
  448. conf.npage = 0;
  449. for(i=0; i<nelem(conf.mem); i++)
  450. conf.npage += conf.mem[i].npage;
  451. conf.nproc = 100 + ((conf.npage*PGSZ)/MB)*5;
  452. if(cpuserver)
  453. conf.nproc *= 3;
  454. if(conf.nproc > 1000)
  455. conf.nproc = 1000;
  456. conf.nimage = 200;
  457. conf.nswap = conf.nproc*80;
  458. conf.nswppo = 4096;
  459. }
  460. static void
  461. shutdown(int ispanic)
  462. {
  463. int ms, once;
  464. lock(&active);
  465. if(ispanic)
  466. active.ispanic = ispanic;
  467. else if(machp()->machno == 0 && m->online == 0)
  468. active.ispanic = 0;
  469. once = m->online;
  470. m->online = 0;
  471. adec(&active.nonline);
  472. active.exiting = 1;
  473. unlock(&active);
  474. if(once)
  475. iprint("cpu%d: exiting\n", machp()->machno);
  476. spllo();
  477. for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
  478. delay(TK2MS(2));
  479. if(active.nonline == 0 && consactive() == 0)
  480. break;
  481. }
  482. if(active.ispanic && machp()->machno == 0){
  483. if(cpuserver)
  484. delay(30000);
  485. else
  486. for(;;)
  487. halt();
  488. }
  489. else
  490. delay(1000);
  491. }
  492. void
  493. reboot(void*, void*, int32_t)
  494. {
  495. panic("reboot\n");
  496. }
  497. void
  498. exit(int ispanic)
  499. {
  500. shutdown(ispanic);
  501. archreset();
  502. }