From 557bde43c331024eb5cecf4093a24a5b7a9cc266 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:28:54 -0700 Subject: X86: Make APICs communicate through the memory system. --- src/dev/x86/I82094AA.py | 1 + src/dev/x86/SouthBridge.py | 1 + src/dev/x86/i82094aa.cc | 96 ++++++++++++++++++++++++++++++---------------- src/dev/x86/i82094aa.hh | 15 ++++++++ src/dev/x86/i8259.hh | 6 +-- src/dev/x86/intdev.hh | 68 +++++++++++++++++++++++++++++++- 6 files changed, 151 insertions(+), 36 deletions(-) (limited to 'src/dev') diff --git a/src/dev/x86/I82094AA.py b/src/dev/x86/I82094AA.py index 731d831f0..b4ad96a9f 100644 --- a/src/dev/x86/I82094AA.py +++ b/src/dev/x86/I82094AA.py @@ -36,6 +36,7 @@ class I82094AA(BasicPioDevice): cxx_class = 'X86ISA::I82094AA' 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") def pin(self, line): return X86IntPin(device=self, line=line) diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index 15ffe153f..8a9bea01b 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -72,3 +72,4 @@ class SouthBridge(SimObject): self.pit.pio = bus.port self.speaker.pio = bus.port self.io_apic.pio = bus.port + self.io_apic.int_port = bus.port diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index 713f59592..f944e7171 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -28,12 +28,13 @@ * Authors: Gabe Black */ +#include "arch/x86/intmessage.hh" #include "dev/x86/i82094aa.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "sim/system.hh" -X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), +X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), latency(p->pio_latency), pioAddr(p->pio_addr) { // This assumes there's only one I/O APIC in the system @@ -140,11 +141,56 @@ X86ISA::I82094AA::signalInterrupt(int line) DPRINTF(I82094AA, "Entry was masked.\n"); return; } else { + if (DTRACE(I82094AA)) { + switch(entry.deliveryMode) { + case 0: + DPRINTF(I82094AA, "Delivery mode is: Fixed.\n"); + break; + case 1: + DPRINTF(I82094AA, "Delivery mode is: Lowest Priority.\n"); + break; + case 2: + DPRINTF(I82094AA, "Delivery mode is: SMI.\n"); + break; + case 3: + fatal("Tried to use reserved delivery mode " + "for IO APIC entry %d.\n", line); + break; + case 4: + DPRINTF(I82094AA, "Delivery mode is: NMI.\n"); + break; + case 5: + DPRINTF(I82094AA, "Delivery mode is: INIT.\n"); + break; + case 6: + fatal("Tried to use reserved delivery mode " + "for IO APIC entry %d.\n", line); + break; + case 7: + DPRINTF(I82094AA, "Delivery mode is: ExtINT.\n"); + break; + } + DPRINTF(I82094AA, "Vector is %#x.\n", entry.vector); + } + + TriggerIntMessage message; + message.destination = entry.dest; + message.vector = entry.vector; + message.deliveryMode = entry.deliveryMode; + message.destMode = entry.destMode; + if (entry.destMode == 0) { DPRINTF(I82094AA, - "Would send interrupt to APIC ID %d.\n", entry.dest); + "Sending interrupt to APIC ID %d.\n", entry.dest); + PacketPtr pkt = buildIntRequest(entry.dest, message); + if (sys->getMemoryMode() == Enums::timing) + intPort->sendMessageTiming(pkt, latency); + else if (sys->getMemoryMode() == Enums::atomic) + intPort->sendMessageAtomic(pkt); + else + panic("Unrecognized memory mode.\n"); } else { - DPRINTF(I82094AA, "Would send interrupts to APIC IDs:" + DPRINTF(I82094AA, "Sending interrupts to APIC IDs:" "%s%s%s%s%s%s%s%s\n", bits((int)entry.dest, 0) ? " 0": "", bits((int)entry.dest, 1) ? " 1": "", @@ -155,36 +201,22 @@ X86ISA::I82094AA::signalInterrupt(int line) bits((int)entry.dest, 6) ? " 6": "", bits((int)entry.dest, 7) ? " 7": "" ); + uint8_t dests = entry.dest; + uint8_t id = 0; + while(dests) { + if (dests & 0x1) { + PacketPtr pkt = buildIntRequest(id, message); + if (sys->getMemoryMode() == Enums::timing) + intPort->sendMessageTiming(pkt, latency); + else if (sys->getMemoryMode() == Enums::atomic) + intPort->sendMessageAtomic(pkt); + else + panic("Unrecognized memory mode.\n"); + } + dests >>= 1; + id++; + } } - switch(entry.deliveryMode) { - case 0: - DPRINTF(I82094AA, "Delivery mode is: Fixed.\n"); - break; - case 1: - DPRINTF(I82094AA, "Delivery mode is: Lowest Priority.\n"); - break; - case 2: - DPRINTF(I82094AA, "Delivery mode is: SMI.\n"); - break; - case 3: - fatal("Tried to use reserved delivery mode " - "for IO APIC entry %d.\n", line); - break; - case 4: - DPRINTF(I82094AA, "Delivery mode is: NMI.\n"); - break; - case 5: - DPRINTF(I82094AA, "Delivery mode is: INIT.\n"); - break; - case 6: - fatal("Tried to use reserved delivery mode " - "for IO APIC entry %d.\n", line); - break; - case 7: - DPRINTF(I82094AA, "Delivery mode is: ExtINT.\n"); - break; - } - DPRINTF(I82094AA, "Vector is %#x.\n", entry.vector); } } diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index b442e3e92..6c874a5f9 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -60,6 +60,7 @@ class I82094AA : public PioDevice, public IntDev EndBitUnion(RedirTableEntry) protected: + System * system; Tick latency; Addr pioAddr; @@ -95,9 +96,23 @@ class I82094AA : public PioDevice, public IntDev range_list.push_back(RangeEx(pioAddr + 16, pioAddr + 20)); } + void getIntAddrRange(AddrRangeList &range_list) + { + range_list.clear(); + range_list.push_back(RangeEx(x86InterruptAddress(1, 0), + x86InterruptAddress(1, 0) + PhysAddrAPICRangeSize)); + } + void writeReg(uint8_t offset, uint32_t value); uint32_t readReg(uint8_t offset); + Port *getPort(const std::string &if_name, int idx = -1) + { + if (if_name == "int_port") + return intPort; + return PioDevice::getPort(if_name, idx); + } + void signalInterrupt(int line); }; diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index f38644222..1c14e5397 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -74,9 +74,9 @@ class I8259 : public BasicPioDevice, public IntDev return dynamic_cast(_params); } - I8259(Params * p) : BasicPioDevice(p), latency(p->pio_latency), - output(p->output), mode(p->mode), readIRR(true), - initControlWord(0) + I8259(Params * p) : BasicPioDevice(p), IntDev(this), + latency(p->pio_latency), output(p->output), + mode(p->mode), readIRR(true), initControlWord(0) { pioSize = 2; } diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh index 7a369f8fa..d36ed462a 100644 --- a/src/dev/x86/intdev.hh +++ b/src/dev/x86/intdev.hh @@ -32,7 +32,11 @@ #define __DEV_X86_INTDEV_HH__ #include +#include +#include "arch/x86/x86_traits.hh" +#include "mem/mem_object.hh" +#include "mem/mport.hh" #include "sim/sim_object.hh" #include "params/X86IntPin.hh" @@ -40,11 +44,73 @@ namespace X86ISA { class IntDev { + protected: + class IntPort : public MessagePort + { + IntDev * device; + Tick latency; + Addr intAddr; + public: + IntPort(const std::string &_name, MemObject * _parent, + IntDev *dev, Tick _latency) : + MessagePort(_name, _parent), device(dev), latency(_latency) + { + } + + void getDeviceAddressRanges(AddrRangeList &resp, bool &snoop) + { + snoop = false; + device->getIntAddrRange(resp); + } + + Tick recvMessage(PacketPtr pkt) + { + return device->recvMessage(pkt); + } + + void recvStatusChange(Status status) + { + if (status == RangeChange) { + sendStatusChange(Port::RangeChange); + } + } + + }; + + IntPort * intPort; + public: + IntDev(MemObject * parent, Tick latency = 0) + { + if (parent != NULL) { + intPort = new IntPort(parent->name() + ".int_port", + parent, this, latency); + } else { + intPort = NULL; + } + } + virtual ~IntDev() {} + + virtual void + signalInterrupt(int line) + { + panic("signalInterrupt not implemented.\n"); + } + + virtual Tick + recvMessage(PacketPtr pkt) + { + panic("recvMessage not implemented.\n"); + return 0; + } + virtual void - signalInterrupt(int line) = 0; + getIntAddrRange(AddrRangeList &range_list) + { + panic("intAddrRange not implemented.\n"); + } }; class IntPin : public SimObject -- cgit v1.2.3