diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-06-24 05:34:17 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-06-24 05:34:17 +0200 |
commit | 7417118d301be3c65bfcfe82005f5ea2d01d1819 (patch) | |
tree | 2e89814a862323a0b34428068110c6d8629b18f7 /sys/src/9/pc/apic.c | |
parent | 0209e21f454b256cd0a67d744baa8f6e7375fb9c (diff) |
apic: fix qemu panic lapic clock xxx > cpu clock > yyy
Diffstat (limited to 'sys/src/9/pc/apic.c')
-rw-r--r-- | sys/src/9/pc/apic.c | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/sys/src/9/pc/apic.c b/sys/src/9/pc/apic.c index b2ed0aa9a..0788e5adf 100644 --- a/sys/src/9/pc/apic.c +++ b/sys/src/9/pc/apic.c @@ -76,15 +76,15 @@ enum { /* LapicTIMER */ LapicDIVIDER = 0x00080000, /* use output of the divider */ }; -enum { /* LapicTDCR */ - LapicX2 = 0x00000000, /* divide by 2 */ - LapicX4 = 0x00000001, /* divide by 4 */ - LapicX8 = 0x00000002, /* divide by 8 */ - LapicX16 = 0x00000003, /* divide by 16 */ - LapicX32 = 0x00000008, /* divide by 32 */ - LapicX64 = 0x00000009, /* divide by 64 */ - LapicX128 = 0x0000000A, /* divide by 128 */ - LapicX1 = 0x0000000B, /* divide by 1 */ +static uchar lapictdxtab[] = { /* LapicTDCR */ + 0x0B, /* divide by 1 */ + 0x00, /* divide by 2 */ + 0x01, /* divide by 4 */ + 0x02, /* divide by 8 */ + 0x03, /* divide by 16 */ + 0x08, /* divide by 32 */ + 0x09, /* divide by 64 */ + 0x0A, /* divide by 128 */ }; static ulong* lapicbase; @@ -95,6 +95,7 @@ struct ulong max; ulong min; ulong div; + int tdx; } lapictimer; static ulong @@ -132,13 +133,13 @@ lapiconline(void) static void lapictimerinit(void) { - uvlong x, v, hz; - - v = m->cpuhz/1000; - lapicw(LapicTDCR, LapicX1); +Retry: + lapicw(LapicTDCR, lapictdxtab[lapictimer.tdx]); lapicw(LapicTIMER, ApicIMASK|LapicCLKIN|LapicONESHOT|(VectorPIC+IrqTIMER)); if(lapictimer.hz == 0ULL){ + uvlong x, v, hz; + x = fastticks(&hz); x += hz/10; lapicw(LapicTICR, 0xffffffff); @@ -146,17 +147,20 @@ lapictimerinit(void) v = fastticks(nil); }while(v < x); - lapictimer.hz = (0xffffffffUL-lapicr(LapicTCCR))*10; - lapictimer.max = lapictimer.hz/HZ; - lapictimer.min = lapictimer.hz/(100*HZ); - - if(lapictimer.hz > hz-(hz/10)){ - if(lapictimer.hz > hz+(hz/10)) - panic("lapic clock %lld > cpu clock > %lld", - lapictimer.hz, hz); - lapictimer.hz = hz; + 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; } + assert(v != 0); + + lapictimer.hz = v; lapictimer.div = hz/lapictimer.hz; + lapictimer.max = lapictimer.hz/HZ; + lapictimer.min = lapictimer.hz/(100*HZ); } } |