X86: Create a mechanism for the IO APIC to access I8259 vectors.
This commit is contained in:
parent
c35da8e495
commit
3a1905157e
5 changed files with 97 additions and 28 deletions
|
@ -30,12 +30,13 @@
|
||||||
|
|
||||||
#include "arch/x86/intmessage.hh"
|
#include "arch/x86/intmessage.hh"
|
||||||
#include "dev/x86/i82094aa.hh"
|
#include "dev/x86/i82094aa.hh"
|
||||||
|
#include "dev/x86/i8259.hh"
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
#include "mem/packet_access.hh"
|
#include "mem/packet_access.hh"
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
|
|
||||||
X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this),
|
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
|
// This assumes there's only one I/O APIC in the system
|
||||||
id = sys->getNumCPUs();
|
id = sys->getNumCPUs();
|
||||||
|
@ -145,25 +146,28 @@ X86ISA::I82094AA::signalInterrupt(int line)
|
||||||
DPRINTF(I82094AA, "Entry was masked.\n");
|
DPRINTF(I82094AA, "Entry was masked.\n");
|
||||||
return;
|
return;
|
||||||
} else {
|
} 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;
|
TriggerIntMessage message;
|
||||||
message.destination = entry.dest;
|
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.deliveryMode = entry.deliveryMode;
|
||||||
message.destMode = entry.destMode;
|
message.destMode = entry.destMode;
|
||||||
message.level = entry.polarity;
|
message.level = entry.polarity;
|
||||||
message.trigger = entry.trigger;
|
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) {
|
if (entry.destMode == 0) {
|
||||||
DPRINTF(I82094AA,
|
DPRINTF(I82094AA,
|
||||||
"Sending interrupt to APIC ID %d.\n", entry.dest);
|
"Sending interrupt to APIC ID %d.\n", entry.dest);
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
namespace X86ISA
|
namespace X86ISA
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class I8259;
|
||||||
|
|
||||||
class I82094AA : public PioDevice, public IntDev
|
class I82094AA : public PioDevice, public IntDev
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -60,10 +62,11 @@ class I82094AA : public PioDevice, public IntDev
|
||||||
EndBitUnion(RedirTableEntry)
|
EndBitUnion(RedirTableEntry)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
System * system;
|
|
||||||
Tick latency;
|
Tick latency;
|
||||||
Addr pioAddr;
|
Addr pioAddr;
|
||||||
|
|
||||||
|
I8259 * extIntPic;
|
||||||
|
|
||||||
uint8_t regSel;
|
uint8_t regSel;
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
uint8_t arbId;
|
uint8_t arbId;
|
||||||
|
@ -86,6 +89,12 @@ class I82094AA : public PioDevice, public IntDev
|
||||||
|
|
||||||
I82094AA(Params *p);
|
I82094AA(Params *p);
|
||||||
|
|
||||||
|
void
|
||||||
|
setExtIntPic(I8259 * pic)
|
||||||
|
{
|
||||||
|
extIntPic = pic;
|
||||||
|
}
|
||||||
|
|
||||||
Tick read(PacketPtr pkt);
|
Tick read(PacketPtr pkt);
|
||||||
Tick write(PacketPtr pkt);
|
Tick write(PacketPtr pkt);
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,28 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "base/bitfield.hh"
|
#include "base/bitfield.hh"
|
||||||
|
#include "dev/x86/i82094aa.hh"
|
||||||
#include "dev/x86/i8259.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
|
Tick
|
||||||
X86ISA::I8259::read(PacketPtr pkt)
|
X86ISA::I8259::read(PacketPtr pkt)
|
||||||
{
|
{
|
||||||
|
@ -189,21 +209,46 @@ void
|
||||||
X86ISA::I8259::signalInterrupt(int line)
|
X86ISA::I8259::signalInterrupt(int line)
|
||||||
{
|
{
|
||||||
DPRINTF(I8259, "Interrupt raised on line %d.\n", line);
|
DPRINTF(I8259, "Interrupt raised on line %d.\n", line);
|
||||||
if (line > 7)
|
if (line >= NumLines)
|
||||||
fatal("Line number %d doesn't exist. The max is 7.\n");
|
fatal("Line number %d doesn't exist. The max is %d.\n",
|
||||||
|
line, NumLines - 1);
|
||||||
if (bits(IMR, line)) {
|
if (bits(IMR, line)) {
|
||||||
DPRINTF(I8259, "Interrupt %d was masked.\n", line);
|
DPRINTF(I8259, "Interrupt %d was masked.\n", line);
|
||||||
} else {
|
} else {
|
||||||
if (output) {
|
IRR |= 1 << line;
|
||||||
DPRINTF(I8259, "Propogating interrupt.\n");
|
if (bits(ISR, 7, line) == 0) {
|
||||||
output->signalInterrupt();
|
if (output) {
|
||||||
} else {
|
DPRINTF(I8259, "Propogating interrupt.\n");
|
||||||
warn("Received interrupt but didn't have "
|
output->signalInterrupt();
|
||||||
"anyone to tell about it.\n");
|
} 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 *
|
X86ISA::I8259 *
|
||||||
I8259Params::create()
|
I8259Params::create()
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,12 +39,17 @@
|
||||||
namespace X86ISA
|
namespace X86ISA
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class I82094AA;
|
||||||
|
|
||||||
class I8259 : public BasicPioDevice, public IntDev
|
class I8259 : public BasicPioDevice, public IntDev
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
static const int NumLines = 8;
|
||||||
|
|
||||||
Tick latency;
|
Tick latency;
|
||||||
IntPin *output;
|
IntPin *output;
|
||||||
Enums::X86I8259CascadeMode mode;
|
Enums::X86I8259CascadeMode mode;
|
||||||
|
I8259 * slave;
|
||||||
|
|
||||||
// Interrupt Request Register
|
// Interrupt Request Register
|
||||||
uint8_t IRR;
|
uint8_t IRR;
|
||||||
|
@ -77,19 +82,19 @@ class I8259 : public BasicPioDevice, public IntDev
|
||||||
return dynamic_cast<const Params *>(_params);
|
return dynamic_cast<const Params *>(_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
I8259(Params * p) : BasicPioDevice(p), IntDev(this),
|
I8259(Params * p);
|
||||||
latency(p->pio_latency), output(p->output),
|
|
||||||
mode(p->mode), IRR(0), ISR(0), IMR(0),
|
void
|
||||||
vectorOffset(0), readIRR(true), initControlWord(0)
|
setSlave(I8259 * _slave)
|
||||||
{
|
{
|
||||||
pioSize = 2;
|
slave = _slave;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tick read(PacketPtr pkt);
|
Tick read(PacketPtr pkt);
|
||||||
|
|
||||||
Tick write(PacketPtr pkt);
|
Tick write(PacketPtr pkt);
|
||||||
|
|
||||||
void signalInterrupt(int line);
|
void signalInterrupt(int line);
|
||||||
|
int getVector();
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace X86ISA
|
}; // namespace X86ISA
|
||||||
|
|
|
@ -122,6 +122,12 @@ class IntPin : public SimObject
|
||||||
public:
|
public:
|
||||||
typedef X86IntPinParams Params;
|
typedef X86IntPinParams Params;
|
||||||
|
|
||||||
|
IntDev *
|
||||||
|
getDevice() const
|
||||||
|
{
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
const Params *
|
const Params *
|
||||||
params() const
|
params() const
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue