From 6a3f255a84d93f3e621319fd81f355416e385c8c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 31 Jan 2009 23:33:54 -0800 Subject: X86: Rework interrupt pins to allow one to many connections. --- src/dev/x86/Cmos.py | 4 +- src/dev/x86/I82094AA.py | 5 ++- src/dev/x86/I8254.py | 4 +- src/dev/x86/I8259.py | 8 ++-- src/dev/x86/SouthBridge.py | 21 ++++++++--- src/dev/x86/X86IntPin.py | 24 +++++++++--- src/dev/x86/cmos.cc | 4 +- src/dev/x86/cmos.hh | 6 +-- src/dev/x86/i82094aa.cc | 20 +++++++++- src/dev/x86/i82094aa.hh | 9 ++--- src/dev/x86/i8254.cc | 7 +++- src/dev/x86/i8254.hh | 4 +- src/dev/x86/i8259.cc | 38 +++++++++++++------ src/dev/x86/i8259.hh | 11 ++---- src/dev/x86/intdev.cc | 18 +++++++-- src/dev/x86/intdev.hh | 92 +++++++++++++++++++++++++++++++++++++++------- 16 files changed, 207 insertions(+), 68 deletions(-) (limited to 'src/dev') diff --git a/src/dev/x86/Cmos.py b/src/dev/x86/Cmos.py index a9910f70d..0a92145e2 100644 --- a/src/dev/x86/Cmos.py +++ b/src/dev/x86/Cmos.py @@ -29,6 +29,7 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice +from X86IntPin import X86IntSourcePin class Cmos(BasicPioDevice): type = 'Cmos' @@ -36,4 +37,5 @@ class Cmos(BasicPioDevice): time = Param.Time('01/01/2009', "System time to use ('Now' for actual time)") pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") - int_pin = Param.X86IntPin('Pin to signal RTC alarm interrupts to') + int_pin = Param.X86IntSourcePin(X86IntSourcePin(), + 'Pin to signal RTC alarm interrupts to') diff --git a/src/dev/x86/I82094AA.py b/src/dev/x86/I82094AA.py index b4ad96a9f..5ca58614d 100644 --- a/src/dev/x86/I82094AA.py +++ b/src/dev/x86/I82094AA.py @@ -29,7 +29,7 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice -from X86IntPin import X86IntPin +from X86IntPin import X86IntSinkPin class I82094AA(BasicPioDevice): type = 'I82094AA' @@ -37,6 +37,7 @@ class I82094AA(BasicPioDevice): pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") pio_addr = Param.Addr("Device address") int_port = Port("Port for sending and receiving interrupt messages") + external_int_pic = Param.I8259("External PIC, if any") def pin(self, line): - return X86IntPin(device=self, line=line) + return X86IntSinkPin(device=self, number=line) diff --git a/src/dev/x86/I8254.py b/src/dev/x86/I8254.py index d67d04e86..f468717cc 100644 --- a/src/dev/x86/I8254.py +++ b/src/dev/x86/I8254.py @@ -29,9 +29,11 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice +from X86IntPin import X86IntSourcePin class I8254(BasicPioDevice): type = 'I8254' cxx_class = 'X86ISA::I8254' pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") - int_pin = Param.X86IntPin('Pin to signal timer interrupts to') + int_pin = Param.X86IntSourcePin(X86IntSourcePin(), + 'Pin to signal timer interrupts to') diff --git a/src/dev/x86/I8259.py b/src/dev/x86/I8259.py index d241b092a..e0128d032 100644 --- a/src/dev/x86/I8259.py +++ b/src/dev/x86/I8259.py @@ -29,7 +29,7 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice -from X86IntPin import X86IntPin +from X86IntPin import X86IntSourcePin, X86IntSinkPin class X86I8259CascadeMode(Enum): map = {'I8259Master' : 0, @@ -41,8 +41,10 @@ class I8259(BasicPioDevice): type = 'I8259' cxx_class='X86ISA::I8259' pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") - output = Param.X86IntPin('The pin this I8259 drives') + output = Param.X86IntSourcePin(X86IntSourcePin(), + 'The pin this I8259 drives') mode = Param.X86I8259CascadeMode('How this I8259 is cascaded') + slave = Param.I8259('Slave I8259, if any') def pin(self, line): - return X86IntPin(device=self, line=line) + return X86IntSinkPin(device=self, number=line) diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index bbe3ad102..ba9aaf2b4 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -34,6 +34,7 @@ from I8237 import I8237 from I8254 import I8254 from I8259 import I8259 from PcSpeaker import PcSpeaker +from X86IntPin import X86IntLine from m5.SimObject import SimObject def x86IOAddress(port): @@ -52,6 +53,9 @@ class SouthBridge(SimObject): _pit = I8254(pio_addr=x86IOAddress(0x40)) _speaker = PcSpeaker(pio_addr=x86IOAddress(0x61)) _io_apic = I82094AA(pio_addr=0xFEC00000) + # This is to make sure the interrupt lines are instantiated. Don't use + # it for anything directly. + int_lines = VectorParam.X86IntLine([], "Interrupt lines") pic1 = Param.I8259(_pic1, "Master PIC") pic2 = Param.I8259(_pic2, "Slave PIC") @@ -61,13 +65,20 @@ class SouthBridge(SimObject): speaker = Param.PcSpeaker(_speaker, "PC speaker") io_apic = Param.I82094AA(_io_apic, "I/O APIC") + def connectPins(self, source, sink): + self.int_lines.append(X86IntLine(source=source, sink=sink)) + def attachIO(self, bus): - # Make internal connections - self.pic1.output = self.io_apic.pin(0) - self.pic2.output = self.pic1.pin(2) - self.cmos.int_pin = self.pic2.pin(0) - self.pit.int_pin = self.pic1.pin(0) + # Route interupt signals + self.connectPins(self.pic1.output, self.io_apic.pin(0)) + self.connectPins(self.pic2.output, self.pic1.pin(2)) + self.connectPins(self.cmos.int_pin, self.pic2.pin(0)) + self.connectPins(self.pit.int_pin, self.pic1.pin(0)) + self.connectPins(self.pit.int_pin, self.io_apic.pin(2)) + # Tell the devices about each other + self.pic1.slave = self.pic2 self.speaker.i8254 = self.pit + self.io_apic.external_int_pic = self.pic1 # Connect to the bus self.cmos.pio = bus.port self.dma1.pio = bus.port diff --git a/src/dev/x86/X86IntPin.py b/src/dev/x86/X86IntPin.py index 372b4ab66..35e274624 100644 --- a/src/dev/x86/X86IntPin.py +++ b/src/dev/x86/X86IntPin.py @@ -29,9 +29,23 @@ from m5.params import * from m5.SimObject import SimObject -class X86IntPin(SimObject): - type = 'X86IntPin' - cxx_class = 'X86ISA::IntPin' +# A generic pin to drive an interrupt signal generated by a device. +class X86IntSourcePin(SimObject): + type = 'X86IntSourcePin' + cxx_class = 'X86ISA::IntSourcePin' - line = Param.Int("Interrupt line for this pin") - device = Param.SimObject("Device which handles interrupts") +# A generic pin to receive an interrupt signal generated by another device. +class X86IntSinkPin(SimObject): + type = 'X86IntSinkPin' + cxx_class = 'X86ISA::IntSinkPin' + + device = Param.SimObject("Device this pin belongs to") + number = Param.Int("The pin number on the device") + +# An interrupt line which is driven by a source pin and drives a sink pin. +class X86IntLine(SimObject): + type = 'X86IntLine' + cxx_class = 'X86ISA::IntLine' + + source = Param.X86IntSourcePin("Pin driving this line") + sink = Param.X86IntSinkPin("Pin driven by this line") diff --git a/src/dev/x86/cmos.cc b/src/dev/x86/cmos.cc index c88592870..6bdc78a4b 100644 --- a/src/dev/x86/cmos.cc +++ b/src/dev/x86/cmos.cc @@ -36,7 +36,9 @@ void X86ISA::Cmos::X86RTC::handleEvent() { assert(intPin); - intPin->signalInterrupt(); + intPin->raise(); + //XXX This is a hack. + intPin->lower(); } Tick diff --git a/src/dev/x86/cmos.hh b/src/dev/x86/cmos.hh index 45fb9e8f2..76276dbc1 100644 --- a/src/dev/x86/cmos.hh +++ b/src/dev/x86/cmos.hh @@ -38,7 +38,7 @@ namespace X86ISA { -class IntPin; +class IntSourcePin; class Cmos : public BasicPioDevice { @@ -57,10 +57,10 @@ class Cmos : public BasicPioDevice class X86RTC : public MC146818 { protected: - IntPin * intPin; + IntSourcePin * intPin; public: X86RTC(EventManager *em, const std::string &n, const struct tm time, - bool bcd, Tick frequency, IntPin * _intPin) : + bool bcd, Tick frequency, IntSourcePin * _intPin) : MC146818(em, n, time, bcd, frequency), intPin(_intPin) { } diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index a229fffc3..03944c190 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -36,7 +36,8 @@ #include "sim/system.hh" X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), - latency(p->pio_latency), pioAddr(p->pio_addr), extIntPic(NULL) + latency(p->pio_latency), pioAddr(p->pio_addr), + extIntPic(p->external_int_pic) { // This assumes there's only one I/O APIC in the system id = sys->numContexts(); @@ -47,6 +48,7 @@ X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), entry.mask = 1; for (int i = 0; i < TableSize; i++) { redirTable[i] = entry; + pinStates[i] = false; } } @@ -209,6 +211,22 @@ X86ISA::I82094AA::signalInterrupt(int line) } } +void +X86ISA::I82094AA::raiseInterruptPin(int number) +{ + assert(number < TableSize); + if (!pinStates[number]) + signalInterrupt(number); + pinStates[number] = true; +} + +void +X86ISA::I82094AA::lowerInterruptPin(int number) +{ + assert(number < TableSize); + pinStates[number] = false; +} + X86ISA::I82094AA * I82094AAParams::create() { diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index 6a8873d45..b11e2bcb1 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -77,6 +77,7 @@ class I82094AA : public PioDevice, public IntDev static const uint8_t APICVersion = 0x14; RedirTableEntry redirTable[TableSize]; + bool pinStates[TableSize]; public: typedef I82094AAParams Params; @@ -89,12 +90,6 @@ class I82094AA : public PioDevice, public IntDev I82094AA(Params *p); - void - setExtIntPic(I8259 * pic) - { - extIntPic = pic; - } - Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); @@ -123,6 +118,8 @@ class I82094AA : public PioDevice, public IntDev } void signalInterrupt(int line); + void raiseInterruptPin(int number); + void lowerInterruptPin(int number); }; }; // namespace X86ISA diff --git a/src/dev/x86/i8254.cc b/src/dev/x86/i8254.cc index ac3847cd6..4f37eebad 100644 --- a/src/dev/x86/i8254.cc +++ b/src/dev/x86/i8254.cc @@ -37,8 +37,11 @@ void X86ISA::I8254::counterInterrupt(unsigned int num) { DPRINTF(I8254, "Interrupt from counter %d.\n", num); - if (num == 0) - intPin->signalInterrupt(); + if (num == 0) { + intPin->raise(); + //XXX This is a hack. + intPin->lower(); + } } Tick diff --git a/src/dev/x86/i8254.hh b/src/dev/x86/i8254.hh index e6860b2c4..7de20dfd4 100644 --- a/src/dev/x86/i8254.hh +++ b/src/dev/x86/i8254.hh @@ -38,7 +38,7 @@ namespace X86ISA { -class IntPin; +class IntSourcePin; class I8254 : public BasicPioDevice { @@ -64,7 +64,7 @@ class I8254 : public BasicPioDevice X86Intel8254Timer pit; - IntPin *intPin; + IntSourcePin *intPin; void counterInterrupt(unsigned int num); diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index b3d3a5aa2..b7c8bb08a 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -36,20 +36,12 @@ X86ISA::I8259::I8259(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), output(p->output), - mode(p->mode), slave(NULL), + mode(p->mode), slave(p->slave), IRR(0), ISR(0), IMR(0), readIRR(true), initControlWord(0), autoEOI(false) { - 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); - } + for (int i = 0; i < NumLines; i++) + pinStates[i] = false; pioSize = 2; } @@ -237,7 +229,9 @@ X86ISA::I8259::requestInterrupt(int line) if (bits(ISR, 7, line) == 0) { if (output) { DPRINTF(I8259, "Propogating interrupt.\n"); - output->signalInterrupt(); + output->raise(); + //XXX This is a hack. + output->lower(); } else { warn("Received interrupt but didn't have " "anyone to tell about it.\n"); @@ -260,6 +254,26 @@ X86ISA::I8259::signalInterrupt(int line) } } +void +X86ISA::I8259::raiseInterruptPin(int number) +{ + if (number >= NumLines) + fatal("Line number %d doesn't exist. The max is %d.\n", + number, NumLines - 1); + if (!pinStates[number]) + signalInterrupt(number); + pinStates[number] = true; +} + +void +X86ISA::I8259::lowerInterruptPin(int number) +{ + if (number >= NumLines) + fatal("Line number %d doesn't exist. The max is %d.\n", + number, NumLines - 1); + pinStates[number] = false; +} + int X86ISA::I8259::getVector() { diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index 5a2cf72e8..dfb56646a 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -45,9 +45,10 @@ class I8259 : public BasicPioDevice, public IntDev { protected: static const int NumLines = 8; + bool pinStates[NumLines]; Tick latency; - IntPin *output; + IntSourcePin *output; Enums::X86I8259CascadeMode mode; I8259 * slave; @@ -90,16 +91,12 @@ class I8259 : public BasicPioDevice, public IntDev I8259(Params * p); - void - setSlave(I8259 * _slave) - { - slave = _slave; - } - Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); void signalInterrupt(int line); + void raiseInterruptPin(int number); + void lowerInterruptPin(int number); int getVector(); }; diff --git a/src/dev/x86/intdev.cc b/src/dev/x86/intdev.cc index 463b3c9fe..e386687a9 100644 --- a/src/dev/x86/intdev.cc +++ b/src/dev/x86/intdev.cc @@ -30,8 +30,20 @@ #include "dev/x86/intdev.hh" -X86ISA::IntPin * -X86IntPinParams::create() +X86ISA::IntSourcePin * +X86IntSourcePinParams::create() { - return new X86ISA::IntPin(this); + return new X86ISA::IntSourcePin(this); +} + +X86ISA::IntSinkPin * +X86IntSinkPinParams::create() +{ + return new X86ISA::IntSinkPin(this); +} + +X86ISA::IntLine * +X86IntLineParams::create() +{ + return new X86ISA::IntLine(this); } diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh index ba9a073a4..ca8e7eea5 100644 --- a/src/dev/x86/intdev.hh +++ b/src/dev/x86/intdev.hh @@ -38,7 +38,9 @@ #include "mem/mem_object.hh" #include "mem/mport.hh" #include "sim/sim_object.hh" -#include "params/X86IntPin.hh" +#include "params/X86IntSourcePin.hh" +#include "params/X86IntSinkPin.hh" +#include "params/X86IntLine.hh" namespace X86ISA { @@ -99,6 +101,18 @@ class IntDev panic("signalInterrupt not implemented.\n"); } + virtual void + raiseInterruptPin(int number) + { + panic("raiseInterruptPin not implemented.\n"); + } + + virtual void + lowerInterruptPin(int number) + { + panic("lowerInterruptPin not implemented.\n"); + } + virtual Tick recvMessage(PacketPtr pkt) { @@ -113,20 +127,34 @@ class IntDev } }; -class IntPin : public SimObject +class IntSinkPin : public SimObject { - protected: + public: IntDev * device; - int line; + int number; - public: - typedef X86IntPinParams Params; + typedef X86IntSinkPinParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } - IntDev * - getDevice() const + IntSinkPin(Params *p) : SimObject(p), + device(dynamic_cast(p->device)), number(p->number) { - return device; + assert(device); } +}; + +class IntSourcePin : public SimObject +{ + protected: + std::vector sinks; + + public: + typedef X86IntSourcePinParams Params; const Params * params() const @@ -134,16 +162,52 @@ class IntPin : public SimObject return dynamic_cast(_params); } - IntPin(Params *p) : SimObject(p), - device(dynamic_cast(p->device)), line(p->line) + void + addSink(IntSinkPin *sink) { - assert(device); + sinks.push_back(sink); } void - signalInterrupt() + raise() + { + for (int i = 0; i < sinks.size(); i++) { + const IntSinkPin &pin = *sinks[i]; + pin.device->raiseInterruptPin(pin.number); + } + } + + void + lower() + { + for (int i = 0; i < sinks.size(); i++) { + const IntSinkPin &pin = *sinks[i]; + pin.device->lowerInterruptPin(pin.number); + } + } + + IntSourcePin(Params *p) : SimObject(p) + {} +}; + +class IntLine : public SimObject +{ + protected: + IntSourcePin *source; + IntSinkPin *sink; + + public: + typedef X86IntLineParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + IntLine(Params *p) : SimObject(p), source(p->source), sink(p->sink) { - device->signalInterrupt(line); + source->addSink(sink); } }; -- cgit v1.2.3