merge
This commit is contained in:
commit
f8787d5815
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