X86: Rework interrupt pins to allow one to many connections.

This commit is contained in:
Gabe Black 2009-01-31 23:33:54 -08:00
parent 64b663c607
commit 6a3f255a84
16 changed files with 209 additions and 70 deletions

View file

@ -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')

View file

@ -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)

View file

@ -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')

View file

@ -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)

View file

@ -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

View file

@ -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")

View file

@ -36,7 +36,9 @@ void
X86ISA::Cmos::X86RTC::handleEvent()
{
assert(intPin);
intPin->signalInterrupt();
intPin->raise();
//XXX This is a hack.
intPin->lower();
}
Tick

View file

@ -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)
{
}

View file

@ -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()
{

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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<I8259 *>(output->getDevice());
if (master)
master->setSlave(this);
I82094AA * ioApic;
ioApic = dynamic_cast<I82094AA *>(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()
{

View file

@ -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();
};

View file

@ -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);
}

View file

@ -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,13 @@ class IntDev
}
};
class IntPin : public SimObject
class IntSinkPin : public SimObject
{
protected:
IntDev * device;
int line;
public:
typedef X86IntPinParams Params;
IntDev * device;
int number;
IntDev *
getDevice() const
{
return device;
}
typedef X86IntSinkPinParams Params;
const Params *
params() const
@ -134,16 +141,73 @@ class IntPin : public SimObject
return dynamic_cast<const Params *>(_params);
}
IntPin(Params *p) : SimObject(p),
device(dynamic_cast<IntDev *>(p->device)), line(p->line)
IntSinkPin(Params *p) : SimObject(p),
device(dynamic_cast<IntDev *>(p->device)), number(p->number)
{
assert(device);
}
};
class IntSourcePin : public SimObject
{
protected:
std::vector<IntSinkPin *> sinks;
public:
typedef X86IntSourcePinParams Params;
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
void
signalInterrupt()
addSink(IntSinkPin *sink)
{
device->signalInterrupt(line);
sinks.push_back(sink);
}
void
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<const Params *>(_params);
}
IntLine(Params *p) : SimObject(p), source(p->source), sink(p->sink)
{
source->addSink(sink);
}
};