944 lines · 18.4 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"tos.h"#include	"ureg.h"#include	"init.h"#include	"pool.h"#include	"reboot.h" Mach *m; /* * Where configuration info is left for the loaded programme. * This will turn into a structure as more is done by the boot loader * (e.g. why parse the .ini file twice?). * There are 3584 bytes available at CONFADDR. */#define BOOTLINE	((char*)CONFADDR)#define BOOTLINELEN	64#define BOOTARGS	((char*)(CONFADDR+BOOTLINELEN))#define	BOOTARGSLEN	(4096-0x200-BOOTLINELEN)#define	MAXCONF		64 Conf conf;char *confname[MAXCONF];char *confval[MAXCONF];int nconf;char *sp;	/* user stack of init proc */int delaylink;int idle_spin; static voidmultibootargs(void){	char *cp, *ep;	ulong *m, l; 	extern ulong *multiboot; 	if(multiboot == nil)		return; 	/* command line */	if((multiboot[0] & (1<<2)) != 0)		strncpy(BOOTLINE, KADDR(multiboot[4]), BOOTLINELEN-1); 	cp = BOOTARGS;	ep = cp + BOOTARGSLEN-1; 	/* memory map */	if((multiboot[0] & (1<<6)) != 0 && (l = multiboot[11]) >= 24){		cp = seprint(cp, ep, "*e820=");		m = KADDR(multiboot[12]);		while(m[0] >= 20 && m[0] <= l-4){			uvlong base, size;			m++;			base = ((uvlong)m[0] | (uvlong)m[1]<<32);			size = ((uvlong)m[2] | (uvlong)m[3]<<32);			cp = seprint(cp, ep, "%.1lux %.16llux %.16llux ",				m[4] & 0xF, base, base+size);			l -= m[-1]+4;			m = (ulong*)((ulong)m + m[-1]);		}		cp[-1] = '\n';	} 	/* plan9.ini passed as the first module */	if((multiboot[0] & (1<<3)) != 0 && multiboot[5] > 0){		m = KADDR(multiboot[6]);		l = m[1] - m[0];		m = KADDR(m[0]);		if(cp+l > ep)			l = ep - cp;		memmove(cp, m, l);		cp += l;	}	*cp = 0;} static voidoptions(void){	long i, n;	char *cp, *line[MAXCONF], *p, *q; 	multibootargs(); 	/*	 *  parse configuration args from dos file plan9.ini	 */	cp = BOOTARGS;	/* where b.com leaves its config */	cp[BOOTARGSLEN-1] = 0; 	/*	 * Strip out '\r', change '\t' -> ' '.	 */	p = cp;	for(q = cp; *q; q++){		if(*q == '\r')			continue;		if(*q == '\t')			*q = ' ';		*p++ = *q;	}	*p = 0; 	n = getfields(cp, line, MAXCONF, 1, "\n");	for(i = 0; i < n; i++){		if(*line[i] == '#')			continue;		cp = strchr(line[i], '=');		if(cp == nil)			continue;		*cp++ = '\0';		confname[nconf] = line[i];		confval[nconf] = cp;		nconf++;	}} extern void (*i8237alloc)(void);extern void bootscreeninit(void); voidmain(void){	mach0init();	options();	ioinit();	i8250console();	quotefmtinstall();	screeninit(); 	print("\nPlan 9\n"); 	trapinit0();	i8253init();	cpuidentify();	meminit();	confinit();	xinit();	archinit();	bootscreeninit();	if(i8237alloc != nil)		i8237alloc();	trapinit();	printinit();	cpuidprint();	mmuinit();	if(arch->intrinit)	/* launches other processors on an mp */		arch->intrinit();	timersinit();	mathinit();	if(arch->clockenable)		arch->clockenable();	procinit0();	initseg();	if(delaylink){		bootlinks();		pcimatch(0, 0, 0);	}else		links();	chandevreset();	pageinit();	swapinit();	userinit();	active.thunderbirdsarego = 1;	schedinit();} voidmach0init(void){	conf.nmach = 1;	MACHP(0) = (Mach*)CPU0MACH;	m->pdb = (ulong*)CPU0PDB;	m->gdt = (Segdesc*)CPU0GDT; 	machinit(); 	active.machs[0] = 1;	active.exiting = 0;} voidmachinit(void){	int machno;	ulong *pdb;	Segdesc *gdt; 	machno = m->machno;	pdb = m->pdb;	gdt = m->gdt;	memset(m, 0, sizeof(Mach));	m->machno = machno;	m->pdb = pdb;	m->gdt = gdt;	m->perf.period = 1; 	/*	 * For polled uart output at boot, need	 * a default delay constant. 100000 should	 * be enough for a while. Cpuidentify will	 * calculate the real value later.	 */	m->loopconst = 100000;} voidinit0(void){	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), "%s %s", arch->id, conffile);		ksetenv("terminal", buf, 0);		ksetenv("cputype", "386", 0);		if(cpuserver)			ksetenv("service", "cpu", 0);		else			ksetenv("service", "terminal", 0);		for(i = 0; i < nconf; i++){			if(confname[i][0] != '*')				ksetenv(confname[i], confval[i], 0);			ksetenv(confname[i], confval[i], 1);		}		poperror();	}	kproc("alarm", alarmkproc, 0);	touser(sp);} voiduserinit(void){	void *v;	Proc *p;	Segment *s;	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); 	procsetup(p); 	/*	 * Kernel Stack	 *	 * N.B. make sure there's enough space for syscall to check	 *	for valid args and 	 *	4 bytes for gotolabel's return PC	 */	p->sched.pc = (ulong)init0;	p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD); 	/*	 * User Stack	 *	 * N.B. cannot call newpage() with clear=1, because pc kmap	 * requires up != nil.  use tmpmap instead.	 */	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);	p->seg[SSEG] = s;	pg = newpage(0, 0, USTKTOP-BY2PG);	v = tmpmap(pg);	memset(v, 0, BY2PG);	segpage(s, pg);	bootargs(v);	tmpunmap(v); 	/*	 * Text	 */	s = newseg(SG_TEXT, UTZERO, 1);	s->flushme++;	p->seg[TSEG] = s;	pg = newpage(0, 0, UTZERO);	pg->txtflush = ~0;	segpage(s, pg);	v = tmpmap(pg);	memset(v, 0, BY2PG);	memmove(v, initcode, sizeof initcode);	tmpunmap(v); 	ready(p);} voidbootargs(void *base){	char *argv[8];	int i, argc; #define UA(ka)	((char*)(ka) + ((uintptr)(USTKTOP - BY2PG) - (uintptr)base))	sp = (char*)base + BY2PG - sizeof(Tos); 	/* push boot command line onto the stack */	sp -= BOOTLINELEN;	sp[BOOTLINELEN-1] = '\0';	memmove(sp, BOOTLINE, BOOTLINELEN-1); 	/* parse boot command line */	argc = tokenize(sp, argv, nelem(argv));	if(argc < 1){		strcpy(sp, "boot");		argc = 0;		argv[argc++] = sp;	} 	/* 4 byte word align stack */	sp = (char*)((uintptr)sp & ~3); 	/* build argv on stack */	sp -= (argc+1)*BY2WD;	for(i=0; i<argc; i++)		((char**)sp)[i] = UA(argv[i]);	((char**)sp)[i] = nil; 	sp = UA(sp);#undef UA	sp -= BY2WD;} char*getconf(char *name){	int i; 	for(i = 0; i < nconf; i++)		if(cistrcmp(confname[i], name) == 0)			return confval[i];	return 0;} static voidwriteconf(void){	char *p, *q;	int n; 	p = getconfenv(); 	if(waserror()) {		free(p);		nexterror();	} 	/* convert to name=value\n format */	for(q=p; *q; q++) {		q += strlen(q);		*q = '=';		q += strlen(q);		*q = '\n';	}	n = q - p + 1;	if(n >= BOOTARGSLEN)		error("kernel configuration too large");	memset(BOOTLINE, 0, BOOTLINELEN);	memmove(BOOTARGS, p, n);	poperror();	free(p);} voidconfinit(void){	char *p;	int i, userpcnt;	ulong kpages; 	if(p = getconf("service")){		if(strcmp(p, "cpu") == 0)			cpuserver = 1;		else if(strcmp(p,"terminal") == 0)			cpuserver = 0;	} 	if(p = getconf("*kernelpercent"))		userpcnt = 100 - strtol(p, 0, 0);	else		userpcnt = 0; 	conf.npage = 0;	for(i=0; i<nelem(conf.mem); i++)		conf.npage += conf.mem[i].npage; 	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; 	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 fixed max + 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(getconf("*imagemaxmb") == 0)		if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){			kpages = (64*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 = 50;			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*MB;	} 	/*	 * can't go past the end of virtual memory	 * (ulong)-KZERO is 2^32 - KZERO	 */	if(kpages > ((ulong)-KZERO)/BY2PG)		kpages = ((ulong)-KZERO)/BY2PG; 	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.	 */	kpages *= BY2PG;	kpages -= conf.upages*sizeof(Page)		+ conf.nproc*sizeof(Proc)		+ conf.nimage*sizeof(Image)		+ conf.nswap		+ conf.nswppo*sizeof(Page*);	mainmem->maxsize = kpages; 	/*	 * the dynamic allocation will balance the load properly,	 * hopefully. be careful with 32-bit overflow.	 */	imagmem->maxsize = kpages - (kpages/10);	if(p = getconf("*imagemaxmb")){		imagmem->maxsize = strtol(p, nil, 0)*MB;		if(imagmem->maxsize > mainmem->maxsize)			imagmem->maxsize = mainmem->maxsize;	}} /* * we keep FPsave structure in sse format emulating FXSAVE / FXRSTOR * instructions for legacy x87 fpu. * * Note that fpx87restore() and fpxsserestore() do modify the FPsave * data structure for conversion / realignment shuffeling. this means

Lines 1–500 of 944.