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

📄 devarch.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
static intunimplemented(int){	return 0;}static voidnop(void){}/* * 386 has no compare-and-swap instruction. * Run it with interrupts turned off instead. */static intcmpswap386(long *addr, long old, long new){	int r, s;		s = splhi();	if(r = (*addr == old))		*addr = new;	splx(s);	return r;}/* * On a uniprocessor, you'd think that coherence could be nop, * but it can't.  We still need a barrier when using coherence() in * device drivers. * * On VMware, it's safe (and a huge win) to set this to nop. * Aux/vmware does this via the #P/archctl file. */void (*coherence)(void) = nop;int (*cmpswap)(long*, long, long) = cmpswap386;PCArch* arch;extern PCArch* knownarch[];PCArch archgeneric = {.id=		"generic",.ident=		0,.reset=		i8042reset,.serialpower=	unimplemented,.modempower=	unimplemented,.intrinit=	i8259init,.intrenable=	i8259enable,.intrvecno=	i8259vecno,.intrdisable=	i8259disable,.intron=		i8259on,.introff=		i8259off,.clockenable=	i8253enable,.fastclock=	i8253read,.timerset=	i8253timerset,};typedef struct X86type X86type;struct X86type {	int	family;	int	model;	int	aalcycles;	char*	name;};static X86type x86intel[] ={	{ 4,	0,	22,	"486DX", },	/* known chips */	{ 4,	1,	22,	"486DX50", },	{ 4,	2,	22,	"486SX", },	{ 4,	3,	22,	"486DX2", },	{ 4,	4,	22,	"486SL", },	{ 4,	5,	22,	"486SX2", },	{ 4,	7,	22,	"DX2WB", },	/* P24D */	{ 4,	8,	22,	"DX4", },	/* P24C */	{ 4,	9,	22,	"DX4WB", },	/* P24CT */	{ 5,	0,	23,	"P5", },	{ 5,	1,	23,	"P5", },	{ 5,	2,	23,	"P54C", },	{ 5,	3,	23,	"P24T", },	{ 5,	4,	23,	"P55C MMX", },	{ 5,	7,	23,	"P54C VRT", },	{ 6,	1,	16,	"PentiumPro", },/* trial and error */	{ 6,	3,	16,	"PentiumII", },	{ 6,	5,	16,	"PentiumII/Xeon", },	{ 6,	6,	16,	"Celeron", },	{ 6,	7,	16,	"PentiumIII/Xeon", },	{ 6,	8,	16,	"PentiumIII/Xeon", },	{ 6,	0xB,	16,	"PentiumIII/Xeon", },	{ 0xF,	1,	16,	"P4", },	/* P4 */	{ 0xF,	2,	16,	"PentiumIV/Xeon", },	{ 3,	-1,	32,	"386", },	/* family defaults */	{ 4,	-1,	22,	"486", },	{ 5,	-1,	23,	"P5", },	{ 6,	-1,	16,	"P6", },	{ 0xF,	-1,	16,	"P4", },	/* P4 */	{ -1,	-1,	16,	"unknown", },	/* total default */};/* * The AMD processors all implement the CPUID instruction. * The later ones also return the processor name via functions * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX * and DX: *	K5	"AMD-K5(tm) Processor" *	K6	"AMD-K6tm w/ multimedia extensions" *	K6 3D	"AMD-K6(tm) 3D processor" *	K6 3D+	? */static X86type x86amd[] ={	{ 5,	0,	23,	"AMD-K5", },	/* guesswork */	{ 5,	1,	23,	"AMD-K5", },	/* guesswork */	{ 5,	2,	23,	"AMD-K5", },	/* guesswork */	{ 5,	3,	23,	"AMD-K5", },	/* guesswork */	{ 5,	6,	11,	"AMD-K6", },	/* trial and error */	{ 5,	7,	11,	"AMD-K6", },	/* trial and error */	{ 5,	8,	11,	"AMD-K6-2", },	/* trial and error */	{ 5,	9,	11,	"AMD-K6-III", },/* trial and error */	{ 6,	1,	11,	"AMD-Athlon", },/* trial and error */	{ 6,	2,	11,	"AMD-Athlon", },/* trial and error */	{ 4,	-1,	22,	"Am486", },	/* guesswork */	{ 5,	-1,	23,	"AMD-K5/K6", },	/* guesswork */	{ 6,	-1,	11,	"AMD-Athlon", },/* guesswork */	{ 0xF,	-1,	11,	"AMD64", },	/* guesswork */	{ -1,	-1,	11,	"unknown", },	/* total default */};/* * WinChip 240MHz */static X86type x86winchip[] ={	{5,	4,	23,	"Winchip",},	/* guesswork */	{6,	7,	23,	"Via C3 Samuel 2 or Ezra",},	{6,	8,	23,	"Via C3 Ezra-T",},	{6,	9,	23,	"Via C3 Eden-N",},	{ -1,	-1,	23,	"unknown", },	/* total default */};/* * SiS 55x */static X86type x86sis[] ={	{5,	0,	23,	"SiS 55x",},	/* guesswork */	{ -1,	-1,	23,	"unknown", },	/* total default */};static X86type *cputype;static void	simplecycles(uvlong*);void	(*cycles)(uvlong*) = simplecycles;void	_cycles(uvlong*);	/* in l.s */static voidsimplecycles(uvlong*x){	*x = m->ticks;}voidcpuidprint(void){	int i;	char buf[128];	i = sprint(buf, "cpu%d: %dMHz ", m->machno, m->cpumhz);	if(m->cpuidid[0])		i += sprint(buf+i, "%12.12s ", m->cpuidid);	sprint(buf+i, "%s (cpuid: AX 0x%4.4uX DX 0x%4.4uX)\n",		m->cpuidtype, m->cpuidax, m->cpuiddx);	print(buf);}/* *  figure out: *	- cpu type *	- whether or not we have a TSC (cycle counter) *	- whether or not it supports page size extensions *		(if so turn it on) *	- whether or not it supports machine check exceptions *		(if so turn it on) *	- whether or not it supports the page global flag *		(if so turn it on) */intcpuidentify(void){	char *p;	int family, model, nomce;	X86type *t, *tab;	ulong cr4;	vlong mca, mct;	cpuid(m->cpuidid, &m->cpuidax, &m->cpuiddx);	if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0)		tab = x86amd;	else if(strncmp(m->cpuidid, "CentaurHauls", 12) == 0)		tab = x86winchip;	else if(strncmp(m->cpuidid, "SiS SiS SiS ", 12) == 0)		tab = x86sis;	else		tab = x86intel;		family = X86FAMILY(m->cpuidax);	model = X86MODEL(m->cpuidax);	for(t=tab; t->name; t++)		if((t->family == family && t->model == model)		|| (t->family == family && t->model == -1)		|| (t->family == -1))			break;	m->cpuidtype = t->name;	/*	 *  if there is one, set tsc to a known value	 */	if(m->cpuiddx & 0x10){		m->havetsc = 1;		cycles = _cycles;		if(m->cpuiddx & 0x20)			wrmsr(0x10, 0);	}	/* 	 *  use i8253 to guess our cpu speed	 */	guesscpuhz(t->aalcycles);	/*	 * If machine check exception, page size extensions or page global bit	 * are supported enable them in CR4 and clear any other set extensions.	 * If machine check was enabled clear out any lingering status.	 */	if(m->cpuiddx & 0x2088){		cr4 = 0;		if(m->cpuiddx & 0x08)			cr4 |= 0x10;		/* page size extensions */		if(p = getconf("*nomce"))			nomce = strtoul(p, 0, 0);		else			nomce = 0;		if((m->cpuiddx & 0x80) && !nomce){			cr4 |= 0x40;		/* machine check enable */			if(family == 5){				rdmsr(0x00, &mca);				rdmsr(0x01, &mct);			}		}			/*		 * Detect whether the chip supports the global bit		 * in page directory and page table entries.  When set		 * in a particular entry, it means ``don't bother removing		 * this from the TLB when CR3 changes.''  		 * 		 * We flag all kernel pages with this bit.  Doing so lessens the		 * overhead of switching processes on bare hardware,		 * even more so on VMware.  See mmu.c:/^memglobal.		 *		 * For future reference, should we ever need to do a		 * full TLB flush, it can be accomplished by clearing		 * the PGE bit in CR4, writing to CR3, and then		 * restoring the PGE bit.		 */		if(m->cpuiddx & 0x2000){			cr4 |= 0x80;		/* page global enable bit */			m->havepge = 1;		}		putcr4(cr4);		if(m->cpuiddx & 0x80)			rdmsr(0x01, &mct);	}	cputype = t;	return t->family;}static longcputyperead(Chan*, void *a, long n, vlong offset){	char str[32];	ulong mhz;	mhz = (m->cpuhz+999999)/1000000;	snprint(str, sizeof(str), "%s %lud\n", cputype->name, mhz);	return readstr(offset, a, n, str);}static longarchctlread(Chan*, void *a, long nn, vlong offset){	char buf[256];	int n;		n = snprint(buf, sizeof buf, "cpu %s %lud%s\n",		cputype->name, (ulong)(m->cpuhz+999999)/1000000,		m->havepge ? " pge" : "");	n += snprint(buf+n, sizeof buf-n, "pge %s\n", getcr4()&0x80 ? "on" : "off");	n += snprint(buf+n, sizeof buf-n, "coherence ");	if(coherence == mb386)		n += snprint(buf+n, sizeof buf-n, "mb386\n");	else if(coherence == mb586)		n += snprint(buf+n, sizeof buf-n, "mb586\n");	else if(coherence == nop)		n += snprint(buf+n, sizeof buf-n, "nop\n");	else		n += snprint(buf+n, sizeof buf-n, "0x%p\n", coherence);	n += snprint(buf+n, sizeof buf-n, "cmpswap ");	if(cmpswap == cmpswap386)		n += snprint(buf+n, sizeof buf-n, "cmpswap386\n");	else if(cmpswap == cmpswap486)		n += snprint(buf+n, sizeof buf-n, "cmpswap486\n");	else		n += snprint(buf+n, sizeof buf-n, "0x%p\n", cmpswap);	n += snprint(buf+n, sizeof buf-n, "i8253set %s\n", doi8253set ? "on" : "off");	buf[n] = 0;	return readstr(offset, a, nn, buf);}enum{	CMpge,	CMcoherence,	CMi8253set,};static Cmdtab archctlmsg[] ={	CMpge,		"pge",		2,	CMcoherence,	"coherence",	2,	CMi8253set,	"i8253set",	2,};static longarchctlwrite(Chan*, void *a, long n, vlong){	Cmdbuf *cb;	Cmdtab *ct;	cb = parsecmd(a, n);	if(waserror()){		free(cb);		nexterror();	}	ct = lookupcmd(cb, archctlmsg, nelem(archctlmsg));	switch(ct->index){	case CMpge:		if(!m->havepge)			error("processor does not support pge");		if(strcmp(cb->f[1], "on") == 0)			putcr4(getcr4() | 0x80);		else if(strcmp(cb->f[1], "off") == 0)			putcr4(getcr4() & ~0x80);		else			cmderror(cb, "invalid pge ctl");		break;	case CMcoherence:		if(strcmp(cb->f[1], "mb386") == 0)			coherence = mb386;		else if(strcmp(cb->f[1], "mb586") == 0){			if(X86FAMILY(m->cpuidax) < 5)				error("invalid coherence ctl on this cpu family");			coherence = mb586;		}		else if(strcmp(cb->f[1], "nop") == 0){			/* only safe on vmware */			if(conf.nmach > 1)				error("cannot disable coherence on a multiprocessor");			coherence = nop;		}else			cmderror(cb, "invalid coherence ctl");		break;	case CMi8253set:		if(strcmp(cb->f[1], "on") == 0)			doi8253set = 1;		else if(strcmp(cb->f[1], "off") == 0){			doi8253set = 0;			(*arch->timerset)(0);		}else			cmderror(cb, "invalid i2853set ctl");		break;	}	free(cb);	poperror();	return n;}voidarchinit(void){	PCArch **p;	arch = 0;	for(p = knownarch; *p; p++){		if((*p)->ident && (*p)->ident() == 0){			arch = *p;			break;		}	}	if(arch == 0)		arch = &archgeneric;	else{		if(arch->id == 0)			arch->id = archgeneric.id;		if(arch->reset == 0)			arch->reset = archgeneric.reset;		if(arch->serialpower == 0)			arch->serialpower = archgeneric.serialpower;		if(arch->modempower == 0)			arch->modempower = archgeneric.modempower;		if(arch->intrinit == 0)			arch->intrinit = archgeneric.intrinit;		if(arch->intrenable == 0)			arch->intrenable = archgeneric.intrenable;	}	/*	 *  Decide whether to use copy-on-reference (386 and mp).	 *  We get another chance to set it in mpinit() for a	 *  multiprocessor.	 */	if(X86FAMILY(m->cpuidax) == 3)		conf.copymode = 1;	if(X86FAMILY(m->cpuidax) >= 4)		cmpswap = cmpswap486;	if(X86FAMILY(m->cpuidax) >= 5)		coherence = mb586;	addarchfile("cputype", 0444, cputyperead, nil);	addarchfile("archctl", 0664, archctlread, archctlwrite);}/* *  call either the pcmcia or pccard device setup */intpcmspecial(char *idstr, ISAConf *isa){	return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;}/* *  call either the pcmcia or pccard device teardown */voidpcmspecialclose(int a){	if (_pcmspecialclose != nil)		_pcmspecialclose(a);}/* *  return value and speed of timer set in arch->clockenable */uvlongfastticks(uvlong *hz){	return (*arch->fastclock)(hz);}/* *  set next timer interrupt */voidtimerset(uvlong x){	if(doi8253set)		(*arch->timerset)(x);}

⌨️ 快捷键说明

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