diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-06-22 09:50:34 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-06-22 09:50:34 +0200 |
commit | 04b78032914d58a33745a1a13e2e3de99a7d94b4 (patch) | |
tree | 5c89032ea3d9c85a5836f4e8f73fbf5451809d06 /sys/src/9/pc/apic.c | |
parent | e38938384faa8857471fab0c05ade056b55fb360 (diff) |
apic: eleminate splhi and apictimerlock, per cpu apictimer structure
the splhi() and apictimerlock in the Mach isnt neccesary, as
portclock always holds the ilock of the per mach timer queue
when calling timerset().
as fastticks() and the portclock timers are all handled on a
per processor basis, i think it should be theoretically possible
for the lapics to run at different frequencies. so we measure
the lapic frequency for each individual lapic and keep them in
a per processor Apictimer structure instead of assuming them
to be the same.
Diffstat (limited to 'sys/src/9/pc/apic.c')
-rw-r--r-- | sys/src/9/pc/apic.c | 96 |
1 files changed, 53 insertions, 43 deletions
diff --git a/sys/src/9/pc/apic.c b/sys/src/9/pc/apic.c index 4e006e8fb..f27adb81e 100644 --- a/sys/src/9/pc/apic.c +++ b/sys/src/9/pc/apic.c @@ -89,14 +89,17 @@ static uchar lapictdxtab[] = { /* LapicTDCR */ static ulong* lapicbase; -struct +typedef struct Apictimer Apictimer; +struct Apictimer { uvlong hz; ulong max; ulong min; ulong div; int tdx; -} lapictimer; +}; + +static Apictimer lapictimer[MAXMACH]; static ulong lapicr(int r) @@ -115,20 +118,24 @@ lapicw(int r, ulong data) void lapiconline(void) { + Apictimer *a; + + a = &lapictimer[m->machno]; + /* * Reload the timer to de-synchronise the processors, * then lower the task priority to allow interrupts to be * accepted by the APIC. */ microdelay((TK2MS(1)*1000/conf.nmach) * m->machno); - lapicw(LapicTICR, lapictimer.max); + lapicw(LapicTICR, a->max); lapicw(LapicTIMER, LapicCLKIN|LapicPERIODIC|(VectorPIC+IrqTIMER)); /* * not strickly neccesary, but reported (osdev.org) to be * required for some machines. */ - lapicw(LapicTDCR, lapictdxtab[lapictimer.tdx]); + lapicw(LapicTDCR, lapictdxtab[a->tdx]); lapicw(LapicTPR, 0); } @@ -139,35 +146,44 @@ lapiconline(void) static void lapictimerinit(void) { + uvlong x, v, hz; + Apictimer *a; + int s; + + s = splhi(); + a = &lapictimer[m->machno]; + a->tdx = 0; Retry: lapicw(LapicTIMER, ApicIMASK|LapicCLKIN|LapicONESHOT|(VectorPIC+IrqTIMER)); - lapicw(LapicTDCR, lapictdxtab[lapictimer.tdx]); - - if(lapictimer.hz == 0ULL){ - uvlong x, v, hz; - - x = fastticks(&hz); - x += hz/10; - lapicw(LapicTICR, 0xffffffff); - do{ - v = fastticks(nil); - }while(v < x); - - v = (0xffffffffUL-lapicr(LapicTCCR))*10; - if(v > hz-(hz/10)){ - if(v > hz+(hz/10) && lapictimer.tdx < nelem(lapictdxtab)-1){ - lapictimer.tdx++; - goto Retry; - } - v = hz; + lapicw(LapicTDCR, lapictdxtab[a->tdx]); + + x = fastticks(&hz); + x += hz/10; + lapicw(LapicTICR, 0xffffffff); + do{ + v = fastticks(nil); + }while(v < x); + + v = (0xffffffffUL-lapicr(LapicTCCR))*10; + if(v > hz-(hz/10)){ + if(v > hz+(hz/10) && a->tdx < nelem(lapictdxtab)-1){ + a->tdx++; + goto Retry; } - assert(v != 0); - - lapictimer.hz = v; - lapictimer.div = hz/lapictimer.hz; - lapictimer.max = lapictimer.hz/HZ; - lapictimer.min = lapictimer.hz/(100*HZ); + v = hz; } + + assert(v >= (100*HZ)); + + a->hz = v; + a->div = hz/a->hz; + a->max = a->hz/HZ; + a->min = a->hz/(100*HZ); + + splx(s); + + v = (v+500000LL)/1000000LL; + print("cpu%d: lapic clock at %lludMHz\n", m->machno, v); } void @@ -377,25 +393,19 @@ void lapictimerset(uvlong next) { vlong period; - int x; + Apictimer *a; - x = splhi(); - lock(&m->apictimerlock); - - period = lapictimer.max; + a = &lapictimer[m->machno]; + period = a->max; if(next != 0){ period = next - fastticks(nil); - period /= lapictimer.div; - - if(period < lapictimer.min) - period = lapictimer.min; - else if(period > lapictimer.max - lapictimer.min) - period = lapictimer.max; + period /= a->div; + if(period < a->min) + period = a->min; + else if(period > a->max - a->min) + period = a->max; } lapicw(LapicTICR, period); - - unlock(&m->apictimerlock); - splx(x); } void |