636 lines · 12.4 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	"../ip/ip.h"#include	<tos.h>#include	<bootexec.h>#include	"reboot.h" enum {	/* space for syscall args, return PC, top-of-stack struct */	Stkheadroom	= sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),}; typedef struct mipsexec Mipsexec; /* * Option arguments from the command line. * oargv[0] is the boot file. */static int oargc;static char* oargv[20];static char oargb[128];static int oargblen; static uintptr sp;		/* XXX - must go - user stack of init proc */ /* * software tlb simulation */static Softtlb stlb[MAXMACH][STLBSIZE]; Conf	conf;FPsave	initfp; int normalprint; char *getconf(char *){	return nil;	/* stub */} static voidoptionsinit(char* s){	strecpy(oargb, oargb+sizeof(oargb), s); 	oargblen = strlen(oargb);	oargc = tokenize(oargb, oargv, nelem(oargv)-1);	oargv[oargc] = nil;} static voidprcpuid(void){	ulong cpuid, cfg1;	char *cpu; 	cpuid = prid();	if (((cpuid>>16) & MASK(8)) == 0)		/* vendor */		cpu = "old mips";	else if (((cpuid>>16) & MASK(8)) == 1)		switch ((cpuid>>8) & MASK(8)) {		/* processor */		case 0x93:			cpu = "mips 24k";			break;		case 0x96:			cpu = "mips 24ke";			break;		default:			cpu = "mips";			break;		}	else		cpu = "other mips";	delay(20);	print("cpu%d: %ldMHz %s %se v%ld.%ld rev %ld, ",		m->machno, m->hz / Mhz, cpu, getconfig() & (1<<15)? "b": "l",		(cpuid>>5) & MASK(3), (cpuid>>2) & MASK(3), cpuid & MASK(2));	delay(200);	cfg1 = getconfig1();	print("%s fpu\n", (cfg1 & 1? "has": "no"));	print("cpu%d: %ld tlb entries, using %dK pages\n", m->machno,		((cfg1>>25) & MASK(6)) + 1, BY2PG/1024);	delay(50);	print("cpu%d: l1 i cache: %d sets 4 ways 32 bytes/line\n", m->machno,		64 << ((cfg1>>22) & MASK(3)));	delay(50);	print("cpu%d: l1 d cache: %d sets 4 ways 32 bytes/line\n", m->machno,		64 << ((cfg1>>13) & MASK(3)));	delay(500);	if (0)		print("cpu%d: cycle counter res = %ld\n",			m->machno, gethwreg3());} static voidfmtinit(void){	printinit();	quotefmtinstall();	/* ipreset installs these when chandevreset runs */	fmtinstall('i', eipfmt);	fmtinstall('I', eipfmt);	fmtinstall('E', eipfmt);	fmtinstall('V', eipfmt);	fmtinstall('M', eipfmt);} static intckpagemask(ulong mask, ulong size){	int s;	ulong pm; 	s = splhi();	setpagemask(mask);	pm = getpagemask();	splx(s);	if(pm != mask){		iprint("page size %ldK not supported on this cpu; "			"mask %#lux read back as %#lux\n", size/1024, mask, pm);		return -1;	}	return 0;} /* called from rebootcmd() */intparsemipsboothdr(Chan *c, ulong magic, Execvals *evp){	long extra;	Mipsexec me; 	/*	 * BOOT_MAGIC is sometimes defined like this:	 * #define BOOT_MAGIC	(0x160<<16) || magic == ((0x160<<16)|3)	 * so we can only use it in a fairly stylized manner.	 */	if(magic == BOOT_MAGIC) {		c->offset = 0;			/* back up */		readn(c, &me, sizeof me);		/* if binary is -H1, read an extra long */		if (l2be(me.amagic) == 0407 && me.nscns == 0)			readn(c, &extra, sizeof extra);		evp->entry = l2be(me.mentry);		evp->textsize = l2be(me.tsize);		evp->datasize = l2be(me.dsize);		return 0;	} else		return -1;} voidmain(void){	stopwdog();			/* tranquilise the dog */	optionsinit("/boot/boot boot");	confinit();	savefpregs(&initfp); 	machinit();			/* calls clockinit */	active.exiting = 0;	active.machs = 1; 	kmapinit();	xinit(); 	timersinit();	fmtinit();	vecinit(); 	normalprint = 1;	print("\nPlan 9\n");	prcpuid();	if (PTECACHABILITY == PTENONCOHERWT)		print("caches configured as write-through\n");	if (0)		xsummary(); 	ckpagemask(PGSZ, BY2PG);	tlbinit();	machwire();	pageinit();	procinit0();	initseg();	links();	chandevreset(); 	swapinit();	userinit();	sicwdog();	parseboothdr = parsemipsboothdr;	schedinit();	panic("schedinit returned");} /* *  initialize a processor's mach structure.  each processor does this *  for itself. */voidmachinit(void){	/* Ensure CU1 is off */	clrfpintr(); 	m->stb = &stlb[m->machno][0]; 	clockinit();} /* *  setup MIPS trap vectors */voidvecinit(void){	memmove((ulong*)UTLBMISS, (ulong*)vector0, 0x80);	memmove((ulong*)XEXCEPTION, (ulong*)vector0, 0x80);	memmove((ulong*)CACHETRAP, (ulong*)vector100, 0x80);	memmove((ulong*)EXCEPTION, (ulong*)vector180, 0x80);	memmove((ulong*)(KSEG0+0x200), (ulong*)vector180, 0x80);	icflush((ulong*)UTLBMISS, 4*1024); 	setstatus(getstatus() & ~BEV);} voidinit0(void){	char buf[128]; 	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()){		ksetenv("cputype", "mips", 0);		snprint(buf, sizeof buf, "mips %s rb450g", conffile);		ksetenv("terminal", buf, 0);		if(cpuserver)			ksetenv("service", "cpu", 0);		else			ksetenv("service", "terminal", 0);		/*		 * we don't have a good way to read our cfg file in		 * RouterBOOT, so set the configuration here.		 */		ksetenv("nobootprompt", "tcp", 0);		ksetenv("nvram", "/boot/nvram", 0);		poperror();	}	kproc("alarm", alarmkproc, 0);	i8250console();	touser(sp);} FPsave	initfp; static voidbootargs(uintptr base){	int i;	ulong ssize;	char **av, *p; 	/*	 * Push the boot args onto the stack.	 * The initial value of the user stack must be such	 * that the total used is larger than the maximum size	 * of the argument list checked in syscall.	 */	i = oargblen+1;	p = UINT2PTR(STACKALIGN(base + BY2PG - Stkheadroom - i));	memmove(p, oargb, i); 	/*	 * Now push the argv pointers.	 * The code jumped to by touser in lproc.s expects arguments	 *	main(char* argv0, ...)	 * and calls	 * 	startboot("/boot/boot", &argv0)	 * not the usual (int argc, char* argv[])	 */	av = (char**)(p - (oargc+1)*sizeof(char*));	ssize = base + BY2PG - PTR2UINT(av);	for(i = 0; i < oargc; i++)		*av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);	*av = nil;	sp = USTKTOP - ssize;} voiduserinit(void){	Proc *p;	KMap *k;	Page *pg;	Segment *s; 	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;	p->fpsave.fpstatus = initfp.fpstatus; 	/*	 * Kernel Stack	 */	p->sched.pc = (ulong)init0;	p->sched.sp = (ulong)p->kstack+KSTACK-Stkheadroom;	p->sched.sp = STACKALIGN(p->sched.sp); 	/*	 * User Stack	 *	 * Technically, newpage can't be called here because it	 * should only be called when in a user context as it may	 * try to sleep if there are no pages available, but that	 * shouldn't be the case here.	 */	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);	p->seg[SSEG] = s;	pg = newpage(1, 0, USTKTOP-BY2PG);	segpage(s, pg);	k = kmap(pg);	bootargs(VA(k));	kunmap(k); 	/*	 * 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]);	memset((void *)VA(k), 0, BY2PG);	memmove((ulong*)VA(k), initcode, sizeof initcode);	kunmap(k); 	ready(p);} 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;	/* no fpu, so no fp state to save */} 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;#ifdef BOOTARGS_EXIST	if(n >= BOOTARGSLEN)		error("kernel configuration too large");	memmove(BOOTARGS, p, n);	memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);#endif	USED(n);	poperror();	free(p);} static voidshutdown(int ispanic){	int ms, once; 	ilock(&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);	/*	 * setting exiting will make hzclock() on each processor call exit(0),	 * which calls shutdown(0) and idles non-bootstrap cpus and returns	 * on bootstrap processors (to permit a reboot).  clearing our bit	 * in machs avoids calling exit(0) from hzclock() on this processor.	 */	active.machs &= ~(1<<m->machno);	active.exiting = 1;	iunlock(&active); 	if(once) {		delay(m->machno*1000);		/* stagger them */		iprint("cpu%d: exiting\n", m->machno);	}	spllo();	ms = MAXMACH * 1000;	for(; ms > 0; ms -= TK2MS(2)){		delay(TK2MS(2));		if(active.machs == 0 && consactive() == 0)			break;	}	delay(100);} /* * the new kernel is already loaded at address `code' * of size `size' and entry point `entry'. */voidreboot(void *entry, void *code, ulong size){	void (*f)(ulong, ulong, ulong); 	writeconf(); 	/*	 * the boot processor is cpu0.  execute this function on it	 * so that the new kernel has the same cpu0.	 */	if (m->machno != 0) {		procwired(up, 0);		sched();	}	if (m->machno != 0)		print("on cpu%d (not 0)!\n", m->machno); 	shutdown(0); 	/*	 * should be the only processor running now	 *///	iprint("reboot: entry %#p code %#p size %ld\n", entry, code, size);

Lines 1–500 of 636.