/* * 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;}
/*
* 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 void
mpresetothers(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 int
identify(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;
void
syncclock(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);
}
}
uvlong
tscticks(uvlong *hz)
{
if(hz != nil)
*hz = m->cpuhz;
cycles(&m->tscticks); /* Uses the rdtsc instruction */
return m->tscticks;
}