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