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:
Gabe Black
2021-09-20 21:37:40 -07:00
parent 1f9fc43e72
commit 7155b8ba1e
4 changed files with 57 additions and 74 deletions

View File

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

View File

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

View File

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

View File

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