mem: Use the MMU's translation generator in translating proxies.
Use the more flexible MMU translation generator which does not need to be told what page size to use, and which will be able to do flexible things like translate across varying page sizes. Change-Id: Ibfefc39d833f37bc35d703c505b193ea68988ab0 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/50760 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Matthew Poremba <matthew.poremba@amd.com> Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br> Maintainer: Gabe Black <gabe.black@gmail.com>
This commit is contained in:
@@ -52,15 +52,17 @@ SETranslatingPortProxy::SETranslatingPortProxy(
|
||||
{}
|
||||
|
||||
bool
|
||||
SETranslatingPortProxy::fixupAddr(Addr addr, BaseMMU::Mode mode) const
|
||||
SETranslatingPortProxy::fixupRange(const TranslationGen::Range &range,
|
||||
BaseMMU::Mode mode) const
|
||||
{
|
||||
auto *process = _tc->getProcessPtr();
|
||||
|
||||
if (mode == BaseMMU::Write) {
|
||||
if (allocating == Always) {
|
||||
process->allocateMem(roundDown(addr, pageBytes), pageBytes);
|
||||
process->allocateMem(range.vaddr, range.size);
|
||||
return true;
|
||||
} else if (allocating == NextPage && process->fixupFault(addr)) {
|
||||
} else if (allocating == NextPage &&
|
||||
process->fixupFault(range.vaddr)) {
|
||||
// We've accessed the next page on the stack.
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,8 @@ class SETranslatingPortProxy : public TranslatingPortProxy
|
||||
AllocType allocating;
|
||||
|
||||
protected:
|
||||
bool fixupAddr(Addr addr, BaseMMU::Mode mode) const override;
|
||||
bool fixupRange(const TranslationGen::Range &range,
|
||||
BaseMMU::Mode mode) const override;
|
||||
|
||||
public:
|
||||
SETranslatingPortProxy(ThreadContext *tc, AllocType alloc=NextPage,
|
||||
|
||||
@@ -56,87 +56,69 @@ namespace gem5
|
||||
|
||||
TranslatingPortProxy::TranslatingPortProxy(
|
||||
ThreadContext *tc, Request::Flags _flags) :
|
||||
PortProxy(tc, tc->getSystemPtr()->cacheLineSize()), _tc(tc),
|
||||
pageBytes(tc->getSystemPtr()->getPageBytes()),
|
||||
flags(_flags)
|
||||
PortProxy(tc, tc->getSystemPtr()->cacheLineSize()), _tc(tc), flags(_flags)
|
||||
{}
|
||||
|
||||
bool
|
||||
TranslatingPortProxy::tryTLBsOnce(RequestPtr req, BaseMMU::Mode mode) const
|
||||
TranslatingPortProxy::tryOnBlob(BaseMMU::Mode mode, TranslationGenPtr gen,
|
||||
std::function<void(const TranslationGen::Range &)> func) const
|
||||
{
|
||||
BaseMMU *mmu = _tc->getMMUPtr();
|
||||
return mmu->translateFunctional(req, _tc, mode) == NoFault ||
|
||||
mmu->translateFunctional(req, _tc, BaseMMU::Execute) == NoFault;
|
||||
}
|
||||
// Wether we're trying to get past a fault.
|
||||
bool faulting = false;
|
||||
for (const auto &range: *gen) {
|
||||
// Was there a fault this time?
|
||||
if (range.fault) {
|
||||
// If there was a fault last time too, or the fixup this time
|
||||
// fails, then the operation has failed.
|
||||
if (faulting || !fixupRange(range, mode))
|
||||
return false;
|
||||
// This must be the first time we've tried this translation, so
|
||||
// record that we're making a second attempt and continue.
|
||||
faulting = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool
|
||||
TranslatingPortProxy::tryTLBs(RequestPtr req, BaseMMU::Mode mode) const
|
||||
{
|
||||
// If at first this doesn't succeed, try to fixup and translate again. If
|
||||
// it still fails, report failure.
|
||||
return tryTLBsOnce(req, mode) ||
|
||||
(fixupAddr(req->getVaddr(), mode) && tryTLBsOnce(req, mode));
|
||||
// Run func() on this successful translation.
|
||||
faulting = false;
|
||||
func(range);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TranslatingPortProxy::tryReadBlob(Addr addr, void *p, int size) const
|
||||
{
|
||||
for (ChunkGenerator gen(addr, size, pageBytes); !gen.done();
|
||||
gen.next())
|
||||
{
|
||||
auto req = std::make_shared<Request>(
|
||||
gen.addr(), gen.size(), flags, Request::funcRequestorId, 0,
|
||||
_tc->contextId());
|
||||
|
||||
if (!tryTLBs(req, BaseMMU::Read))
|
||||
return false;
|
||||
|
||||
PortProxy::readBlobPhys(
|
||||
req->getPaddr(), req->getFlags(), p, gen.size());
|
||||
|
||||
p = static_cast<uint8_t *>(p) + gen.size();
|
||||
}
|
||||
return true;
|
||||
constexpr auto mode = BaseMMU::Read;
|
||||
return tryOnBlob(mode, _tc->getMMUPtr()->translateFunctional(
|
||||
addr, size, _tc, mode, flags),
|
||||
[this, &p](const auto &range) {
|
||||
PortProxy::readBlobPhys(range.paddr, flags, p, range.size);
|
||||
p = static_cast<uint8_t *>(p) + range.size;
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
TranslatingPortProxy::tryWriteBlob(
|
||||
Addr addr, const void *p, int size) const
|
||||
{
|
||||
for (ChunkGenerator gen(addr, size, pageBytes); !gen.done();
|
||||
gen.next())
|
||||
{
|
||||
auto req = std::make_shared<Request>(
|
||||
gen.addr(), gen.size(), flags, Request::funcRequestorId, 0,
|
||||
_tc->contextId());
|
||||
|
||||
if (!tryTLBs(req, BaseMMU::Write))
|
||||
return false;
|
||||
|
||||
PortProxy::writeBlobPhys(
|
||||
req->getPaddr(), req->getFlags(), p, gen.size());
|
||||
p = static_cast<const uint8_t *>(p) + gen.size();
|
||||
}
|
||||
return true;
|
||||
constexpr auto mode = BaseMMU::Write;
|
||||
return tryOnBlob(mode, _tc->getMMUPtr()->translateFunctional(
|
||||
addr, size, _tc, mode, flags),
|
||||
[this, &p](const auto &range) {
|
||||
PortProxy::writeBlobPhys(range.paddr, flags, p, range.size);
|
||||
p = static_cast<const uint8_t *>(p) + range.size;
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
TranslatingPortProxy::tryMemsetBlob(Addr address, uint8_t v, int size) const
|
||||
TranslatingPortProxy::tryMemsetBlob(Addr addr, uint8_t v, int size) const
|
||||
{
|
||||
for (ChunkGenerator gen(address, size, pageBytes); !gen.done();
|
||||
gen.next())
|
||||
{
|
||||
auto req = std::make_shared<Request>(
|
||||
gen.addr(), gen.size(), flags, Request::funcRequestorId, 0,
|
||||
_tc->contextId());
|
||||
|
||||
if (!tryTLBs(req, BaseMMU::Write))
|
||||
return false;
|
||||
|
||||
PortProxy::memsetBlobPhys(
|
||||
req->getPaddr(), req->getFlags(), v, gen.size());
|
||||
}
|
||||
return true;
|
||||
constexpr auto mode = BaseMMU::Write;
|
||||
return tryOnBlob(mode, _tc->getMMUPtr()->translateFunctional(
|
||||
addr, size, _tc, mode, flags),
|
||||
[this, v](const auto &range) {
|
||||
PortProxy::memsetBlobPhys(range.paddr, flags, v, range.size);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gem5
|
||||
|
||||
@@ -41,7 +41,9 @@
|
||||
#ifndef __MEM_TRANSLATING_PORT_PROXY_HH__
|
||||
#define __MEM_TRANSLATING_PORT_PROXY_HH__
|
||||
|
||||
#include "arch/generic/tlb.hh"
|
||||
#include <functional>
|
||||
|
||||
#include "arch/generic/mmu.hh"
|
||||
#include "mem/port_proxy.hh"
|
||||
|
||||
namespace gem5
|
||||
@@ -57,24 +59,20 @@ class ThreadContext;
|
||||
*/
|
||||
class TranslatingPortProxy : public PortProxy
|
||||
{
|
||||
private:
|
||||
bool tryTLBsOnce(RequestPtr req, BaseMMU::Mode) const;
|
||||
bool tryTLBs(RequestPtr req, BaseMMU::Mode) const;
|
||||
|
||||
protected:
|
||||
ThreadContext* _tc;
|
||||
const Addr pageBytes;
|
||||
|
||||
Request::Flags flags;
|
||||
|
||||
virtual bool
|
||||
fixupAddr(Addr addr, BaseMMU::Mode mode) const
|
||||
fixupRange(const TranslationGen::Range &range, BaseMMU::Mode mode) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
bool tryOnBlob(BaseMMU::Mode mode, TranslationGenPtr gen,
|
||||
std::function<void(const TranslationGen::Range &)> func) const;
|
||||
|
||||
public:
|
||||
TranslatingPortProxy(ThreadContext *tc, Request::Flags _flags=0);
|
||||
|
||||
/** Version of tryReadblob that translates virt->phys and deals
|
||||
|
||||
Reference in New Issue
Block a user