summaryrefslogtreecommitdiff
path: root/src/arch/x86/interrupts.hh
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-04-06 10:19:36 -0700
committerGabe Black <gblack@eecs.umich.edu>2009-04-06 10:19:36 -0700
commitd080581db1f9ee4e1e6d07d2b01c13c67908a391 (patch)
treecc484b289fa5a30c4631f9faa1d8b456bffeebfc /src/arch/x86/interrupts.hh
parent7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9 (diff)
parent639cb0a42d953ee32bc7e96b0cdfa96cd40e9fc1 (diff)
downloadgem5-d080581db1f9ee4e1e6d07d2b01c13c67908a391.tar.xz
Merge ARM into the head. ARM will compile but may not actually work.
Diffstat (limited to 'src/arch/x86/interrupts.hh')
-rw-r--r--src/arch/x86/interrupts.hh253
1 files changed, 227 insertions, 26 deletions
diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh
index cf9109e22..c5e3bde0d 100644
--- a/src/arch/x86/interrupts.hh
+++ b/src/arch/x86/interrupts.hh
@@ -58,73 +58,274 @@
#ifndef __ARCH_X86_INTERRUPTS_HH__
#define __ARCH_X86_INTERRUPTS_HH__
+#include "arch/x86/apicregs.hh"
#include "arch/x86/faults.hh"
+#include "arch/x86/intmessage.hh"
+#include "base/bitfield.hh"
#include "cpu/thread_context.hh"
+#include "dev/io_device.hh"
+#include "dev/x86/intdev.hh"
+#include "params/X86LocalApic.hh"
+#include "sim/eventq.hh"
-namespace X86ISA
-{
+class ThreadContext;
+class BaseCPU;
+
+namespace X86ISA {
-class Interrupts
+class Interrupts : public BasicPioDevice, IntDev
{
+ protected:
+ // 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.
+ */
+ Tick latency;
+ Tick clock;
+
+ class ApicTimerEvent : public Event
+ {
+ private:
+ Interrupts *localApic;
+ public:
+ ApicTimerEvent(Interrupts *_localApic) :
+ Event(), localApic(_localApic)
+ {}
+
+ void process()
+ {
+ assert(localApic);
+ if (localApic->triggerTimerInterrupt()) {
+ localApic->setReg(APIC_INITIAL_COUNT,
+ localApic->readReg(APIC_INITIAL_COUNT));
+ }
+ }
+ };
+
+ ApicTimerEvent apicTimerEvent;
+
+ /*
+ * A set of variables to keep track of interrupts that don't go through
+ * the IRR.
+ */
+ bool pendingSmi;
+ uint8_t smiVector;
+ bool pendingNmi;
+ uint8_t nmiVector;
+ bool pendingExtInt;
+ uint8_t extIntVector;
+ bool pendingInit;
+ uint8_t initVector;
+
+ // This is a quick check whether any of the above (except ExtInt) are set.
+ bool pendingUnmaskableInt;
+
+ /*
+ * IRR and ISR maintenance.
+ */
+ uint8_t IRRV;
+ uint8_t ISRV;
+
+ int
+ findRegArrayMSB(ApicRegIndex base)
+ {
+ int offset = 7;
+ do {
+ if (regs[base + offset] != 0) {
+ return offset * 32 + findMsbSet(regs[base + offset]);
+ }
+ } while (offset--);
+ return 0;
+ }
+
+ void
+ updateIRRV()
+ {
+ IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE);
+ }
+
+ void
+ updateISRV()
+ {
+ ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE);
+ }
+
+ void
+ setRegArrayBit(ApicRegIndex base, uint8_t vector)
+ {
+ regs[base + (vector % 32)] |= (1 << (vector >> 5));
+ }
+
+ void
+ clearRegArrayBit(ApicRegIndex base, uint8_t vector)
+ {
+ regs[base + (vector % 32)] &= ~(1 << (vector >> 5));
+ }
+
+ bool
+ getRegArrayBit(ApicRegIndex base, uint8_t vector)
+ {
+ return bits(regs[base + (vector % 32)], vector >> 5);
+ }
+
+ void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
+
+ BaseCPU *cpu;
+
public:
- Interrupts()
+ /*
+ * Params stuff.
+ */
+ typedef X86LocalApicParams Params;
+
+ void
+ setCPU(BaseCPU * newCPU)
{
- clear_all();
+ cpu = newCPU;
}
- int InterruptLevel(uint64_t softint)
+ void
+ setClock(Tick newClock)
{
- panic("Interrupts::InterruptLevel unimplemented!\n");
- return 0;
+ clock = newClock;
}
- void post(int int_num, int index)
+ const Params *
+ params() const
{
- panic("Interrupts::post unimplemented!\n");
+ return dynamic_cast<const Params *>(_params);
}
- void clear(int int_num, int index)
+ /*
+ * Functions to interact with the interrupt port from IntDev.
+ */
+ Tick read(PacketPtr pkt);
+ Tick write(PacketPtr pkt);
+ Tick recvMessage(PacketPtr pkt);
+
+ bool
+ triggerTimerInterrupt()
{
- warn("Interrupts::clear unimplemented!\n");
+ LVTEntry entry = regs[APIC_LVT_TIMER];
+ if (!entry.masked)
+ requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger);
+ return entry.periodic;
}
- void clear_all()
+ void addressRanges(AddrRangeList &range_list)
{
- warn("Interrupts::clear_all unimplemented!\n");
+ range_list.clear();
+ range_list.push_back(RangeEx(x86LocalAPICAddress(0, 0),
+ x86LocalAPICAddress(0, 0) + PageBytes));
}
- bool check_interrupts(ThreadContext * tc) const
+ void getIntAddrRange(AddrRangeList &range_list)
{
- return false;
+ range_list.clear();
+ range_list.push_back(RangeEx(x86InterruptAddress(0, 0),
+ x86InterruptAddress(0, 0) + PhysAddrAPICRangeSize));
}
- Fault getInterrupt(ThreadContext * tc)
+ Port *getPort(const std::string &if_name, int idx = -1)
{
- return NoFault;
+ if (if_name == "int_port")
+ return intPort;
+ return BasicPioDevice::getPort(if_name, idx);
}
- void updateIntrInfo(ThreadContext * tc)
+ /*
+ * Functions to access and manipulate the APIC's registers.
+ */
+
+ uint32_t readReg(ApicRegIndex miscReg);
+ void setReg(ApicRegIndex reg, uint32_t val);
+ void
+ setRegNoEffect(ApicRegIndex reg, uint32_t val)
{
- panic("Interrupts::updateIntrInfo unimplemented!\n");
+ regs[reg] = val;
}
- uint64_t get_vec(int int_num)
+ /*
+ * Constructor.
+ */
+
+ Interrupts(Params * p)
+ : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), clock(0),
+ apicTimerEvent(this),
+ pendingSmi(false), smiVector(0),
+ pendingNmi(false), nmiVector(0),
+ pendingExtInt(false), extIntVector(0),
+ pendingInit(false), initVector(0),
+ pendingUnmaskableInt(false)
{
- panic("Interrupts::get_vec unimplemented!\n");
- return 0;
+ 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;
}
- void serialize(std::ostream & os)
+ /*
+ * Functions for retrieving interrupts for the CPU to handle.
+ */
+
+ bool checkInterrupts(ThreadContext *tc) const;
+ Fault getInterrupt(ThreadContext *tc);
+ void updateIntrInfo(ThreadContext *tc);
+
+ /*
+ * Serialization.
+ */
+
+ 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 &section)
{
panic("Interrupts::unserialize unimplemented!\n");
}
-};
+ /*
+ * Old functions needed for compatability but which will be phased out
+ * eventually.
+ */
+ void
+ post(int int_num, int index)
+ {
+ panic("Interrupts::post unimplemented!\n");
+ }
+
+ void
+ clear(int int_num, int index)
+ {
+ panic("Interrupts::clear unimplemented!\n");
+ }
+
+ void
+ clearAll()
+ {
+ panic("Interrupts::clearAll unimplemented!\n");
+ }
};
+} // namespace X86ISA
+
#endif // __ARCH_X86_INTERRUPTS_HH__