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:
Andreas Hansson
2012-01-17 12:55:09 -06:00
parent 142380a373
commit 07cf9d914b
54 changed files with 345 additions and 416 deletions

View File

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

View File

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

View File

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

View File

@@ -325,10 +325,12 @@ class Pl111: public AmbaDmaDevice
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
/** 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

View File

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

View File

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

View File

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

View File

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

View File

@@ -80,7 +80,7 @@ class PciConfigAll : public PioDevice
virtual Tick write(PacketPtr pkt);
void addressRanges(AddrRangeList &range_list);
AddrRangeList getAddrRanges();
private:
Addr pioAddr;

View File

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

View File

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

View File

@@ -1714,7 +1714,7 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
if (transmitTick)
schedule(txEvent, curTick() + transmitTick);
pioPort->sendStatusChange(Port::RangeChange);
pioPort->sendRangeChange();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -255,7 +255,7 @@ class I8042 : public BasicPioDevice
commandByte.keyboardFullInt = 1;
}
void addressRanges(AddrRangeList &range_list);
AddrRangeList getAddrRanges();
Tick read(PacketPtr pkt);

View File

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

View File

@@ -54,7 +54,7 @@ X86ISA::IntDev::init()
if (!intPort) {
panic("Int port not connected to anything!");
}
intPort->sendStatusChange(Port::RangeChange);
intPort->sendRangeChange();
}
X86ISA::IntSourcePin *

View File

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