ref: 0ac66d07b30852f78ac2464f41a808cf16f1dfa4
parent: 649cb3123140ce354c34f3be50d19dc7536a5425
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Sun Jun 24 01:34:17 EDT 2012
apic: fix qemu panic lapic clock xxx > cpu clock > yyy
--- a/sys/src/9/pc/apic.c
+++ b/sys/src/9/pc/apic.c
@@ -76,15 +76,15 @@
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 @@
ulong max;
ulong min;
ulong div;
+ int tdx;
} lapictimer;
static ulong
@@ -132,13 +133,13 @@
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 @@
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);
}
}
--
⑨