summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2008-10-12 13:54:57 -0700
committerGabe Black <gblack@eecs.umich.edu>2008-10-12 13:54:57 -0700
commit3a1905157eec2ed80eaf2ddb8be69cb2f509dfee (patch)
tree036a4079a56b09dab9492bc926b426cb773ce604
parentc35da8e495e9f2697a252e8e828e6d7760a8a2db (diff)
downloadgem5-3a1905157eec2ed80eaf2ddb8be69cb2f509dfee.tar.xz
X86: Create a mechanism for the IO APIC to access I8259 vectors.
-rw-r--r--src/dev/x86/i82094aa.cc30
-rw-r--r--src/dev/x86/i82094aa.hh11
-rw-r--r--src/dev/x86/i8259.cc61
-rw-r--r--src/dev/x86/i8259.hh17
-rw-r--r--src/dev/x86/intdev.hh6
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<I8259 *>(output->getDevice());
+ if (master)
+ master->setSlave(this);
+ I82094AA * ioApic;
+ ioApic = dynamic_cast<I82094AA *>(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<const Params *>(_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
{