diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/ppc/main.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/ppc/main.c')
-rwxr-xr-x | sys/src/9/ppc/main.c | 511 |
1 files changed, 511 insertions, 0 deletions
diff --git a/sys/src/9/ppc/main.c b/sys/src/9/ppc/main.c new file mode 100755 index 000000000..380d6fd6f --- /dev/null +++ b/sys/src/9/ppc/main.c @@ -0,0 +1,511 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "init.h" +#include "pool.h" +#include "tos.h" + +#define MAXCONF 64 + +typedef struct Plan9ini Plan9ini; +struct Plan9ini +{ + char *name; + char *val; +}; + +char *plan9inistr; +Plan9ini plan9ini[MAXCONF]; +int nconf; + +Conf conf; +FPsave initfp; +Lock testlock; + +static void plan9iniinit(void); + +char * +cpuid(void) +{ + char *id; + + id = "unknown PowerPC"; + switch(m->cputype) { + case 8: + id = "PowerPC 750"; + break; + case 9: + id = "PowerPC 604e"; + break; + case 0x81: + id = "PowerPC 8260"; + break; + case 0x8081: + id = "PowerPC 826xA"; + break; + default: + break; + } + return id; +} + +void +cpuidprint(void) +{ + print("cpu0: %s, rev 0x%lux, cpu hz %lld, bus hz %ld\n", + cpuid(), getpvr()&0xffff, m->cpuhz, m->bushz); +} + +void +main(void) +{ + memset(edata, 0, (ulong)end-(ulong)edata); + conf.nmach = 1; + machinit(); + confinit(); + xinit(); + trapinit(); + mmuinit(); + plan9iniinit(); + hwintrinit(); + clockinit(); + timerinit(); + console(); + quotefmtinstall(); + printinit(); + cpuidprint(); + print("\nPlan 9 from Bell Labs\n"); + procinit0(); + initseg(); + timersinit(); + links(); + chandevreset(); + pageinit(); + swapinit(); + sharedseginit(); + fpsave(&initfp); + initfp.fpscr = 0; + userinit(); + schedinit(); +} + +char* +getconf(char *name) +{ + int i; + + for(i = 0; i < nconf; i++) + if(cistrcmp(name, plan9ini[i].name) == 0) + return plan9ini[i].val; + return nil; +} + +static void +plan9iniinit(void) +{ + long i; + int c; + char *cp, line[MAXCONF], *p, *q; + + /* + * parse configuration args from dos file plan9.ini + */ + + cp = plan9inistr; + for(i = 0; i < MAXCONF; i++){ + /* + * Strip out '\r', change '\t' -> ' ', test for 0xff which is end of file + */ + p = line; + for(q = cp; c = (uchar)*q; q++){ + if(c == '\r') + continue; + if(c == '\t') + c = ' '; + if(c == 0xff || c == '\n') + break; + *p++ = c; + } + *p = 0; + if (*line == 0) + break; + if(*line != '#' && (cp = strchr(line, '='))){ + *cp++ = '\0'; + kstrdup(&plan9ini[nconf].name, line); + kstrdup(&plan9ini[nconf].val, cp); + nconf++; + } + if (c == 0xff) + break; + + cp = q + 1; + } +} + +void +init0(void) +{ +// char **p, *q, name[KNAMELEN]; + int i; + char buf[2*KNAMELEN]; + + up->nerrlab = 0; + spllo(); + + /* + * These are o.k. because rootinit is null. + * Then early kproc's will have a root and dot. + */ + up->slash = namec("#/", Atodir, 0, 0); + pathclose(up->slash->path); + up->slash->path = newpath("/"); + up->dot = cclone(up->slash); + + chandevinit(); + + if(!waserror()){ + snprint(buf, sizeof(buf), "power %s mtx", conffile); + ksetenv("terminal", buf, 0); + ksetenv("cputype", "power", 0); + if(cpuserver) + ksetenv("service", "cpu", 0); + else + ksetenv("service", "terminal", 0); + + for(i = 0; i < nconf; i++){ + if(plan9ini[i].name[0] != '*') + ksetenv(plan9ini[i].name, plan9ini[i].val, 0); + ksetenv(plan9ini[i].name, plan9ini[i].val, 1); + } + poperror(); + } + kproc("alarm", alarmkproc, 0); + kproc("mmusweep", mmusweep, 0); + touser((void*)(USTKTOP-sizeof(Tos))); +} + +void +userinit(void) +{ + Proc *p; + Segment *s; + KMap *k; + Page *pg; + + p = newproc(); + p->pgrp = newpgrp(); + p->egrp = smalloc(sizeof(Egrp)); + p->egrp->ref = 1; + p->fgrp = dupfgrp(nil); + p->rgrp = newrgrp(); + p->procmode = 0640; + + kstrdup(&eve, ""); + kstrdup(&p->text, "*init*"); + kstrdup(&p->user, eve); + + p->fpstate = FPinit; + + /* + * Stack + * + * N.B. The -12 for the stack pointer is important. + * 4 bytes for gotolabel's return PC + */ + p->sched.pc = (ulong)init0; + p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD); + + /* + * User Stack + */ + s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG); + p->seg[SSEG] = s; + pg = newpage(1, 0, USTKTOP-BY2PG); + segpage(s, pg); + + /* + * Text + */ + s = newseg(SG_TEXT, UTZERO, 1); + s->flushme++; + p->seg[TSEG] = s; + pg = newpage(1, 0, UTZERO); + memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl)); + segpage(s, pg); + k = kmap(s->map[0]->pages[0]); + memmove((ulong*)VA(k), initcode, sizeof initcode); + kunmap(k); + + ready(p); +} + +void +exit(int ispanic) +{ + int ms, once; + + lock(&active); + if(ispanic) + active.ispanic = ispanic; + else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0) + active.ispanic = 0; + once = active.machs & (1<<m->machno); + active.machs &= ~(1<<m->machno); + active.exiting = 1; + unlock(&active); + + if(once) + print("cpu%d: exiting\n", m->machno); + spllo(); + for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){ + delay(TK2MS(2)); + if(active.machs == 0 && consactive() == 0) + break; + } + + if(active.ispanic && m->machno == 0){ + if(cpuserver) + delay(10000); + else if(conf.monitor) + for(;;); + } + else + delay(1000); + +} + +/* + * set up floating point for a new process + */ +void +procsetup(Proc *p) +{ + p->fpstate = FPinit; +} + +void +procrestore(Proc *p) +{ + uvlong t; + + if(p->kp) + return; + cycles(&t); + p->pcycles -= t; +} + +/* + * Save the mach dependent part of the process state. + */ +void +procsave(Proc *p) +{ + uvlong t; + + cycles(&t); + p->pcycles += t; + if(p->fpstate == FPactive){ + if(p->state != Moribund) + fpsave(&up->fpsave); + p->fpstate = FPinactive; + } +} + +void +confinit(void) +{ + char *p; + int userpcnt; + ulong pa, kpages; + /* passed in from ROM monitor: */ + + if(p = getconf("*kernelpercent")) + userpcnt = 100 - strtol(p, 0, 0); + else + userpcnt = 0; + + pa = PGROUND(PADDR(end)); + + /* Blast Board specific */ + conf.mem[0].npage = (MEM1SIZE - pa)/BY2PG; + conf.mem[0].base = pa; + + conf.mem[1].npage = MEM2SIZE/BY2PG; + conf.mem[1].base = MEM2BASE; + + conf.npage = conf.mem[0].npage + conf.mem[1].npage; + + conf.nmach = 1; + conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5; + if(cpuserver) + conf.nproc *= 3; + if(conf.nproc > 2000) + conf.nproc = 2000; + conf.nimage = 200; + conf.nswap = conf.nproc*80; + conf.nswppo = 4096; + conf.copymode = 0; /* copy on write */ + + if(cpuserver) { + if(userpcnt < 10) + userpcnt = 70; + kpages = conf.npage - (conf.npage*userpcnt)/100; + + /* + * Hack for the big boys. Only good while physmem < 4GB. + * Give the kernel a max. of 16MB + enough to allocate the + * page pool. + * This is an overestimate as conf.upages < conf.npages. + * The patch of nimage is a band-aid, scanning the whole + * page list in imagereclaim just takes too long. + */ + if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){ + kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG; + conf.nimage = 2000; + kpages += (conf.nproc*KSTACK)/BY2PG; + } + } else { + if(userpcnt < 10) { + if(conf.npage*BY2PG < 16*MB) + userpcnt = 40; + else + userpcnt = 60; + } + kpages = conf.npage - (conf.npage*userpcnt)/100; + + /* + * Make sure terminals with low memory get at least + * 4MB on the first Image chunk allocation. + */ + if(conf.npage*BY2PG < 16*MB) + imagmem->minarena = 4*1024*1024; + } + conf.upages = conf.npage - kpages; + conf.ialloc = (kpages/2)*BY2PG; + + /* + * Guess how much is taken by the large permanent + * datastructures. Mntcache and Mntrpc are not accounted for + * (probably ~300KB). + */ + kpages *= BY2PG; + kpages -= conf.upages*sizeof(Page) + + conf.nproc*sizeof(Proc) + + conf.nimage*sizeof(Image) + + conf.nswap + + conf.nswppo*sizeof(Page); + mainmem->maxsize = kpages; + if(!cpuserver){ + /* + * give terminals lots of image memory, too; the dynamic + * allocation will balance the load properly, hopefully. + * be careful with 32-bit overflow. + */ + imagmem->maxsize = kpages; + } + +// conf.monitor = 1; /* BUG */ +} + +static int +getcfields(char* lp, char** fields, int n, char* sep) +{ + int i; + + for(i = 0; lp && *lp && i < n; i++){ + while(*lp && strchr(sep, *lp) != 0) + *lp++ = 0; + if(*lp == 0) + break; + fields[i] = lp; + while(*lp && strchr(sep, *lp) == 0){ + if(*lp == '\\' && *(lp+1) == '\n') + *lp++ = ' '; + lp++; + } + } + + return i; +} + +int +isaconfig(char *class, int ctlrno, ISAConf *isa) +{ + int i; + char cc[KNAMELEN], *p; + + sprint(cc, "%s%d", class, ctlrno); + + p = getconf(cc); + if(p == 0) + return 0; + isa->nopt = tokenize(p, isa->opt, NISAOPT); + for(i = 0; i < isa->nopt; i++){ + p = isa->opt[i]; + if(cistrncmp(p, "type=", 5) == 0) + isa->type = p + 5; + else if(cistrncmp(p, "port=", 5) == 0) + isa->port = strtoul(p+5, &p, 0); + else if(cistrncmp(p, "irq=", 4) == 0) + isa->irq = strtoul(p+4, &p, 0); + else if(cistrncmp(p, "dma=", 4) == 0) + isa->dma = strtoul(p+4, &p, 0); + else if(cistrncmp(p, "mem=", 4) == 0) + isa->mem = strtoul(p+4, &p, 0); + else if(cistrncmp(p, "size=", 5) == 0) + isa->size = strtoul(p+5, &p, 0); + else if(cistrncmp(p, "freq=", 5) == 0) + isa->freq = strtoul(p+5, &p, 0); + } + return 1; +} + +int +cistrcmp(char *a, char *b) +{ + int ac, bc; + + for(;;){ + ac = *a++; + bc = *b++; + + if(ac >= 'A' && ac <= 'Z') + ac = 'a' + (ac - 'A'); + if(bc >= 'A' && bc <= 'Z') + bc = 'a' + (bc - 'A'); + ac -= bc; + if(ac) + return ac; + if(bc == 0) + break; + } + return 0; +} + +int +cistrncmp(char *a, char *b, int n) +{ + unsigned ac, bc; + + while(n > 0){ + ac = *a++; + bc = *b++; + n--; + + if(ac >= 'A' && ac <= 'Z') + ac = 'a' + (ac - 'A'); + if(bc >= 'A' && bc <= 'Z') + bc = 'a' + (bc - 'A'); + + ac -= bc; + if(ac) + return ac; + if(bc == 0) + break; + } + + return 0; +} |