737 lines · 13.6 KB · C
RawDownload
/* * Plan 9 VX */ #define	WANT_M #ifdef __APPLE__#define __DARWIN_UNIX03 0#endif #include	"u.h"#include	"libvx32/vx32.h"#include	<sys/mman.h>#include	<signal.h>#include	<pwd.h>#include	<pthread.h>#include	"lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"ureg.h"#include	"init.h"#include	"error.h"#include	"arg.h"#include	"tos.h" #include	"fs.h" #include	"conf.h" #include	"netif.h"#include	"etherif.h"#include	"vether.h" #define Image IMAGE#include	"draw.h"#include	"memdraw.h"#include	"cursor.h"#include	"screen.h" extern Dev ipdevtab;extern Dev pipdevtab;extern Dev drawdevtab;extern Dev fsdevtab;extern Dev audiodevtab; int	doabort = 1;	// for nowint	abortonfault;int	nocpuload;char*	argv0;char*	conffile = "9vx";Conf	conf; static Mach mach0; extern int	tracemmu;extern int tracekdev;extern int nuspace;static int singlethread; static void	siginit(void);static void machkeyinit(void); static char*	getuser(void); voidusage(void){	// TODO(yy): add debug and other options by ron	fprint(2, "usage: 9vx [-gt] [-f inifile | inifields ... ] [-i initarg] [-r localroot] [-u user]\n");	exit(1);} voidnop(void){} intmain(int argc, char **argv){	char *file; 	/* Minimal set up to make print work. */#ifndef TLS	machkeyinit();#endif	setmach(&mach0);	coherence = nop;	cmpswap = oscmpswap;	quotefmtinstall(); 	cpulimit = 0;	memset(inifield, 0, MAXCONF);	memsize = 256;	canopen = "/";	nogui = 0;	nofork = 0;	nve = 0;	usetty = 0;readargs:	ARGBEGIN{	/* debugging options */	case '1':		singlethread = 1;		break;	case 'A':		doabort++;		break;	case 'B':		abortonfault++;		break;	case 'F':		nofork = 1;		break;	case 'K':		tracekdev++;		break;	case 'L':		nocpuload++;		break;	case 'M':		tracemmu++;		break;	case 'P':		traceprocs++;		break;	case 'S':		tracesyscalls++;		break;	case 'U':		nuspace = atoi(EARGF(usage()));		break;	case 'X':		vx32_debugxlate++;		break;		/* real options */	case 'g':		nogui = 1;		usetty = 1;		break;	case 't':		usetty = 1;		break;		/* ini values */	case 'f':		file = EARGF(usage());		if(addinifile(file) < 0)			panic("error reading config file %s", file);		break;	case 'i':		/*		 * Pass additional flag after -i to init 		 * This is convenient for -ic and -im		 */		if(_args[0] != 0){			initarg = smprint("-%c", _args[0]);			_args++;		}		else			initarg = EARGF(usage());		break;	case 'r':		localroot = EARGF(usage());		break;	case 'u':		username = EARGF(usage());		break; 	default:		usage();	}ARGEND 	while(argc > 0){		if(argv[0][0] == '-'){			/*			 * ARGBEGIN will do: argv++; argc--;			 * to skip argv0, but argv[0] is not argv0 now			 */			argc++; argv--;			goto readargs;		}		addini(strdup(argv[0]));		argc--; argv++;	} 	if(username == nil && (username = getuser()) == nil)		username = "tor";	eve = strdup(username);	if(eve == nil)		panic("strdup eve"); 	mmusize(memsize);	mach0init();	mmuinit();	confinit();	conf.monitor = !nogui; 	/*	 * Unless we're going to use the terminal for input/output,	 * fork into the background.  This is a little dicey, since we	 * haven't allocated the screen yet, but that would kick off	 * a kproc, and we need to fork before we start any pthreads.	 * Cannot fork on OS X - it can't handle it.	 */#ifndef __APPLE__	if(!usetty && !nofork && fork() > 0)		_exit(0);#endif 	/*	 * Have to do this after fork; on OS X child does	 * not inherit sigaltstack.	 */	siginit(); 	printconfig(argv0); 	if(nve == 0)		ipdevtab = pipdevtab; 	printinit();	procinit0();	initseg();	if(nve > 0)		links(); 	chandevreset();	if(!singlethread){		if(nve == 0)			makekprocdev(&ipdevtab);		makekprocdev(&fsdevtab);		makekprocdev(&drawdevtab);		makekprocdev(&audiodevtab);		if(nocpuload == 0)			kproc("pload", &ploadproc, nil);		if(cpulimit > 0 && cpulimit < 100)			kproc("plimit", &plimitproc, &cpulimit);	}	bootinit();	pageinit();#ifdef __APPLE__	if(conf.monitor)		screeninit();	extern void machsiginit(void);	machsiginit();#endif	userinit();	terminit(!usetty);	uartinit(usetty);	timersinit();	active.thunderbirdsarego = 1;	schedinit();	return 0;  // Not reached} static char*getuser(void){	struct passwd *pw; 	pw = getpwuid(getuid());	if(pw == nil)		return nil;	return strdup(pw->pw_name);} /* * Initial config. */voidconfinit(void){	int i; 	conf.npage = 0;	for(i=0; i<nelem(conf.mem); i++)		conf.npage += conf.mem[i].npage;	conf.upages = conf.npage;	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;	if(conf.nproc > 2000)		conf.nproc = 2000;	conf.nimage = 200;	conf.nswap = 0;	conf.nswppo = 0;	conf.ialloc = 1<<20;} static uchar *sp;	/* user stack of init proc */static void init0(void); /* * Set up first process. */voiduserinit(void){	void *v;	Proc *p;	Segment *s;	Page *pg; 	p = newproc();	p->pgrp = newpgrp();	p->egrp = smalloc(sizeof(Egrp));	p->egrp->ref.ref = 1;	p->fgrp = dupfgrp(nil);	p->rgrp = newrgrp();	p->procmode = 0640; 	kstrdup(&eve, username);	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	 */	labelinit(&p->sched, (ulong)init0, (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);	segpage(s, pg);	v = tmpmap(pg);	memset(v, 0, BY2PG);	memmove(v, initcode, sizeof initcode);	tmpunmap(v); 	ready(p);} static 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];	uint32 *lsp; 	sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD - sizeof(Tos); 	ac = 0;	av[ac++] = pusharg("9vx");	for(i = 0; i < bootargc && ac < 32; i++)		av[ac++] = pusharg(bootargv[i]);	if(i == 0)		av[ac++] = pusharg(BOOTARG); 	/* 4 byte word align stack */	sp = (uchar*)((uintptr)sp & ~3); 	/* build argc, argv on stack */	sp -= (ac+2)*sizeof(uint32);	lsp = (uint32*)sp;	*lsp++ = ac;	for(i = 0; i < ac; i++)		*lsp++ = (uint32)(uintptr)(av[i] + ((USTKTOP - BY2PG) - (ulong)base));	*lsp = 0;	sp += (USTKTOP - BY2PG) - (ulong)base;} voidshowexec(ulong sp){	uint32 *a, *argv;	int i, n;	uchar *uzero;		uzero = up->pmmu.uzero;	iprint("showexec %p\n", (uintptr)sp);	if(sp >= USTKTOP || sp < USTKTOP-USTKSIZE)		panic("showexec: bad sp");	a = (uint32*)(uzero + sp);	n = *a++;	iprint("argc=%d\n", n);	argv = a;	iprint("argv=%p\n", argv);	for(i=0; i<n; i++){		iprint("argv[%d]=%p\n", i, (uintptr)argv[i]);		iprint("\t%s\n", (uzero + argv[i]));	}	iprint("argv[%d]=%p\n", i, argv[i]);}  /* * First process starts executing, with up set, here. */static voidinit0(void){	char buf[2*KNAMELEN]; 	up->nerrlab = 0;	if(waserror())		panic("init0: %r"); 	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(); 	/* set up environment */	snprint(buf, sizeof(buf), "%s %s", "vx32" /*arch->id*/, conffile);	ksetenv("terminal", buf, 0);	ksetenv("cputype", "386", 0);	ksetenv("rootdir", "/root", 0);	ksetenv("service", "terminal", 0);	ksetenv("sysname", "vx32", 0);//	ksetenv("init", "/386/init -t", 0);	ksetenv("user", username, 0);	setinienv(); 	poperror(); //showexec(sp);	touser(sp);	/* infinity, and beyond. */} int invx32;	/* shared with sbcl-signal.c */ /* * SIGSEGV handler.  If we get SIGSEGV while executing * in the kernel on behalf of user code, then we call fault * to map in the missing page, just as we would on a MIPS * or any other architecture with a software-managed TLB. */voidsigsegv(int signo, siginfo_t *info, void *v){	int read;	ulong addr, eip, esp;	ucontext_t *uc;	uchar *uzero; 	if(m == nil)		panic("sigsegv: m == nil");	if(m->machno != 0)		panic("sigsegv on cpu%d", m->machno);	if(up == nil)		panic("sigsegv: up == nil"); 	uzero = up->pmmu.uzero; 	uc = v;#if defined(__APPLE__)	mcontext_t mc;	mc = uc->uc_mcontext;	addr = (ulong)info->si_addr;	read = !(mc->es.err&2);	eip = mc->ss.eip;	esp = mc->ss.esp;#elif defined(__linux__)

Lines 1–500 of 737.