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*
|
||||
findapic(int gsi, int *pintin)
|
||||
{
|
||||
|
@ -569,13 +583,9 @@ acpiinit(void)
|
|||
amlinit();
|
||||
|
||||
/* load DSDT */
|
||||
for(i=0; i<ntblmap; i++){
|
||||
t = tblmap[i];
|
||||
if(memcmp(t->sig, "DSDT", 4) == 0){
|
||||
if((t = findtable("DSDT")) != nil){
|
||||
amlintmask = (~0ULL) >> (t->rev <= 1)*32;
|
||||
amlload(t->data, tbldlen(t));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* load SSDT, there can be multiple tables */
|
||||
|
@ -588,15 +598,10 @@ acpiinit(void)
|
|||
/* set APIC mode */
|
||||
amleval(amlwalk(amlroot, "_PIC"), "i", 1, nil);
|
||||
|
||||
for(i=0; i<ntblmap; i++){
|
||||
t = tblmap[i];
|
||||
if(memcmp(t->sig, "APIC", 4) == 0)
|
||||
goto Foundapic;
|
||||
}
|
||||
t = findtable("APIC");
|
||||
if(t == nil)
|
||||
panic("acpiinit: no MADT (APIC) table");
|
||||
return;
|
||||
|
||||
Foundapic:
|
||||
s = t->data;
|
||||
e = s + tbldlen(t);
|
||||
lapicbase = get32(s); s += 8;
|
||||
|
@ -708,16 +713,12 @@ acpireset(void)
|
|||
{
|
||||
uchar *p;
|
||||
Tbl *t;
|
||||
int i;
|
||||
|
||||
/* stop application processors */
|
||||
mpshutdown();
|
||||
|
||||
/* locate and write platform reset register */
|
||||
for(i=0; i < ntblmap; i++){
|
||||
t = tblmap[i];
|
||||
if(memcmp(t->sig, "FACP", 4) != 0)
|
||||
continue;
|
||||
while((t = findtable("FACP")) != nil){
|
||||
if(get32(t->len) <= 128)
|
||||
break;
|
||||
p = (uchar*)t;
|
||||
|
@ -735,6 +736,11 @@ acpireset(void)
|
|||
|
||||
static int identify(void);
|
||||
extern int i8259irqno(int, int);
|
||||
extern void i8253init(void);
|
||||
|
||||
extern int hpetprobe(uvlong);
|
||||
extern void hpetinit(void);
|
||||
extern uvlong hpetread(uvlong*);
|
||||
|
||||
PCArch archacpi = {
|
||||
.id= "ACPI",
|
||||
|
@ -745,6 +751,7 @@ PCArch archacpi = {
|
|||
.intrirqno= i8259irqno,
|
||||
.intron= lapicintron,
|
||||
.introff= lapicintroff,
|
||||
.clockinit= i8253init,
|
||||
.fastclock= i8253read,
|
||||
.timerset= lapictimerset,
|
||||
};
|
||||
|
@ -782,6 +789,7 @@ identify(void)
|
|||
{
|
||||
uvlong pa;
|
||||
char *cp;
|
||||
Tbl *t;
|
||||
|
||||
if((cp = getconf("*acpi")) == nil)
|
||||
return 1;
|
||||
|
@ -799,12 +807,20 @@ identify(void)
|
|||
maptables();
|
||||
addarchfile("acpitbls", 0444, readtbls, nil);
|
||||
addarchfile("acpimem", 0600, readmem, writemem);
|
||||
if(strcmp(cp, "0") == 0)
|
||||
if(strcmp(cp, "0") == 0 || findtable("APIC") == nil)
|
||||
return 1;
|
||||
if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
|
||||
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)
|
||||
archacpi.fastclock = tscticks;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,41 @@ archreset(void)
|
|||
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 = {
|
||||
.id= "generic",
|
||||
.ident= 0,
|
||||
|
@ -53,6 +88,7 @@ PCArch archgeneric = {
|
|||
.intron= i8259on,
|
||||
.introff= i8259off,
|
||||
|
||||
.clockinit= i8253init,
|
||||
.clockenable= i8253enable,
|
||||
.fastclock= i8253read,
|
||||
.timerset= i8253timerset,
|
||||
|
|
|
@ -229,6 +229,7 @@ struct Mach
|
|||
int lastintr;
|
||||
|
||||
int loopconst;
|
||||
int aalcycles;
|
||||
|
||||
int cpumhz;
|
||||
uvlong cyclefreq; /* Frequency of user readable cycle counter */
|
||||
|
@ -289,6 +290,7 @@ struct PCArch
|
|||
void (*introff)(void);
|
||||
void (*intron)(void);
|
||||
|
||||
void (*clockinit)(void);
|
||||
void (*clockenable)(void);
|
||||
uvlong (*fastclock)(uvlong*);
|
||||
void (*timerset)(uvlong);
|
||||
|
|
|
@ -461,8 +461,6 @@ static X86type x86sis[] =
|
|||
{ -1, -1, 23, "unknown", }, /* total default */
|
||||
};
|
||||
|
||||
static X86type *cputype;
|
||||
|
||||
static void simplecycles(uvlong*);
|
||||
void (*cycles)(uvlong*) = simplecycles;
|
||||
void _cycles(uvlong*); /* in l.s */
|
||||
|
@ -547,6 +545,7 @@ cpuidentify(void)
|
|||
|| (t->family == -1))
|
||||
break;
|
||||
|
||||
m->aalcycles = t->aalcycles;
|
||||
m->cpuidtype = t->name;
|
||||
|
||||
/*
|
||||
|
@ -559,11 +558,6 @@ cpuidentify(void)
|
|||
wrmsr(0x10, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* use i8253 to guess our cpu speed
|
||||
*/
|
||||
guesscpuhz(t->aalcycles);
|
||||
|
||||
/*
|
||||
* If machine check exception, page size extensions or page global bit
|
||||
* are supported enable them in CR4 and clear any other set extensions.
|
||||
|
@ -690,7 +684,6 @@ cpuidentify(void)
|
|||
|
||||
fpuinit();
|
||||
|
||||
cputype = t;
|
||||
return t->family;
|
||||
}
|
||||
|
||||
|
@ -702,7 +695,7 @@ cputyperead(Chan*, void *a, long n, vlong offset)
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -715,7 +708,7 @@ archctlread(Chan*, void *a, long nn, vlong offset)
|
|||
p = buf = smalloc(READSTR);
|
||||
ep = p + READSTR;
|
||||
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" : "");
|
||||
p = seprint(p, ep, "pge %s\n", getcr4()&0x80 ? "on" : "off");
|
||||
p = seprint(p, ep, "coherence ");
|
||||
|
@ -877,6 +870,8 @@ archinit(void)
|
|||
arch->intrinit = knownarch[0]->intrinit;
|
||||
if(arch->intrassign == nil)
|
||||
arch->intrassign = knownarch[0]->intrassign;
|
||||
if(arch->clockinit == nil)
|
||||
arch->clockinit = knownarch[0]->clockinit;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -51,7 +51,6 @@ ulong getcr3(void);
|
|||
ulong getcr4(void);
|
||||
u32int getdr6(void);
|
||||
char* getconf(char*);
|
||||
void guesscpuhz(int);
|
||||
void halt(void);
|
||||
void mwait(void*);
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
i8253init(void)
|
||||
{
|
||||
ioalloc(T0cntr, 4, 0, "i8253");
|
||||
ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl");
|
||||
|
||||
i8253reset();
|
||||
}
|
||||
|
||||
void
|
||||
guesscpuhz(int aalcycles)
|
||||
static uvlong
|
||||
i8253cpufreq(void)
|
||||
{
|
||||
int loops, x, y;
|
||||
uvlong a, b, 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;
|
||||
}
|
||||
uvlong a, b;
|
||||
|
||||
ilock(&i8253);
|
||||
for(loops = 1000;;loops += 1000) {
|
||||
|
@ -175,21 +158,38 @@ guesscpuhz(int aalcycles)
|
|||
if(x == 0)
|
||||
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){
|
||||
b -= a;
|
||||
b *= 2*Freq;
|
||||
b /= x;
|
||||
m->cyclefreq = b;
|
||||
cpufreq = b;
|
||||
m->cyclefreq = b * 2*Freq / x;
|
||||
m->aalcycles = (b + loops-1) / loops;
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -281,38 +281,3 @@ i8253read(uvlong *hz)
|
|||
|
||||
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();
|
||||
screeninit();
|
||||
print("\nPlan 9\n");
|
||||
i8253init();
|
||||
cpuidentify();
|
||||
meminit0();
|
||||
archinit();
|
||||
if(arch->clockinit)
|
||||
arch->clockinit();
|
||||
meminit();
|
||||
ramdiskinit();
|
||||
confinit();
|
||||
|
|
|
@ -97,7 +97,7 @@ misc
|
|||
pci pcipc
|
||||
|
||||
archgeneric devkbd i8259 i8253
|
||||
archacpi mp apic squidboy ec
|
||||
archacpi mp apic squidboy ec hpet
|
||||
archmp mp apic squidboy
|
||||
mtrr
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ squidboy(Apic* apic)
|
|||
machinit();
|
||||
mmuinit();
|
||||
cpuidentify();
|
||||
if(arch->clockinit)
|
||||
arch->clockinit();
|
||||
cpuidprint();
|
||||
syncclock();
|
||||
active.machs[m->machno] = 1;
|
||||
|
|
|
@ -221,6 +221,7 @@ struct Mach
|
|||
int lastintr;
|
||||
|
||||
int loopconst;
|
||||
int aalcycles;
|
||||
|
||||
int cpumhz;
|
||||
uvlong cyclefreq; /* Frequency of user readable cycle counter */
|
||||
|
@ -278,6 +279,7 @@ struct PCArch
|
|||
void (*introff)(void);
|
||||
void (*intron)(void);
|
||||
|
||||
void (*clockinit)(void);
|
||||
void (*clockenable)(void);
|
||||
uvlong (*fastclock)(uvlong*);
|
||||
void (*timerset)(uvlong);
|
||||
|
|
|
@ -52,7 +52,6 @@ u64int getcr4(void);
|
|||
u64int getxcr0(void);
|
||||
u64int getdr6(void);
|
||||
char* getconf(char*);
|
||||
void guesscpuhz(int);
|
||||
void halt(void);
|
||||
void mwait(void*);
|
||||
int i8042auxcmd(int);
|
||||
|
|
|
@ -183,10 +183,11 @@ main(void)
|
|||
quotefmtinstall();
|
||||
screeninit();
|
||||
print("\nPlan 9\n");
|
||||
i8253init();
|
||||
cpuidentify();
|
||||
meminit0();
|
||||
archinit();
|
||||
if(arch->clockinit)
|
||||
arch->clockinit();
|
||||
meminit();
|
||||
ramdiskinit();
|
||||
confinit();
|
||||
|
|
|
@ -94,7 +94,7 @@ link
|
|||
misc
|
||||
pci pcipc
|
||||
archgeneric devkbd i8259 i8253
|
||||
archacpi mp apic squidboy ec
|
||||
archacpi mp apic squidboy ec hpet
|
||||
archmp mp apic squidboy
|
||||
mtrr
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ squidboy(Apic* apic)
|
|||
machinit();
|
||||
mmuinit();
|
||||
cpuidentify();
|
||||
if(arch->clockinit)
|
||||
arch->clockinit();
|
||||
cpuidprint();
|
||||
syncclock();
|
||||
active.machs[m->machno] = 1;
|
||||
|
|
|
@ -52,10 +52,11 @@ shutdown(void)
|
|||
HYPERVISOR_shutdown(1);
|
||||
}
|
||||
|
||||
int xenintrassign(Vctl *v);
|
||||
void xentimerenable(void);
|
||||
uvlong xentimerread(uvlong*);
|
||||
void xentimerset(uvlong);
|
||||
extern int xenintrassign(Vctl *v);
|
||||
extern void xentimerinit(void);
|
||||
extern void xentimerenable(void);
|
||||
extern uvlong xentimerread(uvlong*);
|
||||
extern void xentimerset(uvlong);
|
||||
|
||||
PCArch archxen = {
|
||||
.id= "Xen",
|
||||
|
@ -63,6 +64,7 @@ PCArch archxen = {
|
|||
.reset= shutdown,
|
||||
.intrinit= intrinit,
|
||||
.intrassign= xenintrassign,
|
||||
.clockinit= xentimerinit,
|
||||
.clockenable= xentimerenable,
|
||||
.fastclock= xentimerread,
|
||||
.timerset= xentimerset,
|
||||
|
|
|
@ -27,7 +27,6 @@ void (*fprestore)(FPsave*);
|
|||
void (*fpsave)(FPsave*);
|
||||
ulong getcr4(void);
|
||||
char* getconf(char*);
|
||||
void guesscpuhz(int);
|
||||
void halt(void);
|
||||
void mwait(void*);
|
||||
void i8042reset(void);
|
||||
|
|
|
@ -76,6 +76,8 @@ main(void)
|
|||
// meminit() is not for us
|
||||
confinit();
|
||||
archinit();
|
||||
if(arch->clockinit)
|
||||
arch->clockinit();
|
||||
xinit();
|
||||
trapinit();
|
||||
printinit();
|
||||
|
|
|
@ -34,7 +34,7 @@ getshadow(void)
|
|||
|
||||
/* just get it from the shared info */
|
||||
void
|
||||
guesscpuhz(int) // XXX no arg!
|
||||
xentimerinit(void)
|
||||
{
|
||||
vcpu_time_info_t *t;
|
||||
|
||||
|
|
Loading…
Reference in a new issue