123 lines · 2.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 "mp.h" _MP_ *_mp_; static voidmpresetothers(void){	/*	 * INIT all excluding self.	 */	lapicicrw(0, 0x000C0000|ApicINIT);} static int identify(void); PCArch archmp = {.id=		"_MP_",	.ident=		identify,.reset=		mpshutdown,.intrinit=	mpinit,.intrenable=	mpintrenable,.intron=	lapicintron,.introff=	lapicintroff,.fastclock=	i8253read,.timerset=	lapictimerset,.resetothers=	mpresetothers,}; static intidentify(void){	char *cp;	PCMP *pcmp;	uchar *p, sum;	ulong length; 	if((cp = getconf("*nomp")) != nil && strtol(cp, 0, 0) != 0)		return 1; 	/*	 * Search for an MP configuration table. For now,	 * don't accept the default configurations (physaddr == 0).	 * Check for correct signature, calculate the checksum and,	 * if correct, check the version.	 * To do: check extended table checksum.	 */	if((_mp_ = sigsearch("_MP_")) == 0 || _mp_->physaddr == 0) {		/*		 * we can easily get processor info from acpi, but		 * interrupt routing, etc. would require interpreting aml.		 */		print("archmp: no mp table found, assuming uniprocessor\n");		return 1;	} 	if (0)		iprint("mp physaddr %#lux\n", _mp_->physaddr);	pcmp = KADDR(_mp_->physaddr);	if(memcmp(pcmp, "PCMP", 4) != 0) {		print("archmp: mp table has bad magic");		return 1;	} 	length = pcmp->length;	sum = 0;	for(p = (uchar*)pcmp; length; length--)		sum += *p++; 	if(sum || (pcmp->version != 1 && pcmp->version != 4))		return 1; 	if(cpuserver && m->havetsc)		archmp.fastclock = tscticks;	return 0;} Lock mpsynclock; voidsyncclock(void){	uvlong x; 	if(arch->fastclock != tscticks)		return; 	if(m->machno == 0){		wrmsr(0x10, 0);		m->tscticks = 0;	} else {		x = MACHP(0)->tscticks;		while(x == MACHP(0)->tscticks)			;		wrmsr(0x10, MACHP(0)->tscticks);		cycles(&m->tscticks);	}} uvlongtscticks(uvlong *hz){	if(hz != nil)		*hz = m->cpuhz; 	cycles(&m->tscticks);	/* Uses the rdtsc instruction */	return m->tscticks;}