869 lines · 16.6 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"ureg.h"#include	"init.h"#include	"pool.h"#include	"reboot.h"#include	"mp.h" enum {	Less_power_slower = 1,}; 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 char bootdisk[KNAMELEN];Conf conf;char *confname[MAXCONF];char *confval[MAXCONF];int nconf;uchar *sp;	/* user stack of init proc */int delaylink; static voidoptions(void){	long i, n;	char *cp, *line[MAXCONF], *p, *q; 	/*	 *  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 mmuinit0(void);extern void (*i8237alloc)(void); voidmain(void){	mach0init();	options();	ioinit();	i8250console();	quotefmtinstall();	screeninit(); 	print("\nPlan 9\n"); 	trapinit0();	mmuinit0(); 	kbdinit();	i8253init();	cpuidentify();	meminit();	confinit();	archinit();	xinit();	if(i8237alloc != nil)		i8237alloc();	trapinit();	printinit();	cpuidprint();	mmuinit();	if(arch->intrinit)	/* launches other processors on an mp */		arch->intrinit();	timersinit();	mathinit();	kbdenable();	if(arch->clockenable)		arch->clockenable();	procinit0();	initseg();	if(delaylink){		bootlinks();		pcimatch(0, 0, 0);	}else		links();	conf.monitor = 1;	chandevreset();	pageinit();	i8253link();	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 = 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); 	p->fpstate = FPinit;	fpoff(); 	/*	 * 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);	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));	segpage(s, pg);	v = tmpmap(pg);	memset(v, 0, BY2PG);	memmove(v, initcode, sizeof initcode);	tmpunmap(v); 	ready(p);} uchar *pusharg(char *p){	int n; 	n = strlen(p)+1;	sp -= n;	memmove(sp, p, n);	return sp;} voidbootargs(void *base){ 	int i, ac;	uchar *av[32];	uchar **lsp;	char *cp = BOOTLINE;	char buf[64]; 	sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD; 	ac = 0;	av[ac++] = pusharg("/386/9dos"); 	/* when boot is changed to only use rc, this code can go away */	cp[BOOTLINELEN-1] = 0;	buf[0] = 0;	if(strncmp(cp, "fd", 2) == 0){		sprint(buf, "local!#f/fd%lddisk", strtol(cp+2, 0, 0));		av[ac++] = pusharg(buf);	} else if(strncmp(cp, "sd", 2) == 0){		sprint(buf, "local!#S/sd%c%c/fs", *(cp+2), *(cp+3));		av[ac++] = pusharg(buf);	} else if(strncmp(cp, "ether", 5) == 0)		av[ac++] = pusharg("-n"); 	/* 4 byte word align stack */	sp = (uchar*)((ulong)sp & ~3); 	/* build argc, argv on stack */	sp -= (ac+1)*sizeof(sp);	lsp = (uchar**)sp;	for(i = 0; i < ac; i++)		*lsp++ = av[i] + ((USTKTOP - BY2PG) - (ulong)base);	*lsp = 0;	sp += (USTKTOP - BY2PG) - (ulong)base - sizeof(ulong);} 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("*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(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 = 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;	} 	/*	 * 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	 * (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;	}} static char* mathmsg[] ={	nil,	/* handled below */	"denormalized operand",	"division by zero",	"numeric overflow",	"numeric underflow",	"precision loss",}; static voidmathnote(void){	int i;	ulong status;	char *msg, note[ERRMAX]; 	status = up->fpsave.status; 	/*	 * Some attention should probably be paid here to the	 * exception masks and error summary.	 */	msg = "unknown exception";	for(i = 1; i <= 5; i++){		if(!((1<<i) & status))			continue;		msg = mathmsg[i];		break;	}	if(status & 0x01){		if(status & 0x40){			if(status & 0x200)				msg = "stack overflow";			else				msg = "stack underflow";		}else			msg = "invalid operation";	}	snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux",		msg, up->fpsave.pc, status);	postnote(up, 1, note, NDebug);}

Lines 1–500 of 869.