⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#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	"/sys/src/boot/alphapc/conf.h"#include	"axp.h"char argbuf[128];	/* arguments passed to initcode and /boot */Hwrpb *hwrpb;Bootconf *bootconf;Conf	conf;FPsave	initfp;	/* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */uvlong initfpcr = (1LL<62)|(1LL<61)|(1LL<60)|(2LL<<58)|(1LL<48);char bootargs[BOOTARGSLEN];char *confname[MAXCONF];char *confval[MAXCONF];int	nconf;static voidoptions(void){	long i, n;	char *cp, *line[MAXCONF], *p, *q;	cp = bootargs;	strncpy(cp, bootconf->bootargs, BOOTARGSLEN);	cp[BOOTARGSLEN-1] = 0;	/* can't print in this routine, see below in main() */	/*	 * 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++;	}}/* debugging only */static voiddumpopts(void){	int i;	print("dumpopts: found /alpha/conf options at 0x%lux\n",		bootconf->bootargs);	for(i = 0; i < nconf; i++)		print("dumpopts: read %s=%s\n", confname[i], confval[i]);}extern void (*i8237alloc)(void);voidmain(void){	hwrpb = (Hwrpb*)0x10000000;	hwrpb = (Hwrpb*)(KZERO|hwrpb->phys);	arginit();	machinit();	options();	ioinit();	clockinit();	confinit();	archinit();	xinit();	memholes();	if(i8237alloc != nil)		i8237alloc();	mmuinit();	if(arch->coreinit)		arch->coreinit();	trapinit();	screeninit();	printinit();	/* it's now safe to print */	/* dumpopts();			/* DEBUG */	kbdinit();	i8250console();	quotefmtinstall();	print("\nPlan 9\n");	cpuidprint();	if(arch->corehello)		arch->corehello();	procinit0();	initseg();	timersinit();	links();	chandevreset();	pageinit();	swapinit();	savefpregs(&initfp);initfp.fpstatus = 0x68028000;	userinit();	schedinit();}/* cpu->state bits */enum {	Cpubootinprog	= 1,	/* boot in progress */	Cpucanrestart	= 2,	/* restart possible */	Cpuavail	= 4,	/* processor available */	Cpuexists 	= 8,	/* processor present */	Cpuuserhalted	= 0x10,	/* user halted */	Cpuctxtokay	= 0x20,	/* context valid */	Cpupalokay	= 0x40,	/* PALcode valid */	Cpupalmemokay	= 0x80,	/* PALcode memory valid */	Cpupalloaded	= 0x100, /* PALcode loaded */	Cpuhaltmask	= 0xff0000, /* halt request mask */	Cpuhaltdflt	= 0,	Cpuhaltsaveexit = 0x10000,	Cpuhaltcoldboot = 0x20000,	Cpuhaltwarmboot = 0x30000,	Cpuhaltstayhalted = 0x40000,	Cpumustbezero = 0xffffffffff000000ULL,	/* 24:63 -- must be zero */};/* *  initialize a processor's mach structure.  each processor does this *  for itself. */voidmachinit(void){	int n;	Hwcpu *cpu;	icflush();	n = m->machno;	memset(m, 0, sizeof(Mach));	m->machno = n;	active.exiting = 0;	active.machs = 1;	cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff + n*hwrpb->cpulen);	cpu->state &= ~Cpubootinprog;	if (0)		cpu->state |= Cpuhaltstayhalted;}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), "alpha %s alphapc", conffile);		ksetenv("terminal", buf, 0);		ksetenv("cputype", "alpha", 0);		if(cpuserver)			ksetenv("service", "cpu", 0);		else			ksetenv("service", "terminal", 0);		for(i = 0; i < nconf; i++)			if(confname[i]){				if(confname[i][0] != '*')					ksetenv(confname[i], confval[i], 0);				ksetenv(confname[i], confval[i], 1);			}		poperror();	}	kproc("alarm", alarmkproc, 0);	touser((uchar*)(USTKTOP - sizeof(argbuf)));}voiduserinit(void){	Proc *p;	Segment *s;	KMap *k;	char **av;	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	 */	p->sched.pc = (ulong)init0;	p->sched.sp = (ulong)p->kstack+KSTACK-MAXSYSARG*BY2WD;	/*	 * User Stack, pass input arguments to boot process	 */	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);	p->seg[SSEG] = s;	pg = newpage(1, 0, USTKTOP-BY2PG);	segpage(s, pg);	k = kmap(pg);	for(av = (char**)argbuf; *av; av++)		*av += (USTKTOP - sizeof(argbuf)) - (ulong)argbuf;	memmove((uchar*)VA(k) + BY2PG - sizeof(argbuf), argbuf, sizeof argbuf);	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]);	memmove((uchar*)VA(k), initcode, sizeof initcode);	kunmap(k);	ready(p);}voidprocsetup(Proc *p){	p->fpstate = FPinit;	fpenab(0);}voidprocsave(Proc *p){	if(p->fpstate == FPactive){		if(p->state == Moribund)			fpenab(0);		else			savefpregs(&up->fpsave);		p->fpstate = FPinactive;	}	/*	 * Switch to the prototype page tables for this processor.	 * While this processor is in the scheduler, the process could run	 * on another processor and exit, returning the page tables to	 * the free list where they could be reallocated and overwritten.	 * When this processor eventually has to get an entry from the	 * trashed page tables it will crash.	 */	mmupark();}voidsetupboot(int halt){	int n = 0;		// cpu id of primary cpu, not just m->machno	Hwcpu *cpu = (Hwcpu*)((ulong)hwrpb + hwrpb->cpuoff + n*hwrpb->cpulen);	cpu->state &= ~(Cpucanrestart | Cpuhaltmask);	cpu->state |= (halt? Cpuhaltstayhalted: Cpuhaltwarmboot);}/* from ../pc */static voidshutdown(int ispanic){	int ms, once;	lock(&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);	active.machs &= ~(1<<m->machno);	active.exiting = 1;	unlock(&active);	if(once)		print("cpu%d: exiting\n", m->machno);	spllo();	for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){		delay(TK2MS(2));		if(active.machs == 0 && consactive() == 0)			break;	}	if(active.ispanic && m->machno == 0) {		if(cpuserver)			delay(10000);		else			for (;;)				continue;	} else		delay(1000);}/* from ../pc: */voidreboot(void *entry, void *code, ulong size){	// writeconf();		// pass kernel environment to next kernel	shutdown(0);	/*	 * should be the only processor running now	 */	print("shutting down...\n");	delay(200);	splhi();	/* turn off buffered serial console */	serialoq = nil;	/* shutdown devices */	chandevshutdown();#ifdef FUTURE{	ulong *pdb;	/*	 * Modify the machine page table to directly map the low 4MB of memory	 * This allows the reboot code to turn off the page mapping	 */	pdb = m->pdb;	pdb[PDX(0)] = pdb[PDX(KZERO)];	mmuflushtlb(PADDR(pdb));}	/* setup reboot trampoline function */{	void (*f)(ulong, ulong, ulong) = (void*)REBOOTADDR;	memmove(f, rebootcode, sizeof(rebootcode));#else	USED(entry, code, size);#endif	print("rebooting...\n");#ifdef FUTURE	/* off we go - never to return */	(*f)(PADDR(entry), PADDR(code), size);}#endif	setupboot(0);		// reboot, don't halt	exit(0);}voidexit(int ispanic){	canlock(&active);	active.machs &= ~(1<<m->machno);	active.exiting = 1;	unlock(&active);	spllo();	print("cpu %d exiting\n", m->machno);	do		delay(100);	while(consactive());	splhi();	delay(1000);	/* give serial fifo time to finish flushing */	if (getconf("*debug") != nil) {		USED(ispanic);		delay(60*1000);		/* give us time to read the screen */	}	if(arch->coredetach)		arch->coredetach();	setupboot(1);			// set up to halt	for (; ; )		firmware();	// on PC is just:	if (0) {		shutdown(ispanic);		// arch->reset();	}}voidconfinit(void){	ulong ktop, kpages;	Bank *b, *eb;	extern void _main(void);	int userpcnt;	char *p;	if(p = getconf("*kernelpercent"))		userpcnt = 100 - strtol(p, 0, 0);	else		userpcnt = 0;	/*	 * The console firmware divides memory into 1 or more banks.	 * FInd the bank with the kernel in it.	 */	b = bootconf->bank;	eb = b+bootconf->nbank;	ktop = PGROUND((ulong)end);	ktop = PADDR(ktop);	while(b < eb) {		if(b->min < ktop && ktop < b->max)			break;		b++;	}	if(b == eb)		panic("confinit");	/*	 * Split the bank of memory into 2 banks to fool the allocator into	 * allocating low memory pages from bank 0 for any peripherals	 * which only have a 24bit address counter.	 */	conf.mem[0].npage = (8*1024*1024)/BY2PG;	conf.mem[0].base = 0;	conf.mem[1].npage = (b->max-8*1024*1024)/BY2PG;	conf.mem[1].base = 8*1024*1024;	conf.npage = conf.mem[0].npage+conf.mem[1].npage;	conf.upages = (conf.npage*70)/100;	conf.mem[0].npage -= ktop/BY2PG;	conf.mem[0].base += ktop;	conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;	/*	 * Fix up the bank we found to be the remnant, below the kernel.	 * This, and the other banks, will be passed to xhole() later.	 * BUG: conf.upages needs to be adjusted, but how?  In practice,	 * we only have 1 bank, and the remnant is small.	 */	b->max = (uvlong)_main & ~(BY2PG-1);	conf.nmach = 1;	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;	conf.copymode = 0;			/* copy on write */	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 a max. of 16MB + 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 > (16*MB + conf.npage*sizeof(Page))/BY2PG){			kpages = (16*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;	}	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;	}//	conf.monitor = 1;	/* BUG */}voidmemholes(void){	Bank *b, *eb;	b = bootconf->bank;	eb = b+bootconf->nbank;	while(b < eb) {		if(b->min < (1LL<<32) && b->max < (1LL<<32))			xhole(b->min, b->max-b->min);		b++;	}}char *sp;char *pusharg(char *p){	int n;	n = strlen(p)+1;	sp -= n;	memmove(sp, p, n);	return sp;}voidarginit(void){	char **av;	av = (char**)argbuf;	sp = argbuf + sizeof(argbuf);	*av++ = pusharg("boot");	*av = 0;}char *getconf(char *name){	int n;	for(n = 0; n < nconf; n++)		if(cistrcmp(confname[n], name) == 0) {			return confval[n];		}	return 0;}intisaconfig(char *class, int ctlrno, ISAConf *isa){	char cc[32], *p;	int i, n;	snprint(cc, sizeof cc, "%s%d", class, ctlrno);	for(n = 0; n < nconf; n++){		if(cistrcmp(confname[n], cc) != 0)			continue;		isa->nopt = tokenize(confval[n], isa->opt, NISAOPT);		for(i = 0; i < isa->nopt; i++){			p = isa->opt[i];			if(cistrncmp(p, "type=", 5) == 0)				isa->type = p + 5;			else if(cistrncmp(p, "port=", 5) == 0)				isa->port = strtoul(p+5, &p, 0);			else if(cistrncmp(p, "irq=", 4) == 0)				isa->irq = strtoul(p+4, &p, 0);			else if(cistrncmp(p, "dma=", 4) == 0)				isa->dma = strtoul(p+4, &p, 0);			else if(cistrncmp(p, "mem=", 4) == 0)				isa->mem = strtoul(p+4, &p, 0);			else if(cistrncmp(p, "size=", 5) == 0)				isa->size = strtoul(p+5, &p, 0);			else if(cistrncmp(p, "freq=", 5) == 0)				isa->freq = strtoul(p+5, &p, 0);		}		return 1;	}	return 0;}intcistrcmp(char *a, char *b){	int ac, bc;	for(;;){		ac = *a++;		bc = *b++;		if(ac >= 'A' && ac <= 'Z')			ac = 'a' + (ac - 'A');		if(bc >= 'A' && bc <= 'Z')			bc = 'a' + (bc - 'A');		ac -= bc;		if(ac)			return ac;		if(bc == 0)			break;	}	return 0;}intcistrncmp(char *a, char *b, int n){	unsigned ac, bc;	while(n > 0){		ac = *a++;		bc = *b++;		n--;		if(ac >= 'A' && ac <= 'Z')			ac = 'a' + (ac - 'A');		if(bc >= 'A' && bc <= 'Z')			bc = 'a' + (bc - 'A');		ac -= bc;		if(ac)			return ac;		if(bc == 0)			break;	}	return 0;}intgetcfields(char* lp, char** fields, int n, char* sep){	int i;	for(i = 0; lp && *lp && i < n; i++){		while(*lp && strchr(sep, *lp) != 0)			*lp++ = 0;		if(*lp == 0)			break;		fields[i] = lp;		while(*lp && strchr(sep, *lp) == 0){			if(*lp == '\\' && *(lp+1) == '\n')				*lp++ = ' ';			lp++;		}	}	return i;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -