From 876f4845f258ed09d348135d8af8cf4a17de1b8a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:44:24 -0700 Subject: X86: Make the local APIC handle interrupt messages from the IO APIC. --- src/arch/x86/interrupts.hh | 136 +++++++++++++++++++++++++++++++++------------ 1 file changed, 100 insertions(+), 36 deletions(-) (limited to 'src/arch/x86/interrupts.hh') diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index c4760dc0f..cfc1ada9d 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -60,6 +60,7 @@ #include "arch/x86/apicregs.hh" #include "arch/x86/faults.hh" +#include "base/bitfield.hh" #include "cpu/thread_context.hh" #include "dev/io_device.hh" #include "dev/x86/intdev.hh" @@ -74,7 +75,12 @@ namespace X86ISA class Interrupts : public BasicPioDevice, IntDev { protected: + // Storage for the APIC registers uint32_t regs[NUM_APIC_REGS]; + + /* + * Timing related stuff. + */ Tick latency; Tick clock; @@ -92,7 +98,58 @@ class Interrupts : public BasicPioDevice, IntDev ApicTimerEvent apicTimerEvent; + /* + * 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); + } + public: + /* + * Params stuff. + */ typedef X86LocalApicParams Params; void setClock(Tick newClock) @@ -106,6 +163,9 @@ class Interrupts : public BasicPioDevice, IntDev return dynamic_cast(_params); } + /* + * Functions to interact with the interrupt port from IntDev. + */ Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); Tick recvMessage(PacketPtr pkt); @@ -124,6 +184,17 @@ class Interrupts : public BasicPioDevice, IntDev x86InterruptAddress(0, 0) + PhysAddrAPICRangeSize)); } + Port *getPort(const std::string &if_name, int idx = -1) + { + if (if_name == "int_port") + return intPort; + return BasicPioDevice::getPort(if_name, idx); + } + + /* + * 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) @@ -131,29 +202,47 @@ class Interrupts : public BasicPioDevice, IntDev regs[reg] = val; } + /* + * Constructor. + */ + Interrupts(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), clock(0) { pioSize = PageBytes; + memset(regs, 0, sizeof(regs)); //Set the local apic DFR to the flat model. regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1); - memset(regs, 0, sizeof(regs)); - clear_all(); + ISRV = 0; + IRRV = 0; } - Port *getPort(const std::string &if_name, int idx = -1) + /* + * Functions for retrieving interrupts for the CPU to handle. + */ + + bool check_interrupts(ThreadContext * tc) const; + Fault getInterrupt(ThreadContext * tc); + void updateIntrInfo(ThreadContext * tc); + + /* + * Serialization. + */ + + void serialize(std::ostream & os) { - if (if_name == "int_port") - return intPort; - return BasicPioDevice::getPort(if_name, idx); + panic("Interrupts::serialize unimplemented!\n"); } - int InterruptLevel(uint64_t softint) + void unserialize(Checkpoint * cp, const std::string & section) { - panic("Interrupts::InterruptLevel unimplemented!\n"); - return 0; + 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"); @@ -161,37 +250,12 @@ class Interrupts : public BasicPioDevice, IntDev void clear(int int_num, int index) { - warn("Interrupts::clear unimplemented!\n"); + panic("Interrupts::clear unimplemented!\n"); } void clear_all() { - warn("Interrupts::clear_all unimplemented!\n"); - } - - bool check_interrupts(ThreadContext * tc) const - { - return false; - } - - Fault getInterrupt(ThreadContext * tc) - { - return NoFault; - } - - void updateIntrInfo(ThreadContext * tc) - { - panic("Interrupts::updateIntrInfo unimplemented!\n"); - } - - void serialize(std::ostream & os) - { - panic("Interrupts::serialize unimplemented!\n"); - } - - void unserialize(Checkpoint * cp, const std::string & section) - { - panic("Interrupts::unserialize unimplemented!\n"); + panic("Interrupts::clear_all unimplemented!\n"); } }; -- cgit v1.2.3