changeset 28d6ff8b94e2 in /z/repo/m5 details: http://repo.m5sim.org/m5?cmd=changeset;node=28d6ff8b94e2 description: X86: Make the local APIC timer event generate an interrupt.
diffstat: 2 files changed, 26 insertions(+) src/arch/x86/interrupts.cc | 21 +++++++++++++++++++++ src/arch/x86/interrupts.hh | 5 +++++ diffs (229 lines): diff -r 0fee2dde61d7 -r 28d6ff8b94e2 src/arch/x86/interrupts.cc --- a/src/arch/x86/interrupts.cc Sun Oct 12 23:28:11 2008 -0700 +++ b/src/arch/x86/interrupts.cc Sun Oct 12 23:28:49 2008 -0700 @@ -240,6 +240,48 @@ setReg(reg, gtoh(val)); return latency; } +void +X86ISA::Interrupts::requestInterrupt(uint8_t vector, + uint8_t deliveryMode, bool level) +{ + /* + * Fixed and lowest-priority delivery mode interrupts are handled + * using the IRR/ISR registers, checking against the TPR, etc. + * The SMI, NMI, ExtInt, INIT, etc interrupts go straight through. + */ + if (deliveryMode == DeliveryMode::Fixed || + deliveryMode == DeliveryMode::LowestPriority) { + DPRINTF(LocalApic, "Interrupt is an %s.\n", + DeliveryMode::names[deliveryMode]); + // Queue up the interrupt in the IRR. + if (vector > IRRV) + IRRV = vector; + if (!getRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector)) { + setRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector); + if (level) { + setRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); + } else { + clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); + } + } + } else if (!DeliveryMode::isReserved(deliveryMode)) { + DPRINTF(LocalApic, "Interrupt is an %s.\n", + DeliveryMode::names[deliveryMode]); + if (deliveryMode == DeliveryMode::SMI && !pendingSmi) { + pendingUnmaskableInt = pendingSmi = true; + smiVector = vector; + } else if (deliveryMode == DeliveryMode::NMI && !pendingNmi) { + pendingUnmaskableInt = pendingNmi = true; + nmiVector = vector; + } else if (deliveryMode == DeliveryMode::ExtInt && !pendingExtInt) { + pendingExtInt = true; + extIntVector = vector; + } else if (deliveryMode == DeliveryMode::INIT && !pendingInit) { + pendingUnmaskableInt = pendingInit = true; + initVector = vector; + } + } +} Tick X86ISA::Interrupts::recvMessage(PacketPtr pkt) @@ -260,49 +302,8 @@ assert((message.destMode == 0 && message.destination == id) || (bits((int)message.destination, id))); - /* - * Fixed and lowest-priority delivery mode interrupts are handled - * using the IRR/ISR registers, checking against the TPR, etc. - * The SMI, NMI, ExtInt, INIT, etc interrupts go straight through. - */ - if (message.deliveryMode == DeliveryMode::Fixed || - message.deliveryMode == DeliveryMode::LowestPriority) { - DPRINTF(LocalApic, "Interrupt is an %s.\n", - DeliveryMode::names[message.deliveryMode]); - // Queue up the interrupt in the IRR. - if (vector > IRRV) - IRRV = vector; - if (!getRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector)) { - setRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector); - if (message.trigger) { - // Level triggered. - setRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); - } else { - // Edge triggered. - clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); - } - } - } else if (!DeliveryMode::isReserved(message.deliveryMode)) { - DPRINTF(LocalApic, "Interrupt is an %s.\n", - DeliveryMode::names[message.deliveryMode]); - if (message.deliveryMode == DeliveryMode::SMI && - !pendingSmi) { - pendingUnmaskableInt = pendingSmi = true; - smiMessage = message; - } else if (message.deliveryMode == DeliveryMode::NMI && - !pendingNmi) { - pendingUnmaskableInt = pendingNmi = true; - nmiMessage = message; - } else if (message.deliveryMode == DeliveryMode::ExtInt && - !pendingExtInt) { - pendingExtInt = true; - extIntMessage = message; - } else if (message.deliveryMode == DeliveryMode::INIT && - !pendingInit) { - pendingUnmaskableInt = pendingInit = true; - initMessage = message; - } - } + requestInterrupt(message.vector, + message.deliveryMode, message.trigger); } break; default: @@ -503,10 +504,10 @@ return new SystemManagementInterrupt(); } else if (pendingNmi) { DPRINTF(LocalApic, "Generated NMI fault object.\n"); - return new NonMaskableInterrupt(nmiMessage.vector); + return new NonMaskableInterrupt(nmiVector); } else if (pendingInit) { DPRINTF(LocalApic, "Generated INIT fault object.\n"); - return new InitInterrupt(initMessage.vector); + return new InitInterrupt(initVector); } else { panic("pendingUnmaskableInt set, but no unmaskable " "ints were pending.\n"); @@ -514,7 +515,7 @@ } } else if (pendingExtInt) { DPRINTF(LocalApic, "Generated external interrupt fault object.\n"); - return new ExternalInterrupt(extIntMessage.vector); + return new ExternalInterrupt(extIntVector); } else { DPRINTF(LocalApic, "Generated regular interrupt fault object.\n"); // The only thing left are fixed and lowest priority interrupts. diff -r 0fee2dde61d7 -r 28d6ff8b94e2 src/arch/x86/interrupts.hh --- a/src/arch/x86/interrupts.hh Sun Oct 12 23:28:11 2008 -0700 +++ b/src/arch/x86/interrupts.hh Sun Oct 12 23:28:49 2008 -0700 @@ -79,6 +79,17 @@ // Storage for the APIC registers uint32_t regs[NUM_APIC_REGS]; + BitUnion32(LVTEntry) + Bitfield<7, 0> vector; + Bitfield<10, 8> deliveryMode; + Bitfield<12> status; + Bitfield<13> polarity; + Bitfield<14> remoteIRR; + Bitfield<15> trigger; + Bitfield<16> masked; + Bitfield<17> periodic; + EndBitUnion(LVTEntry) + /* * Timing related stuff. */ @@ -87,13 +98,20 @@ class ApicTimerEvent : public Event { + private: + Interrupts *localApic; public: - ApicTimerEvent() : Event() + ApicTimerEvent(Interrupts *_localApic) : + Event(), localApic(_localApic) {} void process() { - warn("Local APIC timer event doesn't do anything!\n"); + assert(localApic); + if (localApic->triggerTimerInterrupt()) { + localApic->setReg(APIC_INITIAL_COUNT, + localApic->readReg(APIC_INITIAL_COUNT)); + } } }; @@ -104,13 +122,13 @@ * the IRR. */ bool pendingSmi; - TriggerIntMessage smiMessage; + uint8_t smiVector; bool pendingNmi; - TriggerIntMessage nmiMessage; + uint8_t nmiVector; bool pendingExtInt; - TriggerIntMessage extIntMessage; + uint8_t extIntVector; bool pendingInit; - TriggerIntMessage initMessage; + uint8_t initVector; // This is a quick check whether any of the above (except ExtInt) are set. bool pendingUnmaskableInt; @@ -163,6 +181,8 @@ return bits(regs[base + (vector % 32)], vector >> 5); } + void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level); + public: /* * Params stuff. @@ -186,6 +206,15 @@ Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); Tick recvMessage(PacketPtr pkt); + + bool + triggerTimerInterrupt() + { + LVTEntry entry = regs[APIC_LVT_TIMER]; + if (!entry.masked) + requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger); + return entry.periodic; + } void addressRanges(AddrRangeList &range_list) { @@ -225,10 +254,11 @@ Interrupts(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), clock(0), - pendingSmi(false), smiMessage(0), - pendingNmi(false), nmiMessage(0), - pendingExtInt(false), extIntMessage(0), - pendingInit(false), initMessage(0), + apicTimerEvent(this), + pendingSmi(false), smiVector(0), + pendingNmi(false), nmiVector(0), + pendingExtInt(false), extIntVector(0), + pendingInit(false), initVector(0), pendingUnmaskableInt(false) { pioSize = PageBytes; _______________________________________________ m5-dev mailing list m5-dev@m5sim.org http://m5sim.org/mailman/listinfo/m5-dev