From: Gabe Black Date: Mon, 22 Oct 2007 21:30:45 +0000 (-0700) Subject: CPU: Add functions to the "ExecContext"s that translate a given address. X-Git-Tag: m5_2.0_beta4~32 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=93da9eb7f6d9b2ca84de74afd3e0cb07188db9e6;p=gem5.git CPU: Add functions to the "ExecContext"s that translate a given address. --HG-- extra : convert_revision : 7d898c6b6b13094fd05326eaa0b095a3ab132397 --- diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 0f2a90bf6..74b250207 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -102,6 +102,9 @@ class BaseDynInst : public FastAlloc, public RefCounted template Fault read(Addr addr, T &data, unsigned flags); + Fault translateDataReadAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags); + /** * Does a write to a given address. * @param data The data to be written. @@ -114,6 +117,9 @@ class BaseDynInst : public FastAlloc, public RefCounted Fault write(T data, Addr addr, unsigned flags, uint64_t *res); + Fault translateDataWriteAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags); + void prefetch(Addr addr, unsigned flags); void writeHint(Addr addr, int size, unsigned flags); Fault copySrcTranslate(Addr src); @@ -837,6 +843,29 @@ class BaseDynInst : public FastAlloc, public RefCounted { thread->storeCondFailures = sc_failures; } }; +template +Fault +BaseDynInst::translateDataReadAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags) +{ + if (traceData) { + traceData->setAddr(vaddr); + } + + reqMade = true; + Request *req = new Request(); + req->setVirt(asid, vaddr, size, flags, PC); + req->setThreadContext(thread->readCpuId(), threadNumber); + + fault = cpu->translateDataReadReq(req, thread); + + if (fault == NoFault) + paddr = req->getPaddr(); + + delete req; + return fault; +} + template template inline Fault @@ -888,6 +917,29 @@ BaseDynInst::read(Addr addr, T &data, unsigned flags) return fault; } +template +Fault +BaseDynInst::translateDataWriteAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags) +{ + if (traceData) { + traceData->setAddr(vaddr); + } + + reqMade = true; + Request *req = new Request(); + req->setVirt(asid, vaddr, size, flags, PC); + req->setThreadContext(thread->readCpuId(), threadNumber); + + fault = cpu->translateDataWriteReq(req, thread); + + if (fault == NoFault) + paddr = req->getPaddr(); + + delete req; + return fault; +} + template template inline Fault diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 9f574e8be..4e52f9b33 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -366,6 +366,61 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) } } +Fault +AtomicSimpleCPU::translateDataReadAddr(Addr vaddr, Addr & paddr, + int size, unsigned flags) +{ + // use the CPU's statically allocated read request and packet objects + Request *req = &data_read_req; + + if (traceData) { + traceData->setAddr(vaddr); + } + + //The block size of our peer. + int blockSize = dcachePort.peerBlockSize(); + //The size of the data we're trying to read. + int dataSize = size; + + bool firstTimeThrough = true; + + //The address of the second part of this access if it needs to be split + //across a cache line boundary. + Addr secondAddr = roundDown(vaddr + dataSize - 1, blockSize); + + if(secondAddr > vaddr) + dataSize = secondAddr - vaddr; + + while(1) { + req->setVirt(0, vaddr, dataSize, flags, thread->readPC()); + + // translate to physical address + Fault fault = thread->translateDataReadReq(req); + + //If there's a fault, return it + if (fault != NoFault) + return fault; + + if (firstTimeThrough) { + paddr = req->getPaddr(); + firstTimeThrough = false; + } + + //If we don't need to access a second cache line, stop now. + if (secondAddr <= vaddr) + return fault; + + /* + * Set up for accessing the second cache line. + */ + + //Adjust the size to get the remaining bytes. + dataSize = vaddr + size - secondAddr; + //And access the right address. + vaddr = secondAddr; + } +} + #ifndef DOXYGEN_SHOULD_SKIP_THIS template @@ -524,6 +579,64 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) } } +Fault +AtomicSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags) +{ + // use the CPU's statically allocated write request and packet objects + Request *req = &data_write_req; + + if (traceData) { + traceData->setAddr(vaddr); + } + + //The block size of our peer. + int blockSize = dcachePort.peerBlockSize(); + + //The address of the second part of this access if it needs to be split + //across a cache line boundary. + Addr secondAddr = roundDown(vaddr + size - 1, blockSize); + + //The size of the data we're trying to read. + int dataSize = size; + + bool firstTimeThrough = true; + + if(secondAddr > vaddr) + dataSize = secondAddr - vaddr; + + dcache_latency = 0; + + while(1) { + req->setVirt(0, vaddr, flags, flags, thread->readPC()); + + // translate to physical address + Fault fault = thread->translateDataWriteReq(req); + + //If there's a fault or we don't need to access a second cache line, + //stop now. + if (fault != NoFault) + return fault; + + if (firstTimeThrough) { + paddr = req->getPaddr(); + firstTimeThrough = false; + } + + if (secondAddr <= vaddr) + return fault; + + /* + * Set up for accessing the second cache line. + */ + + //Adjust the size to get the remaining bytes. + dataSize = vaddr + size - secondAddr; + //And access the right address. + vaddr = secondAddr; + } +} + #ifndef DOXYGEN_SHOULD_SKIP_THIS diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 96429e5b1..f68f41a90 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -151,6 +151,11 @@ class AtomicSimpleCPU : public BaseSimpleCPU template Fault write(T data, Addr addr, unsigned flags, uint64_t *res); + + Fault translateDataReadAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags); + Fault translateDataWriteAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags); }; #endif // __CPU_SIMPLE_ATOMIC_HH__ diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index f1e51ac70..998d0b017 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -293,6 +293,26 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) return fault; } +Fault +TimingSimpleCPU::translateDataReadAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags) +{ + Request *req = + new Request(0, vaddr, size, flags, thread->readPC(), cpuId, 0); + + if (traceData) { + traceData->setAddr(vaddr); + } + + Fault fault = thread->translateDataWriteReq(req); + + if (fault == NoFault) + paddr = req->getPaddr(); + + delete req; + return fault; +} + #ifndef DOXYGEN_SHOULD_SKIP_THIS template @@ -411,6 +431,26 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) return fault; } +Fault +TimingSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags) +{ + Request *req = + new Request(0, vaddr, size, flags, thread->readPC(), cpuId, 0); + + if (traceData) { + traceData->setAddr(vaddr); + } + + Fault fault = thread->translateDataWriteReq(req); + + if (fault == NoFault) + paddr = req->getPaddr(); + + delete req; + return fault; +} + #ifndef DOXYGEN_SHOULD_SKIP_THIS template diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 668b6ddaf..d7554f6de 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -189,9 +189,15 @@ class TimingSimpleCPU : public BaseSimpleCPU template Fault read(Addr addr, T &data, unsigned flags); + Fault translateDataReadAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags); + template Fault write(T data, Addr addr, unsigned flags, uint64_t *res); + Fault translateDataWriteAddr(Addr vaddr, Addr &paddr, + int size, unsigned flags); + void fetch(); void completeIfetch(PacketPtr ); void completeDataAccess(PacketPtr );