X86: Fix the time keeping of the Local APIC timer.
This commit is contained in:
parent
1c5b9773bd
commit
6b60a29706
1 changed files with 19 additions and 12 deletions
|
@ -344,10 +344,19 @@ X86ISA::Interrupts::readReg(ApicRegIndex reg)
|
||||||
break;
|
break;
|
||||||
case APIC_CURRENT_COUNT:
|
case APIC_CURRENT_COUNT:
|
||||||
{
|
{
|
||||||
assert(clock);
|
if (apicTimerEvent.scheduled()) {
|
||||||
uint32_t val = regs[reg] - curTick / clock;
|
assert(clock);
|
||||||
val /= (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]));
|
// Compute how many m5 ticks happen per count.
|
||||||
return val;
|
uint64_t ticksPerCount = clock *
|
||||||
|
divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]);
|
||||||
|
// Compute how many m5 ticks are left.
|
||||||
|
uint64_t val = apicTimerEvent.when() - curTick;
|
||||||
|
// Turn that into a count.
|
||||||
|
val = (val + ticksPerCount - 1) / ticksPerCount;
|
||||||
|
return val;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -441,19 +450,17 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
|
||||||
{
|
{
|
||||||
assert(clock);
|
assert(clock);
|
||||||
newVal = bits(val, 31, 0);
|
newVal = bits(val, 31, 0);
|
||||||
uint32_t newCount = newVal *
|
// Compute how many timer ticks we're being programmed for.
|
||||||
(divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]) * 16);
|
uint64_t newCount = newVal *
|
||||||
regs[APIC_CURRENT_COUNT] = newCount + curTick / clock;
|
(divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]));
|
||||||
// Find out how long a "tick" of the timer should take.
|
|
||||||
Tick timerTick = 16 * clock;
|
|
||||||
// Schedule on the edge of the next tick plus the new count.
|
// Schedule on the edge of the next tick plus the new count.
|
||||||
Tick offset = curTick % timerTick;
|
Tick offset = curTick % clock;
|
||||||
if (offset) {
|
if (offset) {
|
||||||
reschedule(apicTimerEvent,
|
reschedule(apicTimerEvent,
|
||||||
curTick + (newCount + 1) * timerTick - offset, true);
|
curTick + (newCount + 1) * clock - offset, true);
|
||||||
} else {
|
} else {
|
||||||
reschedule(apicTimerEvent,
|
reschedule(apicTimerEvent,
|
||||||
curTick + newCount * timerTick, true);
|
curTick + newCount * clock, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue