#include "sim/eventq.hh"
class ThreadContext;
+class BaseCPU;
-namespace X86ISA
-{
+namespace X86ISA {
class Interrupts : public BasicPioDevice, IntDev
{
// 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.
*/
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));
+ }
}
};
* 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;
+ bool pendingStartup;
+ uint8_t startupVector;
+ bool startedUp;
// This is a quick check whether any of the above (except ExtInt) are set.
bool pendingUnmaskableInt;
+ // A count of how many IPIs are in flight.
+ int pendingIPIs;
+
/*
* IRR and ISR maintenance.
*/
void
setRegArrayBit(ApicRegIndex base, uint8_t vector)
{
- regs[base + (vector % 32)] |= (1 << (vector >> 5));
+ regs[base + (vector / 32)] |= (1 << (vector % 32));
}
void
clearRegArrayBit(ApicRegIndex base, uint8_t vector)
{
- regs[base + (vector % 32)] &= ~(1 << (vector >> 5));
+ regs[base + (vector / 32)] &= ~(1 << (vector % 32));
}
bool
getRegArrayBit(ApicRegIndex base, uint8_t vector)
{
- return bits(regs[base + (vector % 32)], vector >> 5);
+ return bits(regs[base + (vector / 32)], vector % 5);
}
+ void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
+
+ BaseCPU *cpu;
+
+ int initialApicId;
+
public:
/*
* Params stuff.
*/
typedef X86LocalApicParams Params;
- void setClock(Tick newClock)
+ void setCPU(BaseCPU * newCPU);
+
+ void
+ setClock(Tick newClock)
{
clock = newClock;
}
return dynamic_cast<const Params *>(_params);
}
+ /*
+ * Initialize this object by registering it with the IO APIC.
+ */
+ void init();
+
/*
* Functions to interact with the interrupt port from IntDev.
*/
Tick read(PacketPtr pkt);
Tick write(PacketPtr pkt);
Tick recvMessage(PacketPtr pkt);
+ Tick recvResponse(PacketPtr pkt);
- void addressRanges(AddrRangeList &range_list)
+ bool
+ triggerTimerInterrupt()
{
- range_list.clear();
- range_list.push_back(RangeEx(x86LocalAPICAddress(0, 0),
- x86LocalAPICAddress(0, 0) + PageBytes));
+ LVTEntry entry = regs[APIC_LVT_TIMER];
+ if (!entry.masked)
+ requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger);
+ return entry.periodic;
}
- void getIntAddrRange(AddrRangeList &range_list)
- {
- range_list.clear();
- range_list.push_back(RangeEx(x86InterruptAddress(0, 0),
- x86InterruptAddress(0, 0) + PhysAddrAPICRangeSize));
- }
+ void addressRanges(AddrRangeList &range_list);
+ void getIntAddrRange(AddrRangeList &range_list);
Port *getPort(const std::string &if_name, int idx = -1)
{
uint32_t readReg(ApicRegIndex miscReg);
void setReg(ApicRegIndex reg, uint32_t val);
- void setRegNoEffect(ApicRegIndex reg, uint32_t val)
+ void
+ setRegNoEffect(ApicRegIndex reg, uint32_t val)
{
regs[reg] = val;
}
* Constructor.
*/
- 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),
- pendingUnmaskableInt(false)
- {
- pioSize = PageBytes;
- memset(regs, 0, sizeof(regs));
- //Set the local apic DFR to the flat model.
- regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1);
- ISRV = 0;
- IRRV = 0;
- }
+ Interrupts(Params * p);
/*
* Functions for retrieving interrupts for the CPU to handle.
*/
- bool check_interrupts(ThreadContext * tc) const;
- Fault getInterrupt(ThreadContext * tc);
- void updateIntrInfo(ThreadContext * tc);
+ bool checkInterrupts(ThreadContext *tc) const;
+ Fault getInterrupt(ThreadContext *tc);
+ void updateIntrInfo(ThreadContext *tc);
/*
* Serialization.
*/
- void serialize(std::ostream & os)
+ void
+ serialize(std::ostream &os)
{
panic("Interrupts::serialize unimplemented!\n");
}
- void unserialize(Checkpoint * cp, const std::string & section)
+ void
+ unserialize(Checkpoint *cp, const std::string §ion)
{
panic("Interrupts::unserialize unimplemented!\n");
}
* Old functions needed for compatability but which will be phased out
* eventually.
*/
- void post(int int_num, int index)
+ void
+ post(int int_num, int index)
{
panic("Interrupts::post unimplemented!\n");
}
- void clear(int int_num, int index)
+ void
+ clear(int int_num, int index)
{
panic("Interrupts::clear unimplemented!\n");
}
- void clear_all()
+ void
+ clearAll()
{
- panic("Interrupts::clear_all unimplemented!\n");
+ panic("Interrupts::clearAll unimplemented!\n");
}
};
-};
+} // namespace X86ISA
#endif // __ARCH_X86_INTERRUPTS_HH__