Пример #1
0
void
mathinit(void)
{
	trapenable(VectorCERR, matherror, 0, "matherror");
	if(X86FAMILY(m->cpuidax) == 3)
		intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror");
	trapenable(VectorCNA, mathemu, 0, "mathemu");
	trapenable(VectorCSO, mathover, 0, "mathover");
}
Пример #2
0
static void
x86wdenable(void)
{
	Wd *wd;
	vlong r, t;
	int i, model;
	u32int evntsel;

	wd = &x86wd;
	ilock(wd);
	if(wd->inuse){
		iunlock(wd);
		error(Einuse);
	}
	iunlock(wd);

	/*
	 * keep this process on cpu 0 so we always see the same timers
	 * and so that this will work even if all other cpus are shut down.
	 */
	runoncpu(0);

	/*
	 * Check the processor is capable of doing performance
	 * monitoring and that it has TSC, RDMSR/WRMSR and a local APIC.
	 */
	model = -1;
	if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0){
		if(X86FAMILY(m->cpuidax) == 0x06)
			model = K6;
		else if(X86FAMILY(m->cpuidax) == 0x0F)
			model = K8;
	}
	else if(strncmp(m->cpuidid, "GenuineIntel", 12) == 0){
		if(X86FAMILY(m->cpuidax) == 0x06)
			model = P6;
		else if(X86FAMILY(m->cpuidax) == 0x0F)
			model = P4;
	}
	if(model == -1 ||
	    (m->cpuiddx & (Cpuapic|Cpumsr|Tsc)) != (Cpuapic|Cpumsr|Tsc))
		error(Enodev);

	ilock(wd);
	if(wd->inuse){
		iunlock(wd);
		error(Einuse);
	}
	wd->model = model;
	wd->inuse = 1;
	wd->ticks = 0;

	/*
	 * See the IA-32 Intel Architecture Software
	 * Developer's Manual Volume 3: System Programming Guide,
	 * Chapter 15 and the AMD equivalent for what all this
	 * bit-whacking means.
	 */
	t = interval();
	switch(model){
	case P6:
		wrmsr(0x186, 0);			/* evntsel */
		wrmsr(0x187, 0);
		wrmsr(0xC1, 0);				/* perfctr */
		wrmsr(0xC2, 0);

		lapicnmienable();
	
		evntsel = 0x00130000|0x79;
		wrmsr(0xC1, -t);
		wrmsr(0x186, 0x00400000|evntsel);
		break;
	case P4:
		rdmsr(0x1A0, &r);
		if(!(r & 0x0000000000000080LL))
			return;
	
		for(i = 0; i < 18; i++)
			wrmsr(0x300+i, 0);		/* perfctr */
		for(i = 0; i < 18; i++)
			wrmsr(0x360+i, 0);		/* ccr */
	
		for(i = 0; i < 31; i++)
			wrmsr(0x3A0+i, 0);		/* escr */
		for(i = 0; i < 6; i++)
			wrmsr(0x3C0+i, 0);		/* escr */
		for(i = 0; i < 6; i++)
			wrmsr(0x3C8+i, 0);		/* escr */
		for(i = 0; i < 2; i++)
			wrmsr(0x3E0+i, 0);		/* escr */
	
		if(!(r & 0x0000000000001000LL)){
			for(i = 0; i < 2; i++)
				wrmsr(0x3F1+i, 0);	/* pebs */
		}
	
		lapicnmienable();
	
		wrmsr(0x3B8, 0x000000007E00000CLL);	/* escr0 */
		r = 0x0000000004FF8000ULL;
		wrmsr(0x36C, r);			/* cccr0 */
		wrmsr(0x30C, -t);
		wrmsr(0x36C, 0x0000000000001000LL|r);
		break;
	case K6:
	case K8:
		/*
		 * PerfEvtSel 0-3, PerfCtr 0-4.
		 */
		for(i = 0; i < 8; i++)
			wrmsr(0xC0010000+i, 0);
	
		lapicnmienable();
	
		evntsel = 0x00130000|0x76;
		wrmsr(0xC0010004, -t);
		wrmsr(0xC0010000, 0x00400000|evntsel);
		break;
	}
	iunlock(wd);
}
Пример #3
0
void
mpinit(void)
{
	int ncpu, cpuson;
	char *cp;
	PCMP *pcmp;
	uchar *e, *p;
	Apic *apic, *bpapic;
	void *va;

	mpdebug = getconf("*debugmp") != nil;
	i8259init();
	syncclock();

	bpapic = nil;
	cpuson = 0;

	if(_mp_ == 0) {
		/*
		 * We can easily get processor info from ACPI, but
		 * interrupt routing, etc. would require interpreting AML.
		 */
		print("mpinit: no mp table found, assuming uniprocessor\n");
		archrevert();
		return;
	}
	pcmp = KADDR(_mp_->physaddr);

	/*
	 * Map the local APIC.
	 */
	if((va = vmap(pcmp->lapicbase, 1024)) == nil)
		return;
	mppcmp = pcmp;
	print("LAPIC: %#lux %#lux\n", pcmp->lapicbase, (ulong)va);

	/*
	 * Run through the table saving information needed for starting
	 * application processors and initialising any I/O APICs. The table
	 * is guaranteed to be in order such that only one pass is necessary.
	 */
	p = ((uchar*)pcmp)+sizeof(PCMP);
	e = ((uchar*)pcmp)+pcmp->length;
	while(p < e) switch(*p){

	default:
		print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n",
			*p, e-p);
		while(p < e){
			print("%uX ", *p);
			p++;
		}
		break;

	case PcmpPROCESSOR:
		if(apic = mkprocessor((PCMPprocessor*)p)){
			/*
			 * Must take a note of bootstrap processor APIC
			 * now as it will be needed in order to start the
			 * application processors later and there's no
			 * guarantee that the bootstrap processor appears
			 * first in the table before the others.
			 */
			apic->addr = va;
			apic->paddr = pcmp->lapicbase;
			if(apic->flags & PcmpBP)
				bpapic = apic;
			cpuson++;
		}
		p += sizeof(PCMPprocessor);
		continue;

	case PcmpBUS:
		mkbus((PCMPbus*)p);
		p += sizeof(PCMPbus);
		continue;

	case PcmpIOAPIC:
		if(apic = mkioapic((PCMPioapic*)p))
			ioapicinit(apic, ((PCMPioapic*)p)->apicno);
		p += sizeof(PCMPioapic);
		continue;

	case PcmpIOINTR:
		mkiointr((PCMPintr*)p);
		p += sizeof(PCMPintr);
		continue;

	case PcmpLINTR:
		mklintr((PCMPintr*)p);
		p += sizeof(PCMPintr);
		continue;
	}

	dprint("mpinit: mp table describes %d cpus\n", cpuson);

	/* For now, always scan ACPI's MADT for processors that MP missed. */
	trympacpi();

	if (bpapic == nil)
		bpapic = bootapic;

	/*
	 * No bootstrap processor, no need to go further.
	 */
	if(bpapic == 0)
		return;
	bpapic->online = 1;

	lapicinit(bpapic);

	/*
	 * These interrupts are local to the processor
	 * and do not appear in the I/O APIC so it is OK
	 * to set them now.
	 */
	intrenable(IrqTIMER, lapicclock, 0, BUSUNKNOWN, "clock");
	intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror");
	intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious");
	lapiconline();

	checkmtrr();

	/*
	 * Initialise the application processors.
	 */
	if(cp = getconf("*ncpu")){
		ncpu = strtol(cp, 0, 0);
		if(ncpu < 1)
			ncpu = 1;
		else if(ncpu > MAXMACH)
			ncpu = MAXMACH;
	}
	else
		ncpu = MAXMACH;
	memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap));
	for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){
		if(ncpu <= 1)
			break;
		if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN
		&& apic->type == PcmpPROCESSOR){
			mpstartap(apic);
			conf.nmach++;
			ncpu--;
		}
	}

	/*
	 *  we don't really know the number of processors till
	 *  here.
	 *
	 *  set conf.copymode here if nmach > 1.
	 *  Should look for an ExtINT line and enable it.
	 */
	if(X86FAMILY(m->cpuidax) == 3 || conf.nmach > 1)
		conf.copymode = 1;
}
Пример #4
0
Файл: mp.c Проект: 8l/inferno
void
mpinit(void)
{
	int ncpu;
	char *cp;
	PCMP *pcmp;
	uchar *e, *p;
	Apic *apic, *bpapic;

	i8259init();
	syncclock();

	if(_mp_ == 0)
		return;
	pcmp = KADDR(_mp_->physaddr);

	/*
	 * Map the local APIC.
	 */
	if(mmukmap(pcmp->lapicbase, 0, 1024) == 0)
		return;

	bpapic = nil;

	/*
	 * Run through the table saving information needed for starting
	 * application processors and initialising any I/O APICs. The table
	 * is guaranteed to be in order such that only one pass is necessary.
	 */
	p = ((uchar*)pcmp)+sizeof(PCMP);
	e = ((uchar*)pcmp)+pcmp->length;
	while(p < e) switch(*p){

	default:
		print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n",
			*p, e-p);
		while(p < e){
			print("%uX ", *p);
			p++;
		}
		break;

	case PcmpPROCESSOR:
		if(apic = mkprocessor((PCMPprocessor*)p)){
			/*
			 * Must take a note of bootstrap processor APIC
			 * now as it will be needed in order to start the
			 * application processors later and there's no
			 * guarantee that the bootstrap processor appears
			 * first in the table before the others.
			 */
			apic->addr = KADDR(pcmp->lapicbase);
			if(apic->flags & PcmpBP)
				bpapic = apic;
		}
		p += sizeof(PCMPprocessor);
		continue;

	case PcmpBUS:
		mkbus((PCMPbus*)p);
		p += sizeof(PCMPbus);
		continue;

	case PcmpIOAPIC:
		if(apic = mkioapic((PCMPioapic*)p))
			ioapicinit(apic, ((PCMPioapic*)p)->apicno);
		p += sizeof(PCMPioapic);
		continue;

	case PcmpIOINTR:
		mkiointr((PCMPintr*)p);
		p += sizeof(PCMPintr);
		continue;

	case PcmpLINTR:
		mklintr((PCMPintr*)p);
		p += sizeof(PCMPintr);
		continue;
	}

	/*
	 * No bootstrap processor, no need to go further.
	 */
	if(bpapic == 0)
		return;

	lapicinit(bpapic);
	lock(&mprdthilock);
	mprdthi |= (1<<bpapic->apicno)<<24;
	unlock(&mprdthilock);

	/*
	 * These interrupts are local to the processor
	 * and do not appear in the I/O APIC so it is OK
	 * to set them now.
	 */
	intrenable(IrqTIMER, lapicclock, 0, BUSUNKNOWN, "clock");
	intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror");
	intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious");
	lapiconline();

	checkmtrr();

	/*
	 * Initialise the application processors.
	 */
	if(cp = getconf("*ncpu")){
		ncpu = strtol(cp, 0, 0);
		if(ncpu < 1)
			ncpu = 1;
	}
	else
		ncpu = MaxAPICNO;
	memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap));
	for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){
		if(ncpu <= 1)
			break;
		if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN
		&& apic->type == PcmpPROCESSOR){
			mpstartap(apic);
			conf.nmach++;
			ncpu--;
		}
	}

	/*
	 *  we don't really know the number of processors till
	 *  here.
	 *
	 *  set conf.copymode here if nmach > 1.
	 *  Should look for an ExtINT line and enable it.
	 */
	if(X86FAMILY(m->cpuidax) == 3 || conf.nmach > 1)
		conf.copymode = 1;
}