520 lines · 9.3 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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;} voidcpuidprint(void){	print("cpu0: %s, rev 0x%lux, cpu hz %lld, bus hz %ld\n", 		cpuid(), getpvr()&0xffff, m->cpuhz, m->bushz);} voidmain(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 voidplan9iniinit(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;	}} voidinit0(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)));} voiduserinit(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);} voidexit(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 */voidprocsetup(Proc *p){	p->fpstate = FPinit;} voidprocrestore(Proc *p){	uvlong t; 	if(p->kp)		return;	cycles(&t);	p->pcycles -= t;} /* *  Save the mach dependent part of the process state. */voidprocsave(Proc *p){	uvlong t; 	cycles(&t);	p->pcycles += t;	if(p->fpstate == FPactive){		if(p->state != Moribund)			fpsave(&up->fpsave);		p->fpstate = FPinactive;	}} voidconfinit(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 intgetcfields(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;} intisaconfig(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;} intcistrcmp(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;} intcistrncmp(char *a, char *b, int n){	unsigned ac, bc;

Lines 1–500 of 520.