diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2009-04-06 10:19:36 -0700 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2009-04-06 10:19:36 -0700 |
commit | d080581db1f9ee4e1e6d07d2b01c13c67908a391 (patch) | |
tree | cc484b289fa5a30c4631f9faa1d8b456bffeebfc /src/arch/x86/interrupts.hh | |
parent | 7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9 (diff) | |
parent | 639cb0a42d953ee32bc7e96b0cdfa96cd40e9fc1 (diff) | |
download | gem5-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.hh | 253 |
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 §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) + { + 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__ |