#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 void
mpdebugothers(void)
{
/*
* NMI all excluding self iff we have started other machs.
*/
if(conf.nmach > 1)
lapicnmibcast();
}
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,
.debugothers= mpdebugothers,
};
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;
}
|