964 lines · 18.7 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	"ureg.h"#include	"init.h"#include	"pool.h"#include	"reboot.h"#include	"mp.h"#include	<tos.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 enum {	/* space for syscall args, return PC, top-of-stack struct */	Ustkheadroom	= sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),}; char bootdisk[KNAMELEN];Conf conf;char *confname[MAXCONF];char *confval[MAXCONF];int nconf;uchar *sp;	/* user stack of init proc */int delaylink;int idle_spin, idle_if_nproc; 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); voidfpsavealloc(void){	m->fpsavalign = mallocalign(sizeof(FPssestate), FPalign, 0, 0);	if (m->fpsavalign == nil)		panic("cpu%d: can't allocate fpsavalign", m->machno);} voidmain(void){	cgapost(0);	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();	fpsavealloc();	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();	cgapost(0xcd); 	pageinit();	i8253link();	swapinit();	userinit();	active.thunderbirdsarego = 1; 	cgapost(0x99);	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);	cgapost(0x9);	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 - Ustkheadroom; 	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){		snprint(buf, sizeof buf, "local!#f/fd%lddisk",			strtol(cp+2, 0, 0));		av[ac++] = pusharg(buf);	} else if(strncmp(cp, "sd", 2) == 0){		snprint(buf, sizeof 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 > (200*MB + conf.npage*sizeof(Page))/BY2PG){			kpages = (200*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 voidmathstate(ulong *stsp, ulong *pcp, ulong *ctlp){	ulong sts, fpc, ctl;	FPsave *f = &up->fpsave;

Lines 1–500 of 964.