pc, pc64: add minimal HPET driver to measure LAPIC and TSC frequencies
This adds the new function pointer PCArch.clockinit(), which is a timer dependent initialization routine. It also takes over the job of guesscpuhz(). This way, the architecture ident code can switch between different timers (i8253, HPET and XEN timer).
This commit is contained in:
parent
999e98b9b8
commit
a05bab362f
19 changed files with 259 additions and 110 deletions
|
@ -180,6 +180,20 @@ maptables(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Tbl*
|
||||||
|
findtable(char sig[4])
|
||||||
|
{
|
||||||
|
Tbl *t;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<ntblmap; i++){
|
||||||
|
t = tblmap[i];
|
||||||
|
if(memcmp(t->sig, sig, 4) == 0)
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
static Apic*
|
static Apic*
|
||||||
findapic(int gsi, int *pintin)
|
findapic(int gsi, int *pintin)
|
||||||
{
|
{
|
||||||
|
@ -569,13 +583,9 @@ acpiinit(void)
|
||||||
amlinit();
|
amlinit();
|
||||||
|
|
||||||
/* load DSDT */
|
/* load DSDT */
|
||||||
for(i=0; i<ntblmap; i++){
|
if((t = findtable("DSDT")) != nil){
|
||||||
t = tblmap[i];
|
amlintmask = (~0ULL) >> (t->rev <= 1)*32;
|
||||||
if(memcmp(t->sig, "DSDT", 4) == 0){
|
amlload(t->data, tbldlen(t));
|
||||||
amlintmask = (~0ULL) >> (t->rev <= 1)*32;
|
|
||||||
amlload(t->data, tbldlen(t));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load SSDT, there can be multiple tables */
|
/* load SSDT, there can be multiple tables */
|
||||||
|
@ -588,15 +598,10 @@ acpiinit(void)
|
||||||
/* set APIC mode */
|
/* set APIC mode */
|
||||||
amleval(amlwalk(amlroot, "_PIC"), "i", 1, nil);
|
amleval(amlwalk(amlroot, "_PIC"), "i", 1, nil);
|
||||||
|
|
||||||
for(i=0; i<ntblmap; i++){
|
t = findtable("APIC");
|
||||||
t = tblmap[i];
|
if(t == nil)
|
||||||
if(memcmp(t->sig, "APIC", 4) == 0)
|
panic("acpiinit: no MADT (APIC) table");
|
||||||
goto Foundapic;
|
|
||||||
}
|
|
||||||
panic("acpiinit: no MADT (APIC) table");
|
|
||||||
return;
|
|
||||||
|
|
||||||
Foundapic:
|
|
||||||
s = t->data;
|
s = t->data;
|
||||||
e = s + tbldlen(t);
|
e = s + tbldlen(t);
|
||||||
lapicbase = get32(s); s += 8;
|
lapicbase = get32(s); s += 8;
|
||||||
|
@ -708,16 +713,12 @@ acpireset(void)
|
||||||
{
|
{
|
||||||
uchar *p;
|
uchar *p;
|
||||||
Tbl *t;
|
Tbl *t;
|
||||||
int i;
|
|
||||||
|
|
||||||
/* stop application processors */
|
/* stop application processors */
|
||||||
mpshutdown();
|
mpshutdown();
|
||||||
|
|
||||||
/* locate and write platform reset register */
|
/* locate and write platform reset register */
|
||||||
for(i=0; i < ntblmap; i++){
|
while((t = findtable("FACP")) != nil){
|
||||||
t = tblmap[i];
|
|
||||||
if(memcmp(t->sig, "FACP", 4) != 0)
|
|
||||||
continue;
|
|
||||||
if(get32(t->len) <= 128)
|
if(get32(t->len) <= 128)
|
||||||
break;
|
break;
|
||||||
p = (uchar*)t;
|
p = (uchar*)t;
|
||||||
|
@ -735,6 +736,11 @@ acpireset(void)
|
||||||
|
|
||||||
static int identify(void);
|
static int identify(void);
|
||||||
extern int i8259irqno(int, int);
|
extern int i8259irqno(int, int);
|
||||||
|
extern void i8253init(void);
|
||||||
|
|
||||||
|
extern int hpetprobe(uvlong);
|
||||||
|
extern void hpetinit(void);
|
||||||
|
extern uvlong hpetread(uvlong*);
|
||||||
|
|
||||||
PCArch archacpi = {
|
PCArch archacpi = {
|
||||||
.id= "ACPI",
|
.id= "ACPI",
|
||||||
|
@ -745,6 +751,7 @@ PCArch archacpi = {
|
||||||
.intrirqno= i8259irqno,
|
.intrirqno= i8259irqno,
|
||||||
.intron= lapicintron,
|
.intron= lapicintron,
|
||||||
.introff= lapicintroff,
|
.introff= lapicintroff,
|
||||||
|
.clockinit= i8253init,
|
||||||
.fastclock= i8253read,
|
.fastclock= i8253read,
|
||||||
.timerset= lapictimerset,
|
.timerset= lapictimerset,
|
||||||
};
|
};
|
||||||
|
@ -782,6 +789,7 @@ identify(void)
|
||||||
{
|
{
|
||||||
uvlong pa;
|
uvlong pa;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
Tbl *t;
|
||||||
|
|
||||||
if((cp = getconf("*acpi")) == nil)
|
if((cp = getconf("*acpi")) == nil)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -799,12 +807,20 @@ identify(void)
|
||||||
maptables();
|
maptables();
|
||||||
addarchfile("acpitbls", 0444, readtbls, nil);
|
addarchfile("acpitbls", 0444, readtbls, nil);
|
||||||
addarchfile("acpimem", 0600, readmem, writemem);
|
addarchfile("acpimem", 0600, readmem, writemem);
|
||||||
if(strcmp(cp, "0") == 0)
|
if(strcmp(cp, "0") == 0 || findtable("APIC") == nil)
|
||||||
return 1;
|
return 1;
|
||||||
if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
|
if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
if(getconf("*nohpet") == nil
|
||||||
|
&& (t = findtable("HPET")) != nil
|
||||||
|
&& ((uchar*)t)[40] == 0
|
||||||
|
&& hpetprobe(get64((uchar*)t+44)) == 0){
|
||||||
|
archacpi.clockinit = hpetinit;
|
||||||
|
archacpi.fastclock = hpetread;
|
||||||
|
}
|
||||||
if(m->havetsc && getconf("*notsc") == nil)
|
if(m->havetsc && getconf("*notsc") == nil)
|
||||||
archacpi.fastclock = tscticks;
|
archacpi.fastclock = tscticks;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,41 @@ archreset(void)
|
||||||
idle();
|
idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
delay(int millisecs)
|
||||||
|
{
|
||||||
|
millisecs *= m->loopconst;
|
||||||
|
if(millisecs <= 0)
|
||||||
|
millisecs = 1;
|
||||||
|
aamloop(millisecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
microdelay(int microsecs)
|
||||||
|
{
|
||||||
|
microsecs *= m->loopconst;
|
||||||
|
microsecs /= 1000;
|
||||||
|
if(microsecs <= 0)
|
||||||
|
microsecs = 1;
|
||||||
|
aamloop(microsecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* performance measurement ticks. must be low overhead.
|
||||||
|
* doesn't have to count over a second.
|
||||||
|
*/
|
||||||
|
ulong
|
||||||
|
perfticks(void)
|
||||||
|
{
|
||||||
|
uvlong x;
|
||||||
|
|
||||||
|
if(m->havetsc)
|
||||||
|
cycles(&x);
|
||||||
|
else
|
||||||
|
x = 0;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
PCArch archgeneric = {
|
PCArch archgeneric = {
|
||||||
.id= "generic",
|
.id= "generic",
|
||||||
.ident= 0,
|
.ident= 0,
|
||||||
|
@ -53,6 +88,7 @@ PCArch archgeneric = {
|
||||||
.intron= i8259on,
|
.intron= i8259on,
|
||||||
.introff= i8259off,
|
.introff= i8259off,
|
||||||
|
|
||||||
|
.clockinit= i8253init,
|
||||||
.clockenable= i8253enable,
|
.clockenable= i8253enable,
|
||||||
.fastclock= i8253read,
|
.fastclock= i8253read,
|
||||||
.timerset= i8253timerset,
|
.timerset= i8253timerset,
|
||||||
|
|
|
@ -229,6 +229,7 @@ struct Mach
|
||||||
int lastintr;
|
int lastintr;
|
||||||
|
|
||||||
int loopconst;
|
int loopconst;
|
||||||
|
int aalcycles;
|
||||||
|
|
||||||
int cpumhz;
|
int cpumhz;
|
||||||
uvlong cyclefreq; /* Frequency of user readable cycle counter */
|
uvlong cyclefreq; /* Frequency of user readable cycle counter */
|
||||||
|
@ -289,6 +290,7 @@ struct PCArch
|
||||||
void (*introff)(void);
|
void (*introff)(void);
|
||||||
void (*intron)(void);
|
void (*intron)(void);
|
||||||
|
|
||||||
|
void (*clockinit)(void);
|
||||||
void (*clockenable)(void);
|
void (*clockenable)(void);
|
||||||
uvlong (*fastclock)(uvlong*);
|
uvlong (*fastclock)(uvlong*);
|
||||||
void (*timerset)(uvlong);
|
void (*timerset)(uvlong);
|
||||||
|
|
|
@ -461,8 +461,6 @@ static X86type x86sis[] =
|
||||||
{ -1, -1, 23, "unknown", }, /* total default */
|
{ -1, -1, 23, "unknown", }, /* total default */
|
||||||
};
|
};
|
||||||
|
|
||||||
static X86type *cputype;
|
|
||||||
|
|
||||||
static void simplecycles(uvlong*);
|
static void simplecycles(uvlong*);
|
||||||
void (*cycles)(uvlong*) = simplecycles;
|
void (*cycles)(uvlong*) = simplecycles;
|
||||||
void _cycles(uvlong*); /* in l.s */
|
void _cycles(uvlong*); /* in l.s */
|
||||||
|
@ -547,6 +545,7 @@ cpuidentify(void)
|
||||||
|| (t->family == -1))
|
|| (t->family == -1))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
m->aalcycles = t->aalcycles;
|
||||||
m->cpuidtype = t->name;
|
m->cpuidtype = t->name;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -559,11 +558,6 @@ cpuidentify(void)
|
||||||
wrmsr(0x10, 0);
|
wrmsr(0x10, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* use i8253 to guess our cpu speed
|
|
||||||
*/
|
|
||||||
guesscpuhz(t->aalcycles);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If machine check exception, page size extensions or page global bit
|
* If machine check exception, page size extensions or page global bit
|
||||||
* are supported enable them in CR4 and clear any other set extensions.
|
* are supported enable them in CR4 and clear any other set extensions.
|
||||||
|
@ -690,7 +684,6 @@ cpuidentify(void)
|
||||||
|
|
||||||
fpuinit();
|
fpuinit();
|
||||||
|
|
||||||
cputype = t;
|
|
||||||
return t->family;
|
return t->family;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,7 +695,7 @@ cputyperead(Chan*, void *a, long n, vlong offset)
|
||||||
|
|
||||||
mhz = (m->cpuhz+999999)/1000000;
|
mhz = (m->cpuhz+999999)/1000000;
|
||||||
|
|
||||||
snprint(str, sizeof(str), "%s %lud\n", cputype->name, mhz);
|
snprint(str, sizeof(str), "%s %lud\n", m->cpuidtype, mhz);
|
||||||
return readstr(offset, a, n, str);
|
return readstr(offset, a, n, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -715,7 +708,7 @@ archctlread(Chan*, void *a, long nn, vlong offset)
|
||||||
p = buf = smalloc(READSTR);
|
p = buf = smalloc(READSTR);
|
||||||
ep = p + READSTR;
|
ep = p + READSTR;
|
||||||
p = seprint(p, ep, "cpu %s %lud%s\n",
|
p = seprint(p, ep, "cpu %s %lud%s\n",
|
||||||
cputype->name, (ulong)(m->cpuhz+999999)/1000000,
|
m->cpuidtype, (ulong)(m->cpuhz+999999)/1000000,
|
||||||
m->havepge ? " pge" : "");
|
m->havepge ? " pge" : "");
|
||||||
p = seprint(p, ep, "pge %s\n", getcr4()&0x80 ? "on" : "off");
|
p = seprint(p, ep, "pge %s\n", getcr4()&0x80 ? "on" : "off");
|
||||||
p = seprint(p, ep, "coherence ");
|
p = seprint(p, ep, "coherence ");
|
||||||
|
@ -877,6 +870,8 @@ archinit(void)
|
||||||
arch->intrinit = knownarch[0]->intrinit;
|
arch->intrinit = knownarch[0]->intrinit;
|
||||||
if(arch->intrassign == nil)
|
if(arch->intrassign == nil)
|
||||||
arch->intrassign = knownarch[0]->intrassign;
|
arch->intrassign = knownarch[0]->intrassign;
|
||||||
|
if(arch->clockinit == nil)
|
||||||
|
arch->clockinit = knownarch[0]->clockinit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -51,7 +51,6 @@ ulong getcr3(void);
|
||||||
ulong getcr4(void);
|
ulong getcr4(void);
|
||||||
u32int getdr6(void);
|
u32int getdr6(void);
|
||||||
char* getconf(char*);
|
char* getconf(char*);
|
||||||
void guesscpuhz(int);
|
|
||||||
void halt(void);
|
void halt(void);
|
||||||
void mwait(void*);
|
void mwait(void*);
|
||||||
int i8042auxcmd(int);
|
int i8042auxcmd(int);
|
||||||
|
|
126
sys/src/9/pc/hpet.c
Normal file
126
sys/src/9/pc/hpet.c
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
#include "u.h"
|
||||||
|
#include "../port/lib.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "dat.h"
|
||||||
|
#include "fns.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HPET timer
|
||||||
|
*
|
||||||
|
* The HPET timer is memory mapped which allows
|
||||||
|
* faster access compared to the classic i8253.
|
||||||
|
* This timer is not used to generate interrupts
|
||||||
|
* as we use the LAPIC timer for that.
|
||||||
|
* Its purpose is to measure the LAPIC timer
|
||||||
|
* and TSC frequencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
Cap = 0x00/4,
|
||||||
|
Period = 0x04/4,
|
||||||
|
Config = 0x10/4,
|
||||||
|
Isr = 0x20/4,
|
||||||
|
Ctrlo = 0xF0/4,
|
||||||
|
Ctrhi = 0xF4/4,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
Lock;
|
||||||
|
u32int *mmio;
|
||||||
|
uvlong last;
|
||||||
|
uvlong freq;
|
||||||
|
} hpet;
|
||||||
|
|
||||||
|
int
|
||||||
|
hpetprobe(uvlong pa)
|
||||||
|
{
|
||||||
|
u32int cap, period;
|
||||||
|
int mhz;
|
||||||
|
|
||||||
|
if((hpet.mmio = vmap(pa, 1024)) == nil)
|
||||||
|
return -1;
|
||||||
|
cap = hpet.mmio[Cap];
|
||||||
|
period = hpet.mmio[Period];
|
||||||
|
if(period == 0 || period > 0x05F4E100)
|
||||||
|
return -1;
|
||||||
|
hpet.freq = 1000000000000000ULL / period;
|
||||||
|
mhz = (hpet.freq + 500000) / 1000000;
|
||||||
|
|
||||||
|
print("HPET: %llux %.8ux %d MHz \n", pa, cap, mhz);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uvlong
|
||||||
|
hpetcpufreq(void)
|
||||||
|
{
|
||||||
|
u32int x, y;
|
||||||
|
uvlong a, b;
|
||||||
|
int loops;
|
||||||
|
|
||||||
|
ilock(&hpet);
|
||||||
|
for(loops = 1000;;loops += 1000){
|
||||||
|
cycles(&a);
|
||||||
|
x = hpet.mmio[Ctrlo];
|
||||||
|
aamloop(loops);
|
||||||
|
cycles(&b);
|
||||||
|
y = hpet.mmio[Ctrlo] - x;
|
||||||
|
if(y >= hpet.freq/HZ || loops >= 1000000)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iunlock(&hpet);
|
||||||
|
|
||||||
|
if(m->havetsc && b > a){
|
||||||
|
b -= a;
|
||||||
|
m->cyclefreq = b * hpet.freq / y;
|
||||||
|
m->aalcycles = (b + loops-1) / loops;
|
||||||
|
return m->cyclefreq;
|
||||||
|
}
|
||||||
|
return (vlong)loops*m->aalcycles * hpet.freq / y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hpetinit(void)
|
||||||
|
{
|
||||||
|
uvlong cpufreq;
|
||||||
|
|
||||||
|
if(m->machno != 0){
|
||||||
|
m->cpuhz = MACHP(0)->cpuhz;
|
||||||
|
m->cpumhz = MACHP(0)->cpumhz;
|
||||||
|
m->cyclefreq = MACHP(0)->cyclefreq;
|
||||||
|
m->loopconst = MACHP(0)->loopconst;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* start counting */
|
||||||
|
hpet.mmio[Config] |= 1;
|
||||||
|
|
||||||
|
/* measure loopconst for delay() and tsc frequencies */
|
||||||
|
cpufreq = hpetcpufreq();
|
||||||
|
|
||||||
|
m->loopconst = (cpufreq/1000)/m->aalcycles; /* AAM+LOOP's for 1 ms */
|
||||||
|
m->cpuhz = cpufreq;
|
||||||
|
|
||||||
|
/* round to the nearest megahz */
|
||||||
|
m->cpumhz = (cpufreq+500000)/1000000L;
|
||||||
|
if(m->cpumhz == 0)
|
||||||
|
m->cpumhz = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uvlong
|
||||||
|
hpetread(uvlong *hz)
|
||||||
|
{
|
||||||
|
uvlong ticks;
|
||||||
|
|
||||||
|
if(hz != nil)
|
||||||
|
*hz = hpet.freq;
|
||||||
|
|
||||||
|
ilock(&hpet);
|
||||||
|
ticks = hpet.last;
|
||||||
|
ticks += hpet.mmio[Ctrlo] - (u32int)ticks;
|
||||||
|
hpet.last = ticks;
|
||||||
|
iunlock(&hpet);
|
||||||
|
|
||||||
|
return ticks;
|
||||||
|
}
|
|
@ -115,28 +115,11 @@ i8253reset(void)
|
||||||
iunlock(&i8253);
|
iunlock(&i8253);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static uvlong
|
||||||
i8253init(void)
|
i8253cpufreq(void)
|
||||||
{
|
|
||||||
ioalloc(T0cntr, 4, 0, "i8253");
|
|
||||||
ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl");
|
|
||||||
|
|
||||||
i8253reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
guesscpuhz(int aalcycles)
|
|
||||||
{
|
{
|
||||||
int loops, x, y;
|
int loops, x, y;
|
||||||
uvlong a, b, cpufreq;
|
uvlong a, b;
|
||||||
|
|
||||||
if(m->machno != 0){
|
|
||||||
m->cpuhz = MACHP(0)->cpuhz;
|
|
||||||
m->cpumhz = MACHP(0)->cpumhz;
|
|
||||||
m->cyclefreq = MACHP(0)->cyclefreq;
|
|
||||||
m->loopconst = MACHP(0)->loopconst;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ilock(&i8253);
|
ilock(&i8253);
|
||||||
for(loops = 1000;;loops += 1000) {
|
for(loops = 1000;;loops += 1000) {
|
||||||
|
@ -175,21 +158,38 @@ guesscpuhz(int aalcycles)
|
||||||
if(x == 0)
|
if(x == 0)
|
||||||
x = 1;
|
x = 1;
|
||||||
|
|
||||||
/*
|
|
||||||
* figure out clock frequency and a loop multiplier for delay().
|
|
||||||
* n.b. counter goes up by 2*Freq
|
|
||||||
*/
|
|
||||||
cpufreq = (vlong)loops*((aalcycles*2*Freq)/x);
|
|
||||||
m->loopconst = (cpufreq/1000)/aalcycles; /* AAM+LOOP's for 1 ms */
|
|
||||||
|
|
||||||
/* a == b means virtualbox has confused us */
|
|
||||||
if(m->havetsc && b > a){
|
if(m->havetsc && b > a){
|
||||||
b -= a;
|
b -= a;
|
||||||
b *= 2*Freq;
|
m->cyclefreq = b * 2*Freq / x;
|
||||||
b /= x;
|
m->aalcycles = (b + loops-1) / loops;
|
||||||
m->cyclefreq = b;
|
|
||||||
cpufreq = b;
|
return m->cyclefreq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (vlong)loops*m->aalcycles * 2*Freq / x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
i8253init(void)
|
||||||
|
{
|
||||||
|
uvlong cpufreq;
|
||||||
|
|
||||||
|
if(m->machno != 0){
|
||||||
|
m->cpuhz = MACHP(0)->cpuhz;
|
||||||
|
m->cpumhz = MACHP(0)->cpumhz;
|
||||||
|
m->cyclefreq = MACHP(0)->cyclefreq;
|
||||||
|
m->loopconst = MACHP(0)->loopconst;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ioalloc(T0cntr, 4, 0, "i8253");
|
||||||
|
ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl");
|
||||||
|
|
||||||
|
i8253reset();
|
||||||
|
|
||||||
|
cpufreq = i8253cpufreq();
|
||||||
|
|
||||||
|
m->loopconst = (cpufreq/1000)/m->aalcycles; /* AAM+LOOP's for 1 ms */
|
||||||
m->cpuhz = cpufreq;
|
m->cpuhz = cpufreq;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -281,38 +281,3 @@ i8253read(uvlong *hz)
|
||||||
|
|
||||||
return ticks<<Tickshift;
|
return ticks<<Tickshift;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
delay(int millisecs)
|
|
||||||
{
|
|
||||||
millisecs *= m->loopconst;
|
|
||||||
if(millisecs <= 0)
|
|
||||||
millisecs = 1;
|
|
||||||
aamloop(millisecs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
microdelay(int microsecs)
|
|
||||||
{
|
|
||||||
microsecs *= m->loopconst;
|
|
||||||
microsecs /= 1000;
|
|
||||||
if(microsecs <= 0)
|
|
||||||
microsecs = 1;
|
|
||||||
aamloop(microsecs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* performance measurement ticks. must be low overhead.
|
|
||||||
* doesn't have to count over a second.
|
|
||||||
*/
|
|
||||||
ulong
|
|
||||||
perfticks(void)
|
|
||||||
{
|
|
||||||
uvlong x;
|
|
||||||
|
|
||||||
if(m->havetsc)
|
|
||||||
cycles(&x);
|
|
||||||
else
|
|
||||||
x = 0;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
|
@ -31,10 +31,11 @@ main(void)
|
||||||
quotefmtinstall();
|
quotefmtinstall();
|
||||||
screeninit();
|
screeninit();
|
||||||
print("\nPlan 9\n");
|
print("\nPlan 9\n");
|
||||||
i8253init();
|
|
||||||
cpuidentify();
|
cpuidentify();
|
||||||
meminit0();
|
meminit0();
|
||||||
archinit();
|
archinit();
|
||||||
|
if(arch->clockinit)
|
||||||
|
arch->clockinit();
|
||||||
meminit();
|
meminit();
|
||||||
ramdiskinit();
|
ramdiskinit();
|
||||||
confinit();
|
confinit();
|
||||||
|
|
|
@ -97,7 +97,7 @@ misc
|
||||||
pci pcipc
|
pci pcipc
|
||||||
|
|
||||||
archgeneric devkbd i8259 i8253
|
archgeneric devkbd i8259 i8253
|
||||||
archacpi mp apic squidboy ec
|
archacpi mp apic squidboy ec hpet
|
||||||
archmp mp apic squidboy
|
archmp mp apic squidboy
|
||||||
mtrr
|
mtrr
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ squidboy(Apic* apic)
|
||||||
machinit();
|
machinit();
|
||||||
mmuinit();
|
mmuinit();
|
||||||
cpuidentify();
|
cpuidentify();
|
||||||
|
if(arch->clockinit)
|
||||||
|
arch->clockinit();
|
||||||
cpuidprint();
|
cpuidprint();
|
||||||
syncclock();
|
syncclock();
|
||||||
active.machs[m->machno] = 1;
|
active.machs[m->machno] = 1;
|
||||||
|
|
|
@ -221,6 +221,7 @@ struct Mach
|
||||||
int lastintr;
|
int lastintr;
|
||||||
|
|
||||||
int loopconst;
|
int loopconst;
|
||||||
|
int aalcycles;
|
||||||
|
|
||||||
int cpumhz;
|
int cpumhz;
|
||||||
uvlong cyclefreq; /* Frequency of user readable cycle counter */
|
uvlong cyclefreq; /* Frequency of user readable cycle counter */
|
||||||
|
@ -278,6 +279,7 @@ struct PCArch
|
||||||
void (*introff)(void);
|
void (*introff)(void);
|
||||||
void (*intron)(void);
|
void (*intron)(void);
|
||||||
|
|
||||||
|
void (*clockinit)(void);
|
||||||
void (*clockenable)(void);
|
void (*clockenable)(void);
|
||||||
uvlong (*fastclock)(uvlong*);
|
uvlong (*fastclock)(uvlong*);
|
||||||
void (*timerset)(uvlong);
|
void (*timerset)(uvlong);
|
||||||
|
|
|
@ -52,7 +52,6 @@ u64int getcr4(void);
|
||||||
u64int getxcr0(void);
|
u64int getxcr0(void);
|
||||||
u64int getdr6(void);
|
u64int getdr6(void);
|
||||||
char* getconf(char*);
|
char* getconf(char*);
|
||||||
void guesscpuhz(int);
|
|
||||||
void halt(void);
|
void halt(void);
|
||||||
void mwait(void*);
|
void mwait(void*);
|
||||||
int i8042auxcmd(int);
|
int i8042auxcmd(int);
|
||||||
|
|
|
@ -183,10 +183,11 @@ main(void)
|
||||||
quotefmtinstall();
|
quotefmtinstall();
|
||||||
screeninit();
|
screeninit();
|
||||||
print("\nPlan 9\n");
|
print("\nPlan 9\n");
|
||||||
i8253init();
|
|
||||||
cpuidentify();
|
cpuidentify();
|
||||||
meminit0();
|
meminit0();
|
||||||
archinit();
|
archinit();
|
||||||
|
if(arch->clockinit)
|
||||||
|
arch->clockinit();
|
||||||
meminit();
|
meminit();
|
||||||
ramdiskinit();
|
ramdiskinit();
|
||||||
confinit();
|
confinit();
|
||||||
|
|
|
@ -94,7 +94,7 @@ link
|
||||||
misc
|
misc
|
||||||
pci pcipc
|
pci pcipc
|
||||||
archgeneric devkbd i8259 i8253
|
archgeneric devkbd i8259 i8253
|
||||||
archacpi mp apic squidboy ec
|
archacpi mp apic squidboy ec hpet
|
||||||
archmp mp apic squidboy
|
archmp mp apic squidboy
|
||||||
mtrr
|
mtrr
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ squidboy(Apic* apic)
|
||||||
machinit();
|
machinit();
|
||||||
mmuinit();
|
mmuinit();
|
||||||
cpuidentify();
|
cpuidentify();
|
||||||
|
if(arch->clockinit)
|
||||||
|
arch->clockinit();
|
||||||
cpuidprint();
|
cpuidprint();
|
||||||
syncclock();
|
syncclock();
|
||||||
active.machs[m->machno] = 1;
|
active.machs[m->machno] = 1;
|
||||||
|
|
|
@ -52,10 +52,11 @@ shutdown(void)
|
||||||
HYPERVISOR_shutdown(1);
|
HYPERVISOR_shutdown(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int xenintrassign(Vctl *v);
|
extern int xenintrassign(Vctl *v);
|
||||||
void xentimerenable(void);
|
extern void xentimerinit(void);
|
||||||
uvlong xentimerread(uvlong*);
|
extern void xentimerenable(void);
|
||||||
void xentimerset(uvlong);
|
extern uvlong xentimerread(uvlong*);
|
||||||
|
extern void xentimerset(uvlong);
|
||||||
|
|
||||||
PCArch archxen = {
|
PCArch archxen = {
|
||||||
.id= "Xen",
|
.id= "Xen",
|
||||||
|
@ -63,6 +64,7 @@ PCArch archxen = {
|
||||||
.reset= shutdown,
|
.reset= shutdown,
|
||||||
.intrinit= intrinit,
|
.intrinit= intrinit,
|
||||||
.intrassign= xenintrassign,
|
.intrassign= xenintrassign,
|
||||||
|
.clockinit= xentimerinit,
|
||||||
.clockenable= xentimerenable,
|
.clockenable= xentimerenable,
|
||||||
.fastclock= xentimerread,
|
.fastclock= xentimerread,
|
||||||
.timerset= xentimerset,
|
.timerset= xentimerset,
|
||||||
|
|
|
@ -27,7 +27,6 @@ void (*fprestore)(FPsave*);
|
||||||
void (*fpsave)(FPsave*);
|
void (*fpsave)(FPsave*);
|
||||||
ulong getcr4(void);
|
ulong getcr4(void);
|
||||||
char* getconf(char*);
|
char* getconf(char*);
|
||||||
void guesscpuhz(int);
|
|
||||||
void halt(void);
|
void halt(void);
|
||||||
void mwait(void*);
|
void mwait(void*);
|
||||||
void i8042reset(void);
|
void i8042reset(void);
|
||||||
|
|
|
@ -76,6 +76,8 @@ main(void)
|
||||||
// meminit() is not for us
|
// meminit() is not for us
|
||||||
confinit();
|
confinit();
|
||||||
archinit();
|
archinit();
|
||||||
|
if(arch->clockinit)
|
||||||
|
arch->clockinit();
|
||||||
xinit();
|
xinit();
|
||||||
trapinit();
|
trapinit();
|
||||||
printinit();
|
printinit();
|
||||||
|
|
|
@ -34,7 +34,7 @@ getshadow(void)
|
||||||
|
|
||||||
/* just get it from the shared info */
|
/* just get it from the shared info */
|
||||||
void
|
void
|
||||||
guesscpuhz(int) // XXX no arg!
|
xentimerinit(void)
|
||||||
{
|
{
|
||||||
vcpu_time_info_t *t;
|
vcpu_time_info_t *t;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue