2 #include "../port/lib.h"
9 #include "/sys/src/boot/alphapc/conf.h"
12 char argbuf[128]; /* arguments passed to initcode and /boot */
18 /* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
19 uvlong initfpcr = (1LL<62)|(1LL<61)|(1LL<60)|(2LL<<58)|(1LL<48);
21 char bootargs[BOOTARGSLEN];
22 char *confname[MAXCONF];
23 char *confval[MAXCONF];
30 char *cp, *line[MAXCONF], *p, *q;
33 strncpy(cp, bootconf->bootargs, BOOTARGSLEN);
34 cp[BOOTARGSLEN-1] = 0;
35 /* can't print in this routine, see below in main() */
38 * Strip out '\r', change '\t' -> ' '.
50 n = getfields(cp, line, MAXCONF, 1, "\n");
51 for(i = 0; i < n; i++){
54 cp = strchr(line[i], '=');
58 confname[nconf] = line[i];
70 print("dumpopts: found /alpha/conf options at %#p\n",
72 for(i = 0; i < nconf; i++)
73 print("dumpopts: read %s=%s\n", confname[i], confval[i]);
76 extern void (*i8237alloc)(void);
81 hwrpb = (Hwrpb*)0x10000000;
82 hwrpb = (Hwrpb*)(KZERO|hwrpb->phys);
100 /* it's now safe to print */
101 /* dumpopts(); /* DEBUG */
118 initfp.fpstatus = 0x68028000;
123 /* cpu->state bits */
125 Cpubootinprog = 1, /* boot in progress */
126 Cpucanrestart = 2, /* restart possible */
127 Cpuavail = 4, /* processor available */
128 Cpuexists = 8, /* processor present */
129 Cpuuserhalted = 0x10, /* user halted */
130 Cpuctxtokay = 0x20, /* context valid */
131 Cpupalokay = 0x40, /* PALcode valid */
132 Cpupalmemokay = 0x80, /* PALcode memory valid */
133 Cpupalloaded = 0x100, /* PALcode loaded */
134 Cpuhaltmask = 0xff0000, /* halt request mask */
136 Cpuhaltsaveexit = 0x10000,
137 Cpuhaltcoldboot = 0x20000,
138 Cpuhaltwarmboot = 0x30000,
139 Cpuhaltstayhalted = 0x40000,
140 Cpumustbezero = 0xffffffffff000000ULL, /* 24:63 -- must be zero */
144 * initialize a processor's mach structure. each processor does this
155 memset(m, 0, sizeof(Mach));
161 cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff + n*hwrpb->cpulen);
162 cpu->state &= ~Cpubootinprog;
164 cpu->state |= Cpuhaltstayhalted;
171 char buf[2*KNAMELEN];
178 * These are o.k. because rootinit is null.
179 * Then early kproc's will have a root and dot.
181 up->slash = namec("#/", Atodir, 0, 0);
182 pathclose(up->slash->path);
183 up->slash->path = newpath("/");
184 up->dot = cclone(up->slash);
189 snprint(buf, sizeof(buf), "alpha %s alphapc", conffile);
190 ksetenv("terminal", buf, 0);
191 ksetenv("cputype", "alpha", 0);
193 ksetenv("service", "cpu", 0);
195 ksetenv("service", "terminal", 0);
196 for(i = 0; i < nconf; i++)
198 if(confname[i][0] != '*')
199 ksetenv(confname[i], confval[i], 0);
200 ksetenv(confname[i], confval[i], 1);
205 kproc("alarm", alarmkproc, 0);
206 touser((uchar*)(USTKTOP - sizeof(argbuf)));
220 p->egrp = smalloc(sizeof(Egrp));
222 p->fgrp = dupfgrp(nil);
227 kstrdup(&p->text, "*init*");
228 kstrdup(&p->user, eve);
235 p->sched.pc = (ulong)init0;
236 p->sched.sp = (ulong)p->kstack+KSTACK-MAXSYSARG*BY2WD;
238 * User Stack, pass input arguments to boot process
240 s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
242 pg = newpage(1, 0, USTKTOP-BY2PG);
245 for(av = (char**)argbuf; *av; av++)
246 *av += (USTKTOP - sizeof(argbuf)) - (ulong)argbuf;
248 memmove((uchar*)VA(k) + BY2PG - sizeof(argbuf), argbuf, sizeof argbuf);
254 s = newseg(SG_TEXT, UTZERO, 1);
257 pg = newpage(1, 0, UTZERO);
258 memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
260 k = kmap(s->map[0]->pages[0]);
261 memmove((uchar*)VA(k), initcode, sizeof initcode);
282 if(p->fpstate == FPactive){
283 if(p->state == Moribund)
286 savefpregs(&up->fpsave);
287 p->fpstate = FPinactive;
291 * Switch to the prototype page tables for this processor.
292 * While this processor is in the scheduler, the process could run
293 * on another processor and exit, returning the page tables to
294 * the free list where they could be reallocated and overwritten.
295 * When this processor eventually has to get an entry from the
296 * trashed page tables it will crash.
304 int n = 0; // cpu id of primary cpu, not just m->machno
305 Hwcpu *cpu = (Hwcpu*)((ulong)hwrpb + hwrpb->cpuoff + n*hwrpb->cpulen);
307 cpu->state &= ~(Cpucanrestart | Cpuhaltmask);
308 cpu->state |= (halt? Cpuhaltstayhalted: Cpuhaltwarmboot);
313 shutdown(int ispanic)
319 active.ispanic = ispanic;
320 else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
322 once = active.machs & (1<<m->machno);
323 active.machs &= ~(1<<m->machno);
328 print("cpu%d: exiting\n", m->machno);
330 for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
332 if(active.machs == 0 && consactive() == 0)
336 if(active.ispanic && m->machno == 0) {
348 reboot(void *entry, void *code, ulong size)
350 // writeconf(); // pass kernel environment to next kernel
354 * should be the only processor running now
356 print("shutting down...\n");
361 /* turn off buffered serial console */
364 /* shutdown devices */
371 * Modify the machine page table to directly map the low 4MB of memory
372 * This allows the reboot code to turn off the page mapping
375 pdb[PDX(0)] = pdb[PDX(KZERO)];
376 mmuflushtlb(PADDR(pdb));
378 /* setup reboot trampoline function */
380 void (*f)(ulong, ulong, ulong) = (void*)REBOOTADDR;
382 memmove(f, rebootcode, sizeof(rebootcode));
384 USED(entry, code, size);
387 print("rebooting...\n");
389 /* off we go - never to return */
390 (*f)(PADDR(entry), PADDR(code), size);
393 setupboot(0); // reboot, don't halt
401 active.machs &= ~(1<<m->machno);
406 print("cpu %d exiting\n", m->machno);
412 delay(1000); /* give serial fifo time to finish flushing */
413 if (getconf("*debug") != nil) {
415 delay(60*1000); /* give us time to read the screen */
419 setupboot(1); // set up to halt
425 // shutdown(ispanic);
435 extern void _main(void);
439 if(p = getconf("*kernelpercent"))
440 userpcnt = 100 - strtol(p, 0, 0);
445 * The console firmware divides memory into 1 or more banks.
446 * FInd the bank with the kernel in it.
449 eb = b+bootconf->nbank;
450 ktop = PGROUND((ulong)end);
453 if(b->min < ktop && ktop < b->max)
461 * Split the bank of memory into 2 banks to fool the allocator into
462 * allocating low memory pages from bank 0 for any peripherals
463 * which only have a 24bit address counter.
465 conf.mem[0].npage = (8*1024*1024)/BY2PG;
466 conf.mem[0].base = 0;
468 conf.mem[1].npage = (b->max-8*1024*1024)/BY2PG;
469 conf.mem[1].base = 8*1024*1024;
471 conf.npage = conf.mem[0].npage+conf.mem[1].npage;
472 conf.upages = (conf.npage*70)/100;
474 conf.mem[0].npage -= ktop/BY2PG;
475 conf.mem[0].base += ktop;
476 conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
479 * Fix up the bank we found to be the remnant, below the kernel.
480 * This, and the other banks, will be passed to xhole() later.
481 * BUG: conf.upages needs to be adjusted, but how? In practice,
482 * we only have 1 bank, and the remnant is small.
484 b->max = (uvlong)_main & ~(BY2PG-1);
487 conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
490 if(conf.nproc > 2000)
493 conf.nswap = conf.nproc*80;
495 conf.copymode = 0; /* copy on write */
500 kpages = conf.npage - (conf.npage*userpcnt)/100;
503 * Hack for the big boys. Only good while physmem < 4GB.
504 * Give the kernel a max. of 16MB + enough to allocate the
506 * This is an overestimate as conf.upages < conf.npages.
507 * The patch of nimage is a band-aid, scanning the whole
508 * page list in imagereclaim just takes too long.
510 if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
511 kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
513 kpages += (conf.nproc*KSTACK)/BY2PG;
517 if(conf.npage*BY2PG < 16*MB)
522 kpages = conf.npage - (conf.npage*userpcnt)/100;
525 * Make sure terminals with low memory get at least
526 * 4MB on the first Image chunk allocation.
528 if(conf.npage*BY2PG < 16*MB)
529 imagmem->minarena = 4*1024*1024;
531 conf.upages = conf.npage - kpages;
532 conf.ialloc = (kpages/2)*BY2PG;
535 * Guess how much is taken by the large permanent
536 * datastructures. Mntcache and Mntrpc are not accounted for
540 kpages -= conf.upages*sizeof(Page)
541 + conf.nproc*sizeof(Proc)
542 + conf.nimage*sizeof(Image)
544 + conf.nswppo*sizeof(Page*);
545 mainmem->maxsize = kpages;
548 * give terminals lots of image memory, too; the dynamic
549 * allocation will balance the load properly, hopefully.
550 * be careful with 32-bit overflow.
552 imagmem->maxsize = kpages;
555 // conf.monitor = 1; /* BUG */
564 eb = b+bootconf->nbank;
566 if(b->min < (1LL<<32) && b->max < (1LL<<32))
567 xhole(b->min, b->max-b->min);
591 sp = argbuf + sizeof(argbuf);
592 *av++ = pusharg("boot");
601 for(n = 0; n < nconf; n++)
602 if(cistrcmp(confname[n], name) == 0) {
609 isaconfig(char *class, int ctlrno, ISAConf *isa)
614 snprint(cc, sizeof cc, "%s%d", class, ctlrno);
615 for(n = 0; n < nconf; n++){
616 if(cistrcmp(confname[n], cc) != 0)
618 isa->nopt = tokenize(confval[n], isa->opt, NISAOPT);
619 for(i = 0; i < isa->nopt; i++){
621 if(cistrncmp(p, "type=", 5) == 0)
623 else if(cistrncmp(p, "port=", 5) == 0)
624 isa->port = strtoul(p+5, &p, 0);
625 else if(cistrncmp(p, "irq=", 4) == 0)
626 isa->irq = strtoul(p+4, &p, 0);
627 else if(cistrncmp(p, "dma=", 4) == 0)
628 isa->dma = strtoul(p+4, &p, 0);
629 else if(cistrncmp(p, "mem=", 4) == 0)
630 isa->mem = strtoul(p+4, &p, 0);
631 else if(cistrncmp(p, "size=", 5) == 0)
632 isa->size = strtoul(p+5, &p, 0);
633 else if(cistrncmp(p, "freq=", 5) == 0)
634 isa->freq = strtoul(p+5, &p, 0);
642 cistrcmp(char *a, char *b)
650 if(ac >= 'A' && ac <= 'Z')
651 ac = 'a' + (ac - 'A');
652 if(bc >= 'A' && bc <= 'Z')
653 bc = 'a' + (bc - 'A');
664 cistrncmp(char *a, char *b, int n)
673 if(ac >= 'A' && ac <= 'Z')
674 ac = 'a' + (ac - 'A');
675 if(bc >= 'A' && bc <= 'Z')
676 bc = 'a' + (bc - 'A');
689 getcfields(char* lp, char** fields, int n, char* sep)
693 for(i = 0; lp && *lp && i < n; i++){
694 while(*lp && strchr(sep, *lp) != 0)
699 while(*lp && strchr(sep, *lp) == 0){
700 if(*lp == '\\' && *(lp+1) == '\n')