X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Fpage_table.cc;h=d3af09e1e5ede68010f53889b0bd6614c7fc07e5;hb=f49830ce0ba79c54c65c9c4b25bc3c6184aaf2a9;hp=a34a0393ac50c9d055f6a865e2026acb9e61789b;hpb=44974a4462e019cfc5c65d20ad620faa9bc7f8cf;p=gem5.git diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc index a34a0393a..d3af09e1e 100644 --- a/src/mem/page_table.cc +++ b/src/mem/page_table.cc @@ -1,4 +1,5 @@ /* + * Copyright (c) 2014 Advanced Micro Devices, Inc. * Copyright (c) 2003 The Regents of The University of Michigan * All rights reserved. * @@ -27,135 +28,212 @@ * * Authors: Steve Reinhardt * Ron Dreslinski + * Ali Saidi */ /** * @file - * Definitions of page table. + * Definitions of functional page table. */ -#include -#include #include +#include +#include -#include "arch/faults.hh" #include "base/bitfield.hh" #include "base/intmath.hh" #include "base/trace.hh" +#include "config/the_isa.hh" +#include "debug/MMU.hh" #include "mem/page_table.hh" -#include "sim/builder.hh" +#include "sim/faults.hh" #include "sim/sim_object.hh" -#include "sim/system.hh" using namespace std; using namespace TheISA; -PageTable::PageTable(System *_system, Addr _pageSize) - : pageSize(_pageSize), offsetMask(mask(floorLog2(_pageSize))), - system(_system) +FuncPageTable::FuncPageTable(const std::string &__name, + uint64_t _pid, Addr _pageSize) + : PageTableBase(__name, _pid, _pageSize) { - assert(isPowerOf2(pageSize)); - pTableCache[0].vaddr = 0; - pTableCache[1].vaddr = 0; - pTableCache[2].vaddr = 0; } -PageTable::~PageTable() +FuncPageTable::~FuncPageTable() { } -Fault -PageTable::page_check(Addr addr, int size) const +void +FuncPageTable::map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags) { - if (size < sizeof(uint64_t)) { - if (!isPowerOf2(size)) { - panic("Invalid request size!\n"); - return genMachineCheckFault(); - } + bool clobber = flags & Clobber; + // starting address must be page aligned + assert(pageOffset(vaddr) == 0); - if ((size - 1) & addr) - return genAlignmentFault(); - } - else { - if ((addr & (VMPageSize - 1)) + size > VMPageSize) { - panic("Invalid request size!\n"); - return genMachineCheckFault(); + DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr+ size); + + for (; size > 0; size -= pageSize, vaddr += pageSize, paddr += pageSize) { + if (!clobber && (pTable.find(vaddr) != pTable.end())) { + // already mapped + fatal("FuncPageTable::allocate: addr 0x%x already mapped", vaddr); } - if ((sizeof(uint64_t) - 1) & addr) - return genAlignmentFault(); + pTable[vaddr] = TheISA::TlbEntry(pid, vaddr, paddr, + flags & Uncacheable, + flags & ReadOnly); + eraseCacheEntry(vaddr); + updateCache(vaddr, pTable[vaddr]); } - - return NoFault; } +void +FuncPageTable::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) + { + assert(pTable.find(vaddr) != pTable.end()); + pTable[new_vaddr] = pTable[vaddr]; + pTable.erase(vaddr); + eraseCacheEntry(vaddr); + pTable[new_vaddr].updateVaddr(new_vaddr); + updateCache(new_vaddr, pTable[new_vaddr]); + } +} void -PageTable::allocate(Addr vaddr, int size) +FuncPageTable::unmap(Addr vaddr, int64_t size) { - // starting address must be page aligned assert(pageOffset(vaddr) == 0); - for (; size > 0; size -= pageSize, vaddr += pageSize) { - m5::hash_map::iterator iter = pTable.find(vaddr); - - if (iter != pTable.end()) { - // already mapped - fatal("PageTable::allocate: address 0x%x already mapped", vaddr); - } + DPRINTF(MMU, "Unmapping page: %#x-%#x\n", vaddr, vaddr+ size); - pTable[vaddr] = system->new_page(); - pTableCache[2].paddr = pTableCache[1].paddr; - pTableCache[2].vaddr = pTableCache[1].vaddr; - pTableCache[1].paddr = pTableCache[0].paddr; - pTableCache[1].vaddr = pTableCache[0].vaddr; - pTableCache[0].paddr = pTable[vaddr]; - pTableCache[0].vaddr = vaddr; + for (; size > 0; size -= pageSize, vaddr += pageSize) { + assert(pTable.find(vaddr) != pTable.end()); + pTable.erase(vaddr); + eraseCacheEntry(vaddr); } + } +bool +FuncPageTable::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()) { + return false; + } + } + + return true; +} bool -PageTable::translate(Addr vaddr, Addr &paddr) +FuncPageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry) { Addr page_addr = pageAlign(vaddr); - paddr = 0; - if (pTableCache[0].vaddr == vaddr) { - paddr = pTableCache[0].paddr; + if (pTableCache[0].valid && pTableCache[0].vaddr == page_addr) { + entry = pTableCache[0].entry; return true; } - if (pTableCache[1].vaddr == vaddr) { - paddr = pTableCache[1].paddr; + if (pTableCache[1].valid && pTableCache[1].vaddr == page_addr) { + entry = pTableCache[1].entry; return true; } - if (pTableCache[2].vaddr == vaddr) { - paddr = pTableCache[2].paddr; + if (pTableCache[2].valid && pTableCache[2].vaddr == page_addr) { + entry = pTableCache[2].entry; return true; } - m5::hash_map::iterator iter = pTable.find(page_addr); + PTableItr iter = pTable.find(page_addr); if (iter == pTable.end()) { return false; } - paddr = iter->second + pageOffset(vaddr); + updateCache(page_addr, iter->second); + entry = iter->second; return true; } +bool +PageTableBase::translate(Addr vaddr, Addr &paddr) +{ + TheISA::TlbEntry entry; + if (!lookup(vaddr, entry)) { + DPRINTF(MMU, "Couldn't Translate: %#x\n", vaddr); + return false; + } + paddr = pageOffset(vaddr) + entry.pageStart(); + DPRINTF(MMU, "Translating: %#x->%#x\n", vaddr, paddr); + return true; +} Fault -PageTable::translate(RequestPtr &req) +PageTableBase::translate(RequestPtr req) { Addr paddr; assert(pageAlign(req->getVaddr() + req->getSize() - 1) == pageAlign(req->getVaddr())); if (!translate(req->getVaddr(), paddr)) { - return genPageTableFault(req->getVaddr()); + return Fault(new GenericPageTableFault(req->getVaddr())); } req->setPaddr(paddr); - return page_check(req->getPaddr(), req->getSize()); + if ((paddr & (pageSize - 1)) + req->getSize() > pageSize) { + panic("Request spans page boundaries!\n"); + return NoFault; + } + return NoFault; } + +void +FuncPageTable::serialize(std::ostream &os) +{ + paramOut(os, "ptable.size", pTable.size()); + + PTable::size_type count = 0; + + PTableItr iter = pTable.begin(); + PTableItr end = pTable.end(); + while (iter != end) { + os << "\n[" << csprintf("%s.Entry%d", name(), count) << "]\n"; + + paramOut(os, "vaddr", iter->first); + iter->second.serialize(os); + + ++iter; + ++count; + } + assert(count == pTable.size()); +} + +void +FuncPageTable::unserialize(Checkpoint *cp, const std::string §ion) +{ + int i = 0, count; + paramIn(cp, section, "ptable.size", count); + + pTable.clear(); + + while (i < count) { + TheISA::TlbEntry *entry; + Addr vaddr; + + paramIn(cp, csprintf("%s.Entry%d", name(), i), "vaddr", vaddr); + entry = new TheISA::TlbEntry(); + entry->unserialize(cp, csprintf("%s.Entry%d", name(), i)); + pTable[vaddr] = *entry; + delete entry; + ++i; + } +} +