diff options
-rw-r--r-- | src/arch/alpha/linux/system.cc | 7 | ||||
-rw-r--r-- | src/arch/alpha/stacktrace.cc | 36 | ||||
-rw-r--r-- | src/base/remote_gdb.cc | 9 | ||||
-rw-r--r-- | src/cpu/simple_thread.cc | 7 | ||||
-rw-r--r-- | src/dev/io_device.cc | 57 | ||||
-rw-r--r-- | src/dev/io_device.hh | 18 | ||||
-rw-r--r-- | src/mem/packet.hh | 11 | ||||
-rw-r--r-- | src/mem/port.hh | 8 | ||||
-rw-r--r-- | src/mem/port_impl.hh | 53 | ||||
-rw-r--r-- | src/mem/vport.hh | 2 |
10 files changed, 165 insertions, 43 deletions
diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc index e6c6f42e9..3e061bba8 100644 --- a/src/arch/alpha/linux/system.cc +++ b/src/arch/alpha/linux/system.cc @@ -181,8 +181,11 @@ LinuxAlphaSystem::setDelayLoop(ThreadContext *tc) if (kernelSymtab->findAddress("loops_per_jiffy", addr)) { Tick cpuFreq = tc->getCpuPtr()->frequency(); Tick intrFreq = platform->intrFrequency(); - tc->getVirtPort(tc)->write(addr, - (uint32_t)((cpuFreq / intrFreq) * 0.9988)); + VirtualPort *vp; + + vp = tc->getVirtPort(); + vp->writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988)); + tc->delVirtPort(vp); } } diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc index 3519fd940..d70a4d6dd 100644 --- a/src/arch/alpha/stacktrace.cc +++ b/src/arch/alpha/stacktrace.cc @@ -47,25 +47,31 @@ ProcessInfo::ProcessInfo(ThreadContext *_tc) { Addr addr = 0; + VirtualPort *vp; + + vp = tc->getVirtPort(); + if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) panic("thread info not compiled into kernel\n"); - thread_info_size = gtoh(tc->getVirtPort()->read<int32_t>(addr)); + thread_info_size = vp->readGtoH<int32_t>(addr); if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) panic("thread info not compiled into kernel\n"); - task_struct_size = gtoh(tc->getVirtPort()->read<int32_t>(addr)); + task_struct_size = vp->readGtoH<int32_t>(addr); if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) panic("thread info not compiled into kernel\n"); - task_off = gtoh(tc->getVirtPort()->read<int32_t>(addr)); + task_off = vp->readGtoH<int32_t>(addr); if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) panic("thread info not compiled into kernel\n"); - pid_off = gtoh(tc->getVirtPort()->read<int32_t>(addr)); + pid_off = vp->readGtoH<int32_t>(addr); if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) panic("thread info not compiled into kernel\n"); - name_off = gtoh(tc->getVirtPort()->read<int32_t>(addr)); + name_off = vp->readGtoH<int32_t>(addr); + + tc->delVirtPort(vp); } Addr @@ -75,7 +81,15 @@ ProcessInfo::task(Addr ksp) const if (base == ULL(0xfffffc0000000000)) return 0; - return gtoh(tc->getVirtPort()->read<Addr>(base + task_off)); + Addr tsk; + + VirtualPort *vp; + + vp = tc->getVirtPort(); + tsk = vp->readGtoH<Addr>(base + task_off); + tc->delVirtPort(vp); + + return tsk; } int @@ -85,7 +99,15 @@ ProcessInfo::pid(Addr ksp) const if (!task) return -1; - return gtoh(tc->getVirtPort()->read<uint16_t>(task + pid_off)); + uint16_t pd; + + VirtualPort *vp; + + vp = tc->getVirtPort(); + pd = vp->readGtoH<uint16_t>(task + pid_off); + tc->delVirtPort(vp); + + return pd; } string diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 2b545d13c..0d3b73b1e 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -642,7 +642,9 @@ RemoteGDB::read(Addr vaddr, size_t size, char *data) DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size); - context->getVirtPort(context)->readBlob(vaddr, (uint8_t*)data, size); + VirtualPort *vp = context->getVirtPort(context); + vp->readBlob(vaddr, (uint8_t*)data, size); + context->delVirtPort(vp); #if TRACING_ON if (DTRACE(GDBRead)) { @@ -679,8 +681,9 @@ RemoteGDB::write(Addr vaddr, size_t size, const char *data) } else DPRINTFNR("\n"); } - - context->getVirtPort(context)->writeBlob(vaddr, (uint8_t*)data, size); + VirtualPort *vp = context->getVirtPort(context); + vp->writeBlob(vaddr, (uint8_t*)data, size); + context->delVirtPort(vp); #ifdef IMB alpha_pal_imb(); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 219167e4e..48383ca93 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -314,9 +314,10 @@ SimpleThread::getVirtPort(ThreadContext *src_tc) void SimpleThread::delVirtPort(VirtualPort *vp) { -// assert(!vp->nullThreadContext()); - delete vp->getPeer(); - delete vp; + if (vp != virtPort) { + delete vp->getPeer(); + delete vp; + } } diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index f0509429f..485216874 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -120,19 +120,32 @@ DmaPort::DmaPort(DmaDevice *dev, Platform *p) bool DmaPort::recvTiming(Packet *pkt) { - if (pkt->senderState) { + + + if (pkt->result == Packet::Nacked) { + DPRINTF(DMA, "Received nacked Pkt %#x with State: %#x Addr: %#x\n", + pkt, pkt->senderState, pkt->getAddr()); + pkt->reinitNacked(); + sendDma(pkt, true); + } else if (pkt->senderState) { DmaReqState *state; - DPRINTF(DMA, "Received response Packet %#x with senderState: %#x\n", - pkt, pkt->senderState); + DPRINTF(DMA, "Received response Pkt %#x with State: %#x Addr: %#x\n", + pkt, pkt->senderState, pkt->getAddr()); state = dynamic_cast<DmaReqState*>(pkt->senderState); + pendingCount--; + + assert(pendingCount >= 0); assert(state); - state->completionEvent->process(); + + state->numBytes += pkt->req->getSize(); + if (state->totBytes == state->numBytes) { + state->completionEvent->process(); + delete state; + } delete pkt->req; delete pkt; } else { - DPRINTF(DMA, "Received response Packet %#x with no senderState\n", pkt); - delete pkt->req; - delete pkt; + panic("Got packet without sender state... huh?\n"); } return true; @@ -154,8 +167,6 @@ DmaPort::recvRetry() if (result) { DPRINTF(DMA, "-- Done\n"); transmitList.pop_front(); - pendingCount--; - assert(pendingCount >= 0); } else { DPRINTF(DMA, "-- Failed, queued\n"); } @@ -169,7 +180,7 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, { assert(event); - int prevSize = 0; + DmaReqState *reqState = new DmaReqState(event, this, size); for (ChunkGenerator gen(addr, size, peerBlockSize()); !gen.done(); gen.next()) { @@ -178,15 +189,10 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, // Increment the data pointer on a write if (data) - pkt->dataStatic(data + prevSize); + pkt->dataStatic(data + gen.complete()); - prevSize += gen.size(); + pkt->senderState = reqState; - // Set the last bit of the dma as the final packet for this dma - // and set it's completion event. - if (prevSize == size) { - pkt->senderState = new DmaReqState(event, true); - } assert(pendingCount >= 0); pendingCount++; sendDma(pkt); @@ -195,7 +201,7 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, void -DmaPort::sendDma(Packet *pkt) +DmaPort::sendDma(Packet *pkt, bool front) { // some kind of selction between access methods // more work is going to have to be done to make @@ -203,22 +209,25 @@ DmaPort::sendDma(Packet *pkt) /* MemState state = device->platform->system->memState; if (state == Timing) { */ - DPRINTF(DMA, "Attempting to send Packet %#x with senderState: %#x\n", - pkt, pkt->senderState); + DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n", + pkt, pkt->getAddr()); if (transmitList.size() || !sendTiming(pkt)) { - transmitList.push_back(pkt); + if (front) + transmitList.push_front(pkt); + else + transmitList.push_back(pkt); DPRINTF(DMA, "-- Failed: queued\n"); } else { DPRINTF(DMA, "-- Done\n"); - pendingCount--; - assert(pendingCount >= 0); } /* } else if (state == Atomic) { sendAtomic(pkt); if (pkt->senderState) { DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState); assert(state); - state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1); + state->completionEvent->schedule(curTick + (pkt->time - + pkt->req->getTime()) +1); + delete state; } pendingCount--; assert(pendingCount >= 0); diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index 3cb18c9fa..195ca0fb7 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -121,10 +121,22 @@ class PioPort : public Port struct DmaReqState : public Packet::SenderState { + /** Event to call on the device when this transaction (all packets) + * complete. */ Event *completionEvent; + + /** Where we came from for some sanity checking. */ + Port *outPort; + + /** Total number of bytes that this transaction involves. */ + Addr totBytes; + + /** Number of bytes that have been acked for this transaction. */ + Addr numBytes; + bool final; - DmaReqState(Event *ce, bool f) - : completionEvent(ce), final(f) + DmaReqState(Event *ce, Port *p, Addr tb) + : completionEvent(ce), outPort(p), totBytes(tb), numBytes(0) {} }; @@ -155,7 +167,7 @@ class DmaPort : public Port virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) { resp.clear(); snoop.clear(); } - void sendDma(Packet *pkt); + void sendDma(Packet *pkt, bool front = false); public: DmaPort(DmaDevice *dev, Platform *p); diff --git a/src/mem/packet.hh b/src/mem/packet.hh index d5a10d29a..403039d96 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -179,6 +179,7 @@ class Packet { Success, BadAddress, + Nacked, Unknown }; @@ -249,6 +250,16 @@ class Packet srcValid = false; } + /** Take a request packet that has been returned as NACKED and modify it so + * that it can be sent out again. Only packets that need a response can be + * NACKED, so verify that that is true. */ + void reinitNacked() { + assert(needsResponse() && result == Nacked); + dest = Broadcast; + result = Unknown; + } + + /** Set the data pointer to the following value that should not be freed. */ template <typename T> void dataStatic(T *p); diff --git a/src/mem/port.hh b/src/mem/port.hh index b89c7dbd3..2edad095e 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -249,6 +249,14 @@ class FunctionalPort : public Port virtual void recvFunctional(Packet *pkt) { panic("FuncPort is UniDir"); } virtual void recvStatusChange(Status status) {} + /** a write function that also does an endian conversion. */ + template <typename T> + inline void writeHtoG(Addr addr, T d); + + /** a read function that also does an endian conversion. */ + template <typename T> + inline T readGtoH(Addr addr); + template <typename T> inline void write(Addr addr, T d) { diff --git a/src/mem/port_impl.hh b/src/mem/port_impl.hh new file mode 100644 index 000000000..e9a159293 --- /dev/null +++ b/src/mem/port_impl.hh @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include "arch/isa_specific.hh" +#include "arch/isa_traits.hh" +#include "mem/port.hh" +#include "sim/byteswap.hh" + +template <typename T> +void +FunctionalPort::writeHtoG(Addr addr, T d) +{ + d = TheISA::htog(d); + writeBlob(addr, (uint8_t*)&d, sizeof(T)); +} + + +template <typename T> +T +FunctionalPort::readGtoH(Addr addr) +{ + T d; + readBlob(addr, (uint8_t*)&d, sizeof(T)); + return TheISA::gtoh(d); +} + diff --git a/src/mem/vport.hh b/src/mem/vport.hh index 56f2ff29e..697c8e5f3 100644 --- a/src/mem/vport.hh +++ b/src/mem/vport.hh @@ -38,7 +38,7 @@ #ifndef __MEM_VPORT_HH__ #define __MEM_VPORT_HH__ -#include "mem/port.hh" +#include "mem/port_impl.hh" #include "config/full_system.hh" #include "arch/vtophys.hh" |