57a58
> #include "arch/x86/apicregs.hh"
61c62,63
< int divideFromConf(uint32_t conf)
---
> int
> divideFromConf(uint32_t conf)
71,72c73
< uint32_t
< X86ISA::Interrupts::readRegNoEffect(ApicRegIndex reg)
---
> namespace X86ISA
74c75,205
< return regs[reg];
---
>
> ApicRegIndex
> decodeAddr(Addr paddr)
> {
> ApicRegIndex regNum;
> paddr &= ~mask(3);
> switch (paddr)
> {
> case 0x20:
> regNum = APIC_ID;
> break;
> case 0x30:
> regNum = APIC_VERSION;
> break;
> case 0x80:
> regNum = APIC_TASK_PRIORITY;
> break;
> case 0x90:
> regNum = APIC_ARBITRATION_PRIORITY;
> break;
> case 0xA0:
> regNum = APIC_PROCESSOR_PRIORITY;
> break;
> case 0xB0:
> regNum = APIC_EOI;
> break;
> case 0xD0:
> regNum = APIC_LOGICAL_DESTINATION;
> break;
> case 0xE0:
> regNum = APIC_DESTINATION_FORMAT;
> break;
> case 0xF0:
> regNum = APIC_SPURIOUS_INTERRUPT_VECTOR;
> break;
> case 0x100:
> case 0x108:
> case 0x110:
> case 0x118:
> case 0x120:
> case 0x128:
> case 0x130:
> case 0x138:
> case 0x140:
> case 0x148:
> case 0x150:
> case 0x158:
> case 0x160:
> case 0x168:
> case 0x170:
> case 0x178:
> regNum = APIC_IN_SERVICE((paddr - 0x100) / 0x8);
> break;
> case 0x180:
> case 0x188:
> case 0x190:
> case 0x198:
> case 0x1A0:
> case 0x1A8:
> case 0x1B0:
> case 0x1B8:
> case 0x1C0:
> case 0x1C8:
> case 0x1D0:
> case 0x1D8:
> case 0x1E0:
> case 0x1E8:
> case 0x1F0:
> case 0x1F8:
> regNum = APIC_TRIGGER_MODE((paddr - 0x180) / 0x8);
> break;
> case 0x200:
> case 0x208:
> case 0x210:
> case 0x218:
> case 0x220:
> case 0x228:
> case 0x230:
> case 0x238:
> case 0x240:
> case 0x248:
> case 0x250:
> case 0x258:
> case 0x260:
> case 0x268:
> case 0x270:
> case 0x278:
> regNum = APIC_INTERRUPT_REQUEST((paddr - 0x200) / 0x8);
> break;
> case 0x280:
> regNum = APIC_ERROR_STATUS;
> break;
> case 0x300:
> regNum = APIC_INTERRUPT_COMMAND_LOW;
> break;
> case 0x310:
> regNum = APIC_INTERRUPT_COMMAND_HIGH;
> break;
> case 0x320:
> regNum = APIC_LVT_TIMER;
> break;
> case 0x330:
> regNum = APIC_LVT_THERMAL_SENSOR;
> break;
> case 0x340:
> regNum = APIC_LVT_PERFORMANCE_MONITORING_COUNTERS;
> break;
> case 0x350:
> regNum = APIC_LVT_LINT0;
> break;
> case 0x360:
> regNum = APIC_LVT_LINT1;
> break;
> case 0x370:
> regNum = APIC_LVT_ERROR;
> break;
> case 0x380:
> regNum = APIC_INITIAL_COUNT;
> break;
> case 0x390:
> regNum = APIC_CURRENT_COUNT;
> break;
> case 0x3E0:
> regNum = APIC_DIVIDE_CONFIGURATION;
> break;
> default:
> // A reserved register field.
> panic("Accessed reserved register field %#x.\n", paddr);
> break;
> }
> return regNum;
75a207
> }
76a209,235
> Tick
> X86ISA::Interrupts::read(PacketPtr pkt)
> {
> Addr offset = pkt->getAddr() - pioAddr;
> //Make sure we're at least only accessing one register.
> if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
> panic("Accessed more than one register at a time in the APIC!\n");
> ApicRegIndex reg = decodeAddr(offset);
> uint32_t val = htog(readReg(reg));
> pkt->setData(((uint8_t *)&val) + (offset & mask(3)));
> return latency;
> }
>
> Tick
> X86ISA::Interrupts::write(PacketPtr pkt)
> {
> Addr offset = pkt->getAddr() - pioAddr;
> //Make sure we're at least only accessing one register.
> if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
> panic("Accessed more than one register at a time in the APIC!\n");
> ApicRegIndex reg = decodeAddr(offset);
> uint32_t val = regs[reg];
> pkt->writeData(((uint8_t *)&val) + (offset & mask(3)));
> setReg(reg, gtoh(val));
> return latency;
> }
>
78c237
< X86ISA::Interrupts::readReg(ApicRegIndex reg, ThreadContext * tc)
---
> X86ISA::Interrupts::readReg(ApicRegIndex reg)
107c266,267
< uint32_t val = regs[reg] - tc->getCpuPtr()->curCycle();
---
> assert(clock);
> uint32_t val = regs[reg] - curTick / clock;
114c274
< return readRegNoEffect(reg);
---
> return regs[reg];
118c278
< X86ISA::Interrupts::setRegNoEffect(ApicRegIndex reg, uint32_t val)
---
> X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
120,125d279
< regs[reg] = val;
< }
<
< void
< X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc)
< {
204,208c358,375
< newVal = bits(val, 31, 0);
< regs[APIC_CURRENT_COUNT] =
< tc->getCpuPtr()->curCycle() +
< (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])) * newVal;
< //FIXME This should schedule the timer event.
---
> {
> assert(clock);
> newVal = bits(val, 31, 0);
> uint32_t newCount = newVal *
> (divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]) * 16);
> regs[APIC_CURRENT_COUNT] = newCount + curTick / clock;
> // 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.
> Tick offset = curTick % timerTick;
> if (offset) {
> reschedule(apicTimerEvent,
> curTick + (newCount + 1) * timerTick - offset, true);
> } else {
> reschedule(apicTimerEvent,
> curTick + newCount * timerTick, true);
> }
> }
219c386
< setRegNoEffect(reg, newVal);
---
> regs[reg] = newVal;