using namespace std;
AlphaProcess::AlphaProcess(ProcessParams *params, ObjectFile *objFile)
- : Process(params, new FuncPageTable(params->name, params->pid, PageBytes),
+ : Process(params,
+ new EmulationPageTable(params->name, params->pid, PageBytes),
objFile)
{
fatal_if(params->useArchPT, "Arch page tables not implemented.");
ArmProcess::ArmProcess(ProcessParams *params, ObjectFile *objFile,
ObjectFile::Arch _arch)
- : Process(params, new FuncPageTable(params->name, params->pid, PageBytes),
+ : Process(params,
+ new EmulationPageTable(params->name, params->pid, PageBytes),
objFile),
- arch(_arch)
+ arch(_arch)
{
fatal_if(params->useArchPT, "Arch page tables not implemented.");
}
using namespace MipsISA;
MipsProcess::MipsProcess(ProcessParams *params, ObjectFile *objFile)
- : Process(params, new FuncPageTable(params->name, params->pid, PageBytes),
+ : Process(params,
+ new EmulationPageTable(params->name, params->pid, PageBytes),
objFile)
{
fatal_if(params->useArchPT, "Arch page tables not implemented.");
using namespace PowerISA;
PowerProcess::PowerProcess(ProcessParams *params, ObjectFile *objFile)
- : Process(params, new FuncPageTable(params->name, params->pid, PageBytes),
+ : Process(params,
+ new EmulationPageTable(params->name, params->pid, PageBytes),
objFile)
{
fatal_if(params->useArchPT, "Arch page tables not implemented.");
using namespace RiscvISA;
RiscvProcess::RiscvProcess(ProcessParams *params, ObjectFile *objFile) :
- Process(params, new FuncPageTable(params->name, params->pid,
- PageBytes),
+ Process(params,
+ new EmulationPageTable(params->name, params->pid, PageBytes),
objFile)
{
fatal_if(params->useArchPT, "Arch page tables not implemented.");
SparcProcess::SparcProcess(ProcessParams *params, ObjectFile *objFile,
Addr _StackBias)
- : Process(params, new FuncPageTable(params->name, params->pid, PageBytes),
+ : Process(params,
+ new EmulationPageTable(params->name, params->pid, PageBytes),
objFile),
StackBias(_StackBias)
{
X86Process::X86Process(ProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs)
: Process(params, params->useArchPT ?
- static_cast<PageTableBase *>(
+ static_cast<EmulationPageTable *>(
new ArchPageTable(params->name, params->pid,
params->system, PageBytes)) :
- static_cast<PageTableBase *>(
- new FuncPageTable(params->name, params->pid,
- PageBytes)),
+ new EmulationPageTable(params->name, params->pid,
+ PageBytes),
objFile),
syscallDescs(_syscallDescs), numSyscallDescs(_numSyscallDescs)
{
* @see MultiLevelPageTable
*/
template <class ISAOps>
-class MultiLevelPageTable : public FuncPageTable
+class MultiLevelPageTable : public EmulationPageTable
{
/**
* ISA specific operations
MultiLevelPageTable<ISAOps>::MultiLevelPageTable(const std::string &__name,
uint64_t _pid, System *_sys,
Addr pageSize)
- : FuncPageTable(__name, _pid, pageSize), system(_sys),
+ : EmulationPageTable(__name, _pid, pageSize), system(_sys),
logLevelSize(PageTableLayout),
numLevels(logLevelSize.size())
{
MultiLevelPageTable<ISAOps>::map(Addr vaddr, Addr paddr,
int64_t size, uint64_t flags)
{
- FuncPageTable::map(vaddr, paddr, size, flags);
+ EmulationPageTable::map(vaddr, paddr, size, flags);
PortProxy &p = system->physProxy;
void
MultiLevelPageTable<ISAOps>::remap(Addr vaddr, int64_t size, Addr new_vaddr)
{
- FuncPageTable::remap(vaddr, size, new_vaddr);
+ EmulationPageTable::remap(vaddr, size, new_vaddr);
PortProxy &p = system->physProxy;
void
MultiLevelPageTable<ISAOps>::unmap(Addr vaddr, int64_t size)
{
- FuncPageTable::unmap(vaddr, size);
+ EmulationPageTable::unmap(vaddr, size);
PortProxy &p = system->physProxy;
void
MultiLevelPageTable<ISAOps>::serialize(CheckpointOut &cp) const
{
- FuncPageTable::serialize(cp);
+ EmulationPageTable::serialize(cp);
/** Since, the page table is stored in system memory
* which is serialized separately, we will serialize
* just the base pointer
void
MultiLevelPageTable<ISAOps>::unserialize(CheckpointIn &cp)
{
- FuncPageTable::unserialize(cp);
+ EmulationPageTable::unserialize(cp);
paramIn(cp, "ptable.pointer", basePtr);
}
using namespace std;
using namespace TheISA;
-FuncPageTable::FuncPageTable(const std::string &__name,
- uint64_t _pid, Addr _pageSize)
- : PageTableBase(__name, _pid, _pageSize)
-{
-}
-
-FuncPageTable::~FuncPageTable()
+EmulationPageTable::~EmulationPageTable()
{
for (auto &iter : pTable)
delete iter.second;
}
void
-FuncPageTable::map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags)
+EmulationPageTable::map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags)
{
bool clobber = flags & Clobber;
// starting address must be page aligned
assert(pageOffset(vaddr) == 0);
- DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr+ size);
+ DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr + size);
- for (; size > 0; size -= pageSize, vaddr += pageSize, paddr += pageSize) {
+ while (size > 0) {
auto it = pTable.find(vaddr);
if (it != pTable.end()) {
if (clobber) {
delete it->second;
} else {
// already mapped
- fatal("FuncPageTable::allocate: addr %#x already mapped",
+ fatal("EmulationPageTable::allocate: addr %#x already mapped",
vaddr);
}
} else {
it->second = new TheISA::TlbEntry(pid, vaddr, paddr,
flags & Uncacheable,
flags & ReadOnly);
- eraseCacheEntry(vaddr);
- updateCache(vaddr, pTable[vaddr]);
+ size -= pageSize;
+ vaddr += pageSize;
+ paddr += pageSize;
}
}
void
-FuncPageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr)
+EmulationPageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr)
{
assert(pageOffset(vaddr) == 0);
assert(pageOffset(new_vaddr) == 0);
DPRINTF(MMU, "moving pages from vaddr %08p to %08p, size = %d\n", vaddr,
new_vaddr, size);
- for (; size > 0;
- size -= pageSize, vaddr += pageSize, new_vaddr += pageSize)
- {
+ while (size > 0) {
auto new_it = pTable.find(new_vaddr);
auto old_it = pTable.find(vaddr);
assert(old_it != pTable.end() && new_it == pTable.end());
new_it->second = old_it->second;
pTable.erase(old_it);
- eraseCacheEntry(vaddr);
new_it->second->updateVaddr(new_vaddr);
- updateCache(new_vaddr, new_it->second);
+ size -= pageSize;
+ vaddr += pageSize;
+ new_vaddr += pageSize;
}
}
void
-FuncPageTable::getMappings(std::vector<std::pair<Addr, Addr>> *addr_maps)
+EmulationPageTable::getMappings(std::vector<std::pair<Addr, Addr>> *addr_maps)
{
for (auto &iter : pTable)
addr_maps->push_back(make_pair(iter.first, iter.second->pageStart()));
}
void
-FuncPageTable::unmap(Addr vaddr, int64_t size)
+EmulationPageTable::unmap(Addr vaddr, int64_t size)
{
assert(pageOffset(vaddr) == 0);
DPRINTF(MMU, "Unmapping page: %#x-%#x\n", vaddr, vaddr+ size);
- for (; size > 0; size -= pageSize, vaddr += pageSize) {
+ while (size > 0) {
auto it = pTable.find(vaddr);
assert(it != pTable.end());
- eraseCacheEntry(vaddr);
delete it->second;
pTable.erase(it);
+ size -= pageSize;
+ vaddr += pageSize;
}
-
}
bool
-FuncPageTable::isUnmapped(Addr vaddr, int64_t size)
+EmulationPageTable::isUnmapped(Addr vaddr, int64_t size)
{
// starting address must be page aligned
assert(pageOffset(vaddr) == 0);
- for (; size > 0; size -= pageSize, vaddr += pageSize) {
- if (pTable.find(vaddr) != pTable.end()) {
+ for (int64_t offset = 0; offset < size; offset += pageSize)
+ if (pTable.find(vaddr + offset) != pTable.end())
return false;
- }
- }
return true;
}
bool
-FuncPageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry)
+EmulationPageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry)
{
Addr page_addr = pageAlign(vaddr);
- if (pTableCache[0].entry && pTableCache[0].vaddr == page_addr) {
- entry = *pTableCache[0].entry;
- return true;
- }
- if (pTableCache[1].entry && pTableCache[1].vaddr == page_addr) {
- entry = *pTableCache[1].entry;
- return true;
- }
- if (pTableCache[2].entry && pTableCache[2].vaddr == page_addr) {
- entry = *pTableCache[2].entry;
- return true;
- }
-
PTableItr iter = pTable.find(page_addr);
- if (iter == pTable.end()) {
+ if (iter == pTable.end())
return false;
- }
- updateCache(page_addr, iter->second);
entry = *iter->second;
return true;
}
bool
-PageTableBase::translate(Addr vaddr, Addr &paddr)
+EmulationPageTable::translate(Addr vaddr, Addr &paddr)
{
TheISA::TlbEntry entry;
if (!lookup(vaddr, entry)) {
}
Fault
-PageTableBase::translate(RequestPtr req)
+EmulationPageTable::translate(RequestPtr req)
{
Addr paddr;
- assert(pageAlign(req->getVaddr() + req->getSize() - 1)
- == pageAlign(req->getVaddr()));
- if (!translate(req->getVaddr(), paddr)) {
+ assert(pageAlign(req->getVaddr() + req->getSize() - 1) ==
+ pageAlign(req->getVaddr()));
+ if (!translate(req->getVaddr(), paddr))
return Fault(new GenericPageTableFault(req->getVaddr()));
- }
req->setPaddr(paddr);
if ((paddr & (pageSize - 1)) + req->getSize() > pageSize) {
panic("Request spans page boundaries!\n");
}
void
-FuncPageTable::serialize(CheckpointOut &cp) const
+EmulationPageTable::serialize(CheckpointOut &cp) const
{
paramOut(cp, "ptable.size", pTable.size());
}
void
-FuncPageTable::unserialize(CheckpointIn &cp)
+EmulationPageTable::unserialize(CheckpointIn &cp)
{
int count;
paramIn(cp, "ptable.size", count);
#include "sim/serialize.hh"
class ThreadContext;
-class System;
-/**
- * Declaration of base class for page table
- */
-class PageTableBase : public Serializable
+class EmulationPageTable : public Serializable
{
protected:
- struct cacheElement {
- Addr vaddr;
- TheISA::TlbEntry *entry;
- };
-
- struct cacheElement pTableCache[3];
+ typedef std::unordered_map<Addr, TheISA::TlbEntry *> PTable;
+ typedef PTable::iterator PTableItr;
+ PTable pTable;
const Addr pageSize;
const Addr offsetMask;
public:
- PageTableBase(const std::string &__name, uint64_t _pid, Addr _pageSize)
- : pageSize(_pageSize), offsetMask(mask(floorLog2(_pageSize))),
- pid(_pid), _name(__name)
+ EmulationPageTable(
+ const std::string &__name, uint64_t _pid, Addr _pageSize) :
+ pageSize(_pageSize), offsetMask(mask(floorLog2(_pageSize))),
+ pid(_pid), _name(__name)
{
assert(isPowerOf2(pageSize));
- pTableCache[0].entry = nullptr;
- pTableCache[1].entry = nullptr;
- pTableCache[2].entry = nullptr;
}
- virtual ~PageTableBase() {};
+ virtual ~EmulationPageTable();
/* generic page table mapping flags
* unset | set
ReadOnly = 8,
};
- virtual void initState(ThreadContext* tc) = 0;
+ virtual void initState(ThreadContext* tc) {};
// for DPRINTF compatibility
const std::string name() const { return _name; }
* @param flags Generic mapping flags that can be set by or-ing values
* from MappingFlags enum.
*/
- virtual void map(Addr vaddr, Addr paddr, int64_t size,
- uint64_t flags = 0) = 0;
- virtual void remap(Addr vaddr, int64_t size, Addr new_vaddr) = 0;
- virtual void unmap(Addr vaddr, int64_t size) = 0;
+ virtual void map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags = 0);
+ virtual void remap(Addr vaddr, int64_t size, Addr new_vaddr);
+ virtual void unmap(Addr vaddr, int64_t size);
/**
* Check if any pages in a region are already allocated
* @param size The length of the region.
* @return True if no pages in the region are mapped.
*/
- virtual bool isUnmapped(Addr vaddr, int64_t size) = 0;
+ virtual bool isUnmapped(Addr vaddr, int64_t size);
/**
* Lookup function
* @param vaddr The virtual address.
* @return entry The page table entry corresponding to vaddr.
*/
- virtual bool lookup(Addr vaddr, TheISA::TlbEntry &entry) = 0;
+ virtual bool lookup(Addr vaddr, TheISA::TlbEntry &entry);
/**
* Translate function
*/
Fault translate(RequestPtr req);
- /**
- * Update the page table cache.
- * @param vaddr virtual address (page aligned) to check
- * @param pte page table entry to return
- * @return A pointer to any entry which is displaced from the cache.
- */
- TheISA::TlbEntry *
- updateCache(Addr vaddr, TheISA::TlbEntry *entry)
- {
- TheISA::TlbEntry *evicted = pTableCache[2].entry;
-
- pTableCache[2].entry = pTableCache[1].entry;
- pTableCache[2].vaddr = pTableCache[1].vaddr;
-
- pTableCache[1].entry = pTableCache[0].entry;
- pTableCache[1].vaddr = pTableCache[0].vaddr;
-
- pTableCache[0].entry = entry;
- pTableCache[0].vaddr = vaddr;
-
- return evicted;
- }
-
- /**
- * Erase an entry from the page table cache.
- * @param vaddr virtual address (page aligned) to check
- * @return A pointer to the entry (if any) which is kicked out.
- */
- TheISA::TlbEntry *
- eraseCacheEntry(Addr vaddr)
- {
- TheISA::TlbEntry *evicted = nullptr;
- // Invalidate cached entries if necessary
- if (pTableCache[0].entry && pTableCache[0].vaddr == vaddr) {
- evicted = pTableCache[0].entry;
- pTableCache[0].entry = nullptr;
- } else if (pTableCache[1].entry && pTableCache[1].vaddr == vaddr) {
- evicted = pTableCache[1].entry;
- pTableCache[1].entry = nullptr;
- } else if (pTableCache[2].entry && pTableCache[2].vaddr == vaddr) {
- evicted = pTableCache[2].entry;
- pTableCache[2].entry = nullptr;
- }
- return evicted;
- }
-
- virtual void getMappings(std::vector<std::pair<Addr, Addr>>
- *addr_mappings) {};
-};
-
-/**
- * Declaration of functional page table.
- */
-class FuncPageTable : public PageTableBase
-{
- private:
- typedef std::unordered_map<Addr, TheISA::TlbEntry *> PTable;
- typedef PTable::iterator PTableItr;
- PTable pTable;
-
- public:
-
- FuncPageTable(const std::string &__name, uint64_t _pid, Addr _pageSize);
-
- ~FuncPageTable();
-
- void initState(ThreadContext* tc) override
- {
- }
-
- void map(Addr vaddr, Addr paddr, int64_t size,
- uint64_t flags = 0) override;
- void remap(Addr vaddr, int64_t size, Addr new_vaddr) override;
- void unmap(Addr vaddr, int64_t size) override;
-
- /**
- * Check if any pages in a region are already allocated
- * @param vaddr The starting virtual address of the region.
- * @param size The length of the region.
- * @return True if no pages in the region are mapped.
- */
- bool isUnmapped(Addr vaddr, int64_t size) override;
-
- /**
- * Lookup function
- * @param vaddr The virtual address.
- * @return entry The page table entry corresponding to vaddr.
- */
- bool lookup(Addr vaddr, TheISA::TlbEntry &entry) override;
+ void getMappings(std::vector<std::pair<Addr, Addr>> *addr_mappings);
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
-
- void getMappings(std::vector<std::pair<Addr, Addr>> *addr_maps) override;
};
#endif // __MEM_PAGE_TABLE_HH__
#include "mem/port_proxy.hh"
-class PageTableBase;
+class EmulationPageTable;
class Process;
/**
};
private:
- PageTableBase *pTable;
+ EmulationPageTable *pTable;
Process *process;
AllocType allocating;
SETranslatingPortProxy(MasterPort& port, Process* p, AllocType alloc);
virtual ~SETranslatingPortProxy();
- void setPageTable(PageTableBase *p) { pTable = p; }
+ void setPageTable(EmulationPageTable *p) { pTable = p; }
void setProcess(Process *p) { process = p; }
bool tryReadBlob(Addr addr, uint8_t *p, int size) const;
bool tryWriteBlob(Addr addr, const uint8_t *p, int size) const;
using namespace std;
using namespace TheISA;
-Process::Process(ProcessParams *params, PageTableBase *pTable,
+Process::Process(ProcessParams *params, EmulationPageTable *pTable,
ObjectFile *obj_file)
: SimObject(params), system(params->system),
useArchPT(params->useArchPT),
int npages = divCeil(size, (int64_t)PageBytes);
Addr paddr = system->allocPhysPages(npages);
pTable->map(vaddr, paddr, size,
- clobber ? PageTableBase::Clobber : PageTableBase::Zero);
+ clobber ? EmulationPageTable::Clobber :
+ EmulationPageTable::Zero);
}
void
Process::map(Addr vaddr, Addr paddr, int size, bool cacheable)
{
pTable->map(vaddr, paddr, size,
- cacheable ? PageTableBase::Zero : PageTableBase::Uncacheable);
+ cacheable ? EmulationPageTable::Zero :
+ EmulationPageTable::Uncacheable);
return true;
}
class EmulatedDriver;
class ObjectFile;
-class PageTableBase;
+class EmulationPageTable;
class SyscallDesc;
class SyscallReturn;
class System;
class Process : public SimObject
{
public:
- Process(ProcessParams *params, PageTableBase *pTable,
+ Process(ProcessParams *params, EmulationPageTable *pTable,
ObjectFile *obj_file);
void serialize(CheckpointOut &cp) const override;
bool useArchPT; // flag for using architecture specific page table
bool kvmInSE; // running KVM requires special initialization
- PageTableBase* pTable;
+ EmulationPageTable *pTable;
SETranslatingPortProxy initVirtMem; // memory proxy for initial image load