PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/os/pc/main.c

https://bitbucket.org/floren/inferno/
C | 468 lines | 353 code | 63 blank | 52 comment | 61 complexity | 105c65610130632bc6545040323d1cef MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception
  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 "ureg.h"
  8. extern int main_pool_pcnt;
  9. extern int heap_pool_pcnt;
  10. extern int image_pool_pcnt;
  11. int pckdebug;
  12. Mach *m;
  13. static uchar *sp; /* stack pointer for /boot */
  14. /*
  15. * Where configuration info is left for the loaded programme.
  16. * This will turn into a structure as more is done by the boot loader
  17. * (e.g. why parse the .ini file twice?).
  18. * There are 3584 bytes available at CONFADDR.
  19. */
  20. #define BOOTLINE ((char*)CONFADDR)
  21. #define BOOTLINELEN 64
  22. #define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
  23. #define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
  24. #define MAXCONF 64
  25. char bootdisk[KNAMELEN];
  26. char *confname[MAXCONF];
  27. char *confval[MAXCONF];
  28. int nconf;
  29. static void
  30. options(void)
  31. {
  32. long i, n;
  33. char *cp, *line[MAXCONF], *p, *q;
  34. /*
  35. * parse configuration args from dos file plan9.ini
  36. */
  37. cp = BOOTARGS; /* where b.com leaves its config */
  38. cp[BOOTARGSLEN-1] = 0;
  39. /*
  40. * Strip out '\r', change '\t' -> ' '.
  41. */
  42. p = cp;
  43. for(q = cp; *q; q++){
  44. if(*q == '\r')
  45. continue;
  46. if(*q == '\t')
  47. *q = ' ';
  48. *p++ = *q;
  49. }
  50. *p = 0;
  51. n = getfields(cp, line, MAXCONF, 1, "\n");
  52. for(i = 0; i < n; i++){
  53. if(*line[i] == '#')
  54. continue;
  55. cp = strchr(line[i], '=');
  56. if(cp == nil)
  57. continue;
  58. *cp++ = '\0';
  59. confname[nconf] = line[i];
  60. confval[nconf] = cp;
  61. nconf++;
  62. }
  63. }
  64. static void
  65. doc(char *m)
  66. {
  67. int i;
  68. print("%s...\n", m);
  69. for(i = 0; i < 100*1024*1024; i++)
  70. i++;
  71. }
  72. void
  73. main(void)
  74. {
  75. outb(0x3F2, 0x00); /* botch: turn off the floppy motor */
  76. mach0init();
  77. options();
  78. ioinit();
  79. i8250console();
  80. quotefmtinstall();
  81. kbdinit();
  82. i8253init();
  83. cpuidentify();
  84. confinit();
  85. archinit();
  86. xinit();
  87. poolsizeinit();
  88. trapinit();
  89. printinit();
  90. screeninit();
  91. cpuidprint();
  92. mmuinit();
  93. eve = strdup("inferno");
  94. if(arch->intrinit){ /* launches other processors on an mp */
  95. doc("intrinit");
  96. arch->intrinit();
  97. }
  98. doc("timersinit");
  99. timersinit();
  100. doc("mathinit");
  101. mathinit();
  102. doc("kbdenable");
  103. kbdenable();
  104. if(arch->clockenable){
  105. doc("clockinit");
  106. arch->clockenable();
  107. }
  108. doc("procinit");
  109. procinit();
  110. doc("links");
  111. links();
  112. doc("chandevreset");
  113. chandevreset();
  114. doc("userinit");
  115. userinit();
  116. doc("schedinit");
  117. active.thunderbirdsarego = 1;
  118. schedinit();
  119. }
  120. void
  121. mach0init(void)
  122. {
  123. conf.nmach = 1;
  124. MACHP(0) = (Mach*)CPU0MACH;
  125. m->pdb = (ulong*)CPU0PDB;
  126. m->gdt = (Segdesc*)CPU0GDT;
  127. machinit();
  128. active.machs = 1;
  129. active.exiting = 0;
  130. }
  131. void
  132. machinit(void)
  133. {
  134. int machno;
  135. ulong *pdb;
  136. Segdesc *gdt;
  137. machno = m->machno;
  138. pdb = m->pdb;
  139. gdt = m->gdt;
  140. memset(m, 0, sizeof(Mach));
  141. m->machno = machno;
  142. m->pdb = pdb;
  143. m->gdt = gdt;
  144. /*
  145. * For polled uart output at boot, need
  146. * a default delay constant. 100000 should
  147. * be enough for a while. Cpuidentify will
  148. * calculate the real value later.
  149. */
  150. m->loopconst = 100000;
  151. }
  152. void
  153. init0(void)
  154. {
  155. Osenv *o;
  156. int i;
  157. char buf[2*KNAMELEN];
  158. up->nerrlab = 0;
  159. spllo();
  160. if(waserror())
  161. panic("init0: %r");
  162. /*
  163. * These are o.k. because rootinit is null.
  164. * Then early kproc's will have a root and dot.
  165. */
  166. o = up->env;
  167. o->pgrp->slash = namec("#/", Atodir, 0, 0);
  168. cnameclose(o->pgrp->slash->name);
  169. o->pgrp->slash->name = newcname("/");
  170. o->pgrp->dot = cclone(o->pgrp->slash);
  171. chandevinit();
  172. if(!waserror()){
  173. ksetenv("cputype", "386", 0);
  174. snprint(buf, sizeof(buf), "386 %s", conffile);
  175. ksetenv("terminal", buf, 0);
  176. for(i = 0; i < nconf; i++){
  177. if(confname[i][0] != '*')
  178. ksetenv(confname[i], confval[i], 0);
  179. ksetenv(confname[i], confval[i], 1);
  180. }
  181. poperror();
  182. }
  183. poperror();
  184. disinit("/osinit.dis");
  185. }
  186. void
  187. userinit(void)
  188. {
  189. Proc *p;
  190. Osenv *o;
  191. p = newproc();
  192. o = p->env;
  193. o->fgrp = newfgrp(nil);
  194. o->pgrp = newpgrp();
  195. kstrdup(&o->user, eve);
  196. strcpy(p->text, "interp");
  197. p->fpstate = FPINIT;
  198. fpoff();
  199. /*
  200. * Kernel Stack
  201. *
  202. * N.B. make sure there's
  203. * 4 bytes for gotolabel's return PC
  204. */
  205. p->sched.pc = (ulong)init0;
  206. p->sched.sp = (ulong)p->kstack+KSTACK-BY2WD;
  207. ready(p);
  208. }
  209. Conf conf;
  210. char*
  211. getconf(char *name)
  212. {
  213. int i;
  214. for(i = 0; i < nconf; i++)
  215. if(cistrcmp(confname[i], name) == 0)
  216. return confval[i];
  217. return 0;
  218. }
  219. void
  220. confinit(void)
  221. {
  222. char *p;
  223. int pcnt;
  224. ulong maxmem;
  225. if(p = getconf("*maxmem"))
  226. maxmem = strtoul(p, 0, 0);
  227. else
  228. maxmem = 0;
  229. if(p = getconf("*kernelpercent"))
  230. pcnt = 100 - strtol(p, 0, 0);
  231. else
  232. pcnt = 0;
  233. meminit(maxmem);
  234. conf.npage = conf.npage0 + conf.npage1;
  235. if(pcnt < 10)
  236. pcnt = 70;
  237. conf.ialloc = (((conf.npage*(100-pcnt))/100)/2)*BY2PG;
  238. conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
  239. }
  240. void
  241. poolsizeinit(void)
  242. {
  243. ulong nb;
  244. nb = conf.npage*BY2PG;
  245. poolsize(mainmem, (nb*main_pool_pcnt)/100, 0);
  246. poolsize(heapmem, (nb*heap_pool_pcnt)/100, 0);
  247. poolsize(imagmem, (nb*image_pool_pcnt)/100, 1);
  248. }
  249. static char *mathmsg[] =
  250. {
  251. "invalid operation",
  252. "denormalized operand",
  253. "division by zero",
  254. "numeric overflow",
  255. "numeric underflow",
  256. "precision loss",
  257. "stack",
  258. "error",
  259. };
  260. /*
  261. * math coprocessor error
  262. */
  263. void
  264. matherror(Ureg* ureg, void* arg)
  265. {
  266. ulong status;
  267. int i;
  268. char *msg;
  269. char note[ERRMAX];
  270. USED(arg);
  271. /*
  272. * a write cycle to port 0xF0 clears the interrupt latch attached
  273. * to the error# line from the 387
  274. */
  275. if(!(m->cpuiddx & 0x01))
  276. outb(0xF0, 0xFF);
  277. /*
  278. * save floating point state to check out error
  279. */
  280. FPsave(&up->fpsave.env);
  281. status = up->fpsave.env.status;
  282. msg = 0;
  283. for(i = 0; i < 8; i++)
  284. if((1<<i) & status){
  285. msg = mathmsg[i];
  286. sprint(note, "sys: fp: %s fppc=0x%lux", msg, up->fpsave.env.pc);
  287. error(note);
  288. break;
  289. }
  290. if(msg == 0){
  291. sprint(note, "sys: fp: unknown fppc=0x%lux", up->fpsave.env.pc);
  292. error(note);
  293. }
  294. if(ureg->pc & KZERO)
  295. panic("fp: status %lux fppc=0x%lux pc=0x%lux", status,
  296. up->fpsave.env.pc, ureg->pc);
  297. }
  298. /*
  299. * math coprocessor emulation fault
  300. */
  301. void
  302. mathemu(Ureg* ureg, void* arg)
  303. {
  304. USED(ureg, arg);
  305. switch(up->fpstate){
  306. case FPINIT:
  307. fpinit();
  308. up->fpstate = FPACTIVE;
  309. break;
  310. case FPINACTIVE:
  311. fprestore(&up->fpsave);
  312. up->fpstate = FPACTIVE;
  313. break;
  314. case FPACTIVE:
  315. panic("math emu");
  316. break;
  317. }
  318. }
  319. /*
  320. * math coprocessor segment overrun
  321. */
  322. void
  323. mathover(Ureg* ureg, void* arg)
  324. {
  325. USED(arg);
  326. print("sys: fp: math overrun pc 0x%lux pid %ld\n", ureg->pc, up->pid);
  327. pexit("math overrun", 0);
  328. }
  329. void
  330. mathinit(void)
  331. {
  332. trapenable(VectorCERR, matherror, 0, "matherror");
  333. if(X86FAMILY(m->cpuidax) == 3)
  334. intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror");
  335. trapenable(VectorCNA, mathemu, 0, "mathemu");
  336. trapenable(VectorCSO, mathover, 0, "mathover");
  337. }
  338. /*
  339. * Save the mach dependent part of the process state.
  340. */
  341. void
  342. procsave(Proc *p)
  343. {
  344. if(p->fpstate == FPACTIVE){
  345. if(p->state == Moribund)
  346. fpoff();
  347. else
  348. fpsave(&up->fpsave);
  349. p->fpstate = FPINACTIVE;
  350. }
  351. }
  352. void
  353. exit(int ispanic)
  354. {
  355. USED(ispanic);
  356. up = 0;
  357. print("exiting\n");
  358. /* Shutdown running devices */
  359. chandevshutdown();
  360. arch->reset();
  361. }
  362. void
  363. reboot(void)
  364. {
  365. exit(0);
  366. }
  367. int
  368. isaconfig(char *class, int ctlrno, ISAConf *isa)
  369. {
  370. char cc[32], *p;
  371. int i;
  372. snprint(cc, sizeof cc, "%s%d", class, ctlrno);
  373. p = getconf(cc);
  374. if(p == nil)
  375. return 0;
  376. isa->nopt = tokenize(p, isa->opt, NISAOPT);
  377. for(i = 0; i < isa->nopt; i++){
  378. p = isa->opt[i];
  379. if(cistrncmp(p, "type=", 5) == 0)
  380. isa->type = p + 5;
  381. else if(cistrncmp(p, "port=", 5) == 0)
  382. isa->port = strtoul(p+5, &p, 0);
  383. else if(cistrncmp(p, "irq=", 4) == 0)
  384. isa->irq = strtoul(p+4, &p, 0);
  385. else if(cistrncmp(p, "dma=", 4) == 0)
  386. isa->dma = strtoul(p+4, &p, 0);
  387. else if(cistrncmp(p, "mem=", 4) == 0)
  388. isa->mem = strtoul(p+4, &p, 0);
  389. else if(cistrncmp(p, "size=", 5) == 0)
  390. isa->size = strtoul(p+5, &p, 0);
  391. else if(cistrncmp(p, "freq=", 5) == 0)
  392. isa->freq = strtoul(p+5, &p, 0);
  393. }
  394. return 1;
  395. }
  396. /*
  397. * put the processor in the halt state if we've no processes to run.
  398. * an interrupt will get us going again.
  399. */
  400. void
  401. idlehands(void)
  402. {
  403. if(conf.nmach == 1)
  404. halt();
  405. }