From 3a1905157eec2ed80eaf2ddb8be69cb2f509dfee Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:54:57 -0700 Subject: X86: Create a mechanism for the IO APIC to access I8259 vectors. --- src/dev/x86/i82094aa.cc | 30 +++++++++++++----------- src/dev/x86/i82094aa.hh | 11 ++++++++- src/dev/x86/i8259.cc | 61 ++++++++++++++++++++++++++++++++++++++++++------- src/dev/x86/i8259.hh | 17 +++++++++----- src/dev/x86/intdev.hh | 6 +++++ 5 files changed, 97 insertions(+), 28 deletions(-) diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index d7f479106..0ae7c56f3 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -30,12 +30,13 @@ #include "arch/x86/intmessage.hh" #include "dev/x86/i82094aa.hh" +#include "dev/x86/i8259.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "sim/system.hh" X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), - latency(p->pio_latency), pioAddr(p->pio_addr) + latency(p->pio_latency), pioAddr(p->pio_addr), extIntPic(NULL) { // This assumes there's only one I/O APIC in the system id = sys->getNumCPUs(); @@ -145,25 +146,28 @@ X86ISA::I82094AA::signalInterrupt(int line) DPRINTF(I82094AA, "Entry was masked.\n"); return; } else { - if (DTRACE(I82094AA)) { - if (DeliveryMode::isReserved(entry.deliveryMode)) { - fatal("Tried to use reserved delivery mode " - "for IO APIC entry %d.\n", line); - } else { - DPRINTF(I82094AA, "Delivery mode is: %s.\n", - DeliveryMode::names[entry.deliveryMode]); - } - DPRINTF(I82094AA, "Vector is %#x.\n", entry.vector); - } - TriggerIntMessage message; message.destination = entry.dest; - message.vector = entry.vector; + if (entry.deliveryMode == DeliveryMode::ExtInt) { + assert(extIntPic); + message.vector = extIntPic->getVector(); + } else { + message.vector = entry.vector; + } message.deliveryMode = entry.deliveryMode; message.destMode = entry.destMode; message.level = entry.polarity; message.trigger = entry.trigger; + if (DeliveryMode::isReserved(entry.deliveryMode)) { + fatal("Tried to use reserved delivery mode " + "for IO APIC entry %d.\n", line); + } else if (DTRACE(I82094AA)) { + DPRINTF(I82094AA, "Delivery mode is: %s.\n", + DeliveryMode::names[entry.deliveryMode]); + DPRINTF(I82094AA, "Vector is %#x.\n", message.vector); + } + if (entry.destMode == 0) { DPRINTF(I82094AA, "Sending interrupt to APIC ID %d.\n", entry.dest); diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index 6c874a5f9..6a8873d45 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -40,6 +40,8 @@ namespace X86ISA { +class I8259; + class I82094AA : public PioDevice, public IntDev { public: @@ -60,10 +62,11 @@ class I82094AA : public PioDevice, public IntDev EndBitUnion(RedirTableEntry) protected: - System * system; Tick latency; Addr pioAddr; + I8259 * extIntPic; + uint8_t regSel; uint8_t id; uint8_t arbId; @@ -86,6 +89,12 @@ class I82094AA : public PioDevice, public IntDev I82094AA(Params *p); + void + setExtIntPic(I8259 * pic) + { + extIntPic = pic; + } + Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index a67baa8e2..be0bfbe4d 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -29,8 +29,28 @@ */ #include "base/bitfield.hh" +#include "dev/x86/i82094aa.hh" #include "dev/x86/i8259.hh" +X86ISA::I8259::I8259(Params * p) : BasicPioDevice(p), IntDev(this), + latency(p->pio_latency), output(p->output), + mode(p->mode), slave(NULL), + IRR(0), ISR(0), IMR(0), + readIRR(true), initControlWord(0) +{ + if (output) { + I8259 * master; + master = dynamic_cast(output->getDevice()); + if (master) + master->setSlave(this); + I82094AA * ioApic; + ioApic = dynamic_cast(output->getDevice()); + if (ioApic) + ioApic->setExtIntPic(this); + } + pioSize = 2; +} + Tick X86ISA::I8259::read(PacketPtr pkt) { @@ -189,21 +209,46 @@ void X86ISA::I8259::signalInterrupt(int line) { DPRINTF(I8259, "Interrupt raised on line %d.\n", line); - if (line > 7) - fatal("Line number %d doesn't exist. The max is 7.\n"); + if (line >= NumLines) + fatal("Line number %d doesn't exist. The max is %d.\n", + line, NumLines - 1); if (bits(IMR, line)) { DPRINTF(I8259, "Interrupt %d was masked.\n", line); } else { - if (output) { - DPRINTF(I8259, "Propogating interrupt.\n"); - output->signalInterrupt(); - } else { - warn("Received interrupt but didn't have " - "anyone to tell about it.\n"); + IRR |= 1 << line; + if (bits(ISR, 7, line) == 0) { + if (output) { + DPRINTF(I8259, "Propogating interrupt.\n"); + output->signalInterrupt(); + } else { + warn("Received interrupt but didn't have " + "anyone to tell about it.\n"); + } } } } +int +X86ISA::I8259::getVector() +{ + /* + * This code only handles one slave. Since that's how the PC platform + * always uses the 8259 PIC, there shouldn't be any need for more. If + * there -is- a need for more for some reason, "slave" can become a + * vector of slaves. + */ + int line = findMsbSet(IRR); + IRR &= ~(1 << line); + DPRINTF(I8259, "Interrupt %d was accepted.\n", line); + ISR |= 1 << line; + if (slave && bits(cascadeBits, line)) { + DPRINTF(I8259, "Interrupt was from slave who will " + "provide the vector.\n"); + return slave->getVector(); + } + return line | vectorOffset; +} + X86ISA::I8259 * I8259Params::create() { diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index 107cd015c..371a27874 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -39,12 +39,17 @@ namespace X86ISA { +class I82094AA; + class I8259 : public BasicPioDevice, public IntDev { protected: + static const int NumLines = 8; + Tick latency; IntPin *output; Enums::X86I8259CascadeMode mode; + I8259 * slave; // Interrupt Request Register uint8_t IRR; @@ -77,19 +82,19 @@ class I8259 : public BasicPioDevice, public IntDev return dynamic_cast(_params); } - I8259(Params * p) : BasicPioDevice(p), IntDev(this), - latency(p->pio_latency), output(p->output), - mode(p->mode), IRR(0), ISR(0), IMR(0), - vectorOffset(0), readIRR(true), initControlWord(0) + I8259(Params * p); + + void + setSlave(I8259 * _slave) { - pioSize = 2; + slave = _slave; } Tick read(PacketPtr pkt); - Tick write(PacketPtr pkt); void signalInterrupt(int line); + int getVector(); }; }; // namespace X86ISA diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh index d36ed462a..ba9a073a4 100644 --- a/src/dev/x86/intdev.hh +++ b/src/dev/x86/intdev.hh @@ -122,6 +122,12 @@ class IntPin : public SimObject public: typedef X86IntPinParams Params; + IntDev * + getDevice() const + { + return device; + } + const Params * params() const { -- cgit v1.2.3