MEM: Separate queries for snooping and address ranges
This patch simplifies the address-range determination mechanism and also unifies the naming across ports and devices. It further splits the queries for determining if a port is snooping and what address ranges it responds to (aiming towards a separation of cache-maintenance ports and pure memory-mapped ports). Default behaviours are such that most ports do not have to define isSnooping, and master ports need not implement getAddrRanges.
This commit is contained in:
@@ -703,12 +703,13 @@ Gic::postInt(uint32_t cpu, Tick when)
|
||||
eventq->schedule(postIntEvent[cpu], when);
|
||||
}
|
||||
|
||||
void
|
||||
Gic::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
Gic::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(distAddr, DIST_SIZE));
|
||||
range_list.push_back(RangeSize(cpuAddr, CPU_SIZE));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(distAddr, DIST_SIZE));
|
||||
ranges.push_back(RangeSize(cpuAddr, CPU_SIZE));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ class Gic : public PioDevice
|
||||
/** Return the address ranges used by the Gic
|
||||
* This is the distributor address + all cpu addresses
|
||||
*/
|
||||
virtual void addressRanges(AddrRangeList &range_list);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
/** A PIO read to the device, immediately split up into
|
||||
* readDistributor() or readCpu()
|
||||
|
||||
@@ -735,11 +735,12 @@ Pl111::generateInterrupt()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::addressRanges(AddrRangeList& range_list)
|
||||
AddrRangeList
|
||||
Pl111::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(pioAddr, pioSize));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(pioAddr, pioSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
Pl111 *
|
||||
|
||||
@@ -325,10 +325,12 @@ class Pl111: public AmbaDmaDevice
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
/** return the address ranges that this device responds to.
|
||||
* @param range_list range list to populate with ranges
|
||||
/**
|
||||
* Determine the address ranges that this device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -85,7 +85,6 @@ class CopyEngine : public PciDev
|
||||
void init();
|
||||
|
||||
std::string name() { assert(ce); return ce->name() + csprintf("-chan%d", channelId); }
|
||||
virtual void addressRanges(AddrRangeList &range_list) { range_list.clear(); }
|
||||
virtual Tick read(PacketPtr pkt)
|
||||
{ panic("CopyEngineChannel has no I/O access\n");}
|
||||
virtual Tick write(PacketPtr pkt)
|
||||
|
||||
@@ -47,13 +47,10 @@ PioPort::recvAtomic(PacketPtr pkt)
|
||||
return pkt->isRead() ? device->read(pkt) : device->write(pkt);
|
||||
}
|
||||
|
||||
void
|
||||
PioPort::getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
|
||||
AddrRangeList
|
||||
PioPort::getAddrRanges()
|
||||
{
|
||||
snoop = false;
|
||||
device->addressRanges(resp);
|
||||
for (AddrRangeIter i = resp.begin(); i != resp.end(); i++)
|
||||
DPRINTF(BusAddrRanges, "Adding Range %#x-%#x\n", i->start, i->end);
|
||||
return device->getAddrRanges();
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +69,7 @@ PioDevice::init()
|
||||
{
|
||||
if (!pioPort)
|
||||
panic("Pio port of %s not connected to anything!", name());
|
||||
pioPort->sendStatusChange(Port::RangeChange);
|
||||
pioPort->sendRangeChange();
|
||||
}
|
||||
|
||||
Port *
|
||||
@@ -105,13 +102,14 @@ BasicPioDevice::BasicPioDevice(const Params *p)
|
||||
pioDelay(p->pio_latency)
|
||||
{}
|
||||
|
||||
void
|
||||
BasicPioDevice::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
BasicPioDevice::getAddrRanges()
|
||||
{
|
||||
assert(pioSize != 0);
|
||||
range_list.clear();
|
||||
AddrRangeList ranges;
|
||||
DPRINTF(BusAddrRanges, "registering range: %#x-%#x\n", pioAddr, pioSize);
|
||||
range_list.push_back(RangeSize(pioAddr, pioSize));
|
||||
ranges.push_back(RangeSize(pioAddr, pioSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +119,7 @@ DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff,
|
||||
pendingCount(0), actionInProgress(0), drainEvent(NULL),
|
||||
backoffTime(0), minBackoffDelay(min_backoff),
|
||||
maxBackoffDelay(max_backoff), inRetry(false), recvSnoops(recv_snoops),
|
||||
snoopRangeSent(false), backoffEvent(this)
|
||||
backoffEvent(this)
|
||||
{ }
|
||||
|
||||
bool
|
||||
|
||||
@@ -51,7 +51,7 @@ class System;
|
||||
* The PioPort class is a programmed i/o port that all devices that are
|
||||
* sensitive to an address range use. The port takes all the memory
|
||||
* access types and roles them into one read() and write() call that the device
|
||||
* must respond to. The device must also provide the addressRanges() function
|
||||
* must respond to. The device must also provide getAddrRanges() function
|
||||
* with which it returns the address ranges it is interested in.
|
||||
*/
|
||||
class PioPort : public SimpleTimingPort
|
||||
@@ -62,8 +62,7 @@ class PioPort : public SimpleTimingPort
|
||||
|
||||
virtual Tick recvAtomic(PacketPtr pkt);
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
public:
|
||||
|
||||
@@ -133,9 +132,6 @@ class DmaPort : public Port
|
||||
/** Port accesses a cache which requires snooping */
|
||||
bool recvSnoops;
|
||||
|
||||
/** Records snoop response so we only reply once to a status change */
|
||||
bool snoopRangeSent;
|
||||
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
virtual Tick recvAtomic(PacketPtr pkt)
|
||||
{
|
||||
@@ -150,25 +146,16 @@ class DmaPort : public Port
|
||||
panic("dma port shouldn't be used for pio access.");
|
||||
}
|
||||
|
||||
virtual void recvStatusChange(Status status)
|
||||
virtual void recvRangeChange()
|
||||
{
|
||||
if (recvSnoops) {
|
||||
if (status == RangeChange) {
|
||||
if (!snoopRangeSent) {
|
||||
snoopRangeSent = true;
|
||||
sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
return;
|
||||
}
|
||||
panic("Unexpected recvStatusChange\n");
|
||||
}
|
||||
// DMA port is a master with a single slave so there is no choice and
|
||||
// thus no need to worry about any address changes
|
||||
}
|
||||
|
||||
virtual void recvRetry() ;
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
{ resp.clear(); snoop = recvSnoops; }
|
||||
virtual bool isSnooping()
|
||||
{ return recvSnoops; }
|
||||
|
||||
void queueDma(PacketPtr pkt, bool front = false);
|
||||
void sendDma();
|
||||
@@ -192,7 +179,7 @@ class DmaPort : public Port
|
||||
/**
|
||||
* This device is the base class which all devices senstive to an address range
|
||||
* inherit from. There are three pure virtual functions which all devices must
|
||||
* implement addressRanges(), read(), and write(). The magic do choose which
|
||||
* implement getAddrRanges(), read(), and write(). The magic do choose which
|
||||
* mode we are in, etc is handled by the PioPort so the device doesn't have to
|
||||
* bother.
|
||||
*/
|
||||
@@ -210,7 +197,13 @@ class PioDevice : public MemObject
|
||||
* that it sees. */
|
||||
PioPort *pioPort;
|
||||
|
||||
virtual void addressRanges(AddrRangeList &range_list) = 0;
|
||||
/**
|
||||
* Every PIO device is obliged to provide an implementation that
|
||||
* returns the address ranges the device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
virtual AddrRangeList getAddrRanges() = 0;
|
||||
|
||||
/** Pure virtual function that the device must implement. Called
|
||||
* when a read command is recieved by the port.
|
||||
@@ -269,10 +262,12 @@ class BasicPioDevice : public PioDevice
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
/** return the address ranges that this device responds to.
|
||||
* @param range_list range list to populate with ranges
|
||||
/**
|
||||
* Determine the address ranges that this device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -86,11 +86,12 @@ PciConfigAll::write(PacketPtr pkt)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PciConfigAll::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
PciConfigAll::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(pioAddr, params()->size));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(pioAddr, params()->size));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ class PciConfigAll : public PioDevice
|
||||
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
|
||||
private:
|
||||
Addr pioAddr;
|
||||
|
||||
@@ -72,13 +72,13 @@ PciDev::PciConfigPort::recvAtomic(PacketPtr pkt)
|
||||
return pkt->isRead() ? device->readConfig(pkt) : device->writeConfig(pkt);
|
||||
}
|
||||
|
||||
void
|
||||
PciDev::PciConfigPort::getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
AddrRangeList
|
||||
PciDev::PciConfigPort::getAddrRanges()
|
||||
{
|
||||
snoop = false;;
|
||||
AddrRangeList ranges;
|
||||
if (configAddr != ULL(-1))
|
||||
resp.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1));
|
||||
ranges.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ PciDev::init()
|
||||
{
|
||||
if (!configPort)
|
||||
panic("pci config port not connected to anything!");
|
||||
configPort->sendStatusChange(Port::RangeChange);
|
||||
configPort->sendRangeChange();
|
||||
PioDevice::init();
|
||||
}
|
||||
|
||||
@@ -207,14 +207,15 @@ PciDev::readConfig(PacketPtr pkt)
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
PciDev::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
PciDev::getAddrRanges()
|
||||
{
|
||||
AddrRangeList ranges;
|
||||
int x = 0;
|
||||
range_list.clear();
|
||||
for (x = 0; x < 6; x++)
|
||||
if (BARAddrs[x] != 0)
|
||||
range_list.push_back(RangeSize(BARAddrs[x],BARSize[x]));
|
||||
ranges.push_back(RangeSize(BARAddrs[x],BARSize[x]));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
Tick
|
||||
@@ -301,7 +302,7 @@ PciDev::writeConfig(PacketPtr pkt)
|
||||
BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ?
|
||||
platform->calcPciIOAddr(he_new_bar) :
|
||||
platform->calcPciMemAddr(he_new_bar);
|
||||
pioPort->sendStatusChange(Port::RangeChange);
|
||||
pioPort->sendRangeChange();
|
||||
}
|
||||
}
|
||||
config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) |
|
||||
@@ -354,7 +355,7 @@ PciDev::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
|
||||
UNSERIALIZE_ARRAY(config.data,
|
||||
sizeof(config.data) / sizeof(config.data[0]));
|
||||
pioPort->sendStatusChange(Port::RangeChange);
|
||||
pioPort->sendRangeChange();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +65,7 @@ class PciDev : public DmaDevice
|
||||
|
||||
virtual Tick recvAtomic(PacketPtr pkt);
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
Platform *platform;
|
||||
|
||||
@@ -187,10 +186,12 @@ class PciDev : public DmaDevice
|
||||
interruptLine()
|
||||
{ return letoh(config.interruptLine); }
|
||||
|
||||
/** return the address ranges that this device responds to.
|
||||
* @params range_list range list to populate with ranges
|
||||
/**
|
||||
* Determine the address ranges that this device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
|
||||
/**
|
||||
* Constructor for PCI Dev. This function copies data from the
|
||||
|
||||
@@ -1714,7 +1714,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
if (transmitTick)
|
||||
schedule(txEvent, curTick() + transmitTick);
|
||||
|
||||
pioPort->sendStatusChange(Port::RangeChange);
|
||||
pioPort->sendRangeChange();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -325,12 +325,13 @@ Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Iob::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
Iob::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(iobManAddr, iobManSize));
|
||||
range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(iobManAddr, iobManSize));
|
||||
ranges.push_back(RangeSize(iobJBusAddr, iobJBusSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ class Iob : public PioDevice
|
||||
bool receiveJBusInterrupt(int cpu_id, int source, uint64_t d0,
|
||||
uint64_t d1);
|
||||
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
@@ -286,16 +286,14 @@ Uart8250::dataAvailable()
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Uart8250::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
Uart8250::getAddrRanges()
|
||||
{
|
||||
assert(pioSize != 0);
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(pioAddr, pioSize));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(pioAddr, pioSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Uart8250::serialize(ostream &os)
|
||||
{
|
||||
|
||||
@@ -100,7 +100,7 @@ class Uart8250 : public Uart
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
virtual void addressRanges(AddrRangeList &range_list);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
/**
|
||||
* Inform the uart that there is data available.
|
||||
|
||||
@@ -43,12 +43,13 @@ const uint8_t CommandAck = 0xfa;
|
||||
const uint8_t CommandNack = 0xfe;
|
||||
const uint8_t BatSuccessful = 0xaa;
|
||||
|
||||
void
|
||||
X86ISA::I8042::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
X86ISA::I8042::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(dataPort, 1));
|
||||
range_list.push_back(RangeSize(commandPort, 1));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(dataPort, 1));
|
||||
ranges.push_back(RangeSize(commandPort, 1));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -255,7 +255,7 @@ class I8042 : public BasicPioDevice
|
||||
commandByte.keyboardFullInt = 1;
|
||||
}
|
||||
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
|
||||
Tick read(PacketPtr pkt);
|
||||
|
||||
|
||||
@@ -103,19 +103,21 @@ class I82094AA : public PioDevice, public IntDev
|
||||
Tick read(PacketPtr pkt);
|
||||
Tick write(PacketPtr pkt);
|
||||
|
||||
void addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeEx(pioAddr, pioAddr + 4));
|
||||
range_list.push_back(RangeEx(pioAddr + 16, pioAddr + 20));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeEx(pioAddr, pioAddr + 4));
|
||||
ranges.push_back(RangeEx(pioAddr + 16, pioAddr + 20));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
void getIntAddrRange(AddrRangeList &range_list)
|
||||
AddrRangeList getIntAddrRange()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
|
||||
x86InterruptAddress(initialApicId, 0) +
|
||||
PhysAddrAPICRangeSize));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
|
||||
x86InterruptAddress(initialApicId, 0) +
|
||||
PhysAddrAPICRangeSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
void writeReg(uint8_t offset, uint32_t value);
|
||||
|
||||
@@ -54,7 +54,7 @@ X86ISA::IntDev::init()
|
||||
if (!intPort) {
|
||||
panic("Int port not connected to anything!");
|
||||
}
|
||||
intPort->sendStatusChange(Port::RangeChange);
|
||||
intPort->sendRangeChange();
|
||||
}
|
||||
|
||||
X86ISA::IntSourcePin *
|
||||
|
||||
@@ -63,10 +63,9 @@ class IntDev
|
||||
{
|
||||
}
|
||||
|
||||
void getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
|
||||
AddrRangeList getAddrRanges()
|
||||
{
|
||||
snoop = false;
|
||||
device->getIntAddrRange(resp);
|
||||
return device->getIntAddrRange();
|
||||
}
|
||||
|
||||
Tick recvMessage(PacketPtr pkt)
|
||||
@@ -134,8 +133,8 @@ class IntDev
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void
|
||||
getIntAddrRange(AddrRangeList &range_list)
|
||||
virtual AddrRangeList
|
||||
getIntAddrRange()
|
||||
{
|
||||
panic("intAddrRange not implemented.\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user