From 6f9d294e8685f49d91af48065736ac1d67e53718 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 22 Oct 2011 22:30:08 -0700 Subject: [PATCH] SE: move page allocation from PageTable to Process PageTable supported an allocate() call that called back through the Process to allocate memory, but did not have a method to map addresses without allocating new pages. It makes more sense for Process to do the allocation, so this method was renamed allocateMem() and moved to Process, and uses a new map() call on PageTable. The remaining uses of the process pointer in PageTable were only to get the name and the PID, so by passing these in directly in the constructor, we can make PageTable completely independent of Process. --- src/arch/alpha/process.cc | 2 +- src/arch/arm/linux/process.cc | 2 +- src/arch/arm/process.cc | 3 +-- src/arch/mips/process.cc | 2 +- src/arch/power/process.cc | 3 +-- src/arch/sparc/process.cc | 3 +-- src/arch/x86/process.cc | 9 ++++----- src/kern/tru64/tru64.hh | 4 ++-- src/mem/page_table.cc | 23 ++++++++++------------- src/mem/page_table.hh | 15 +++++++++------ src/mem/translating_port.cc | 8 ++++---- src/sim/process.cc | 14 +++++++++++--- src/sim/process.hh | 2 ++ src/sim/syscall_emul.cc | 3 +-- src/sim/syscall_emul.hh | 10 +++++----- src/sim/system.cc | 4 ++-- src/sim/system.hh | 4 +++- 17 files changed, 59 insertions(+), 52 deletions(-) diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 637fbe065..4a3079264 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -126,7 +126,7 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize) stack_min = roundDown(stack_min, pageSize); stack_size = stack_base - stack_min; // map memory - pTable->allocate(stack_min, roundUp(stack_size, pageSize)); + allocateMem(stack_min, roundUp(stack_size, pageSize)); // map out initial stack contents Addr argv_array_base = stack_min + intSize; // room for argc diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc index f17749252..c65962d00 100644 --- a/src/arch/arm/linux/process.cc +++ b/src/arch/arm/linux/process.cc @@ -503,7 +503,7 @@ void ArmLinuxProcess::initState() { ArmLiveProcess::initState(); - pTable->allocate(commPage, PageBytes); + allocateMem(commPage, PageBytes); ThreadContext *tc = system->getThreadContext(contextIds[0]); uint8_t swiNeg1[] = { diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index c3b02744e..aa5d7dfce 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -251,8 +251,7 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) stack_size = stack_base - stack_min; // map memory - pTable->allocate(roundDown(stack_min, pageSize), - roundUp(stack_size, pageSize)); + allocateMem(roundDown(stack_min, pageSize), roundUp(stack_size, pageSize)); // map out initial stack contents uint32_t sentry_base = stack_base - sentry_size; diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc index c62b60b98..5643ff18a 100644 --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -136,7 +136,7 @@ MipsLiveProcess::argsInit(int pageSize) stack_min = roundDown(stack_min, pageSize); stack_size = stack_base - stack_min; // map memory - pTable->allocate(stack_min, roundUp(stack_size, pageSize)); + allocateMem(stack_min, roundUp(stack_size, pageSize)); // map out initial stack contents IntType argv_array_base = stack_min + intSize; // room for argc diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc index d12e3eab6..788c7cc0c 100644 --- a/src/arch/power/process.cc +++ b/src/arch/power/process.cc @@ -187,8 +187,7 @@ PowerLiveProcess::argsInit(int intSize, int pageSize) stack_size = stack_base - stack_min; // map memory - pTable->allocate(roundDown(stack_min, pageSize), - roundUp(stack_size, pageSize)); + allocateMem(roundDown(stack_min, pageSize), roundUp(stack_size, pageSize)); // map out initial stack contents uint32_t sentry_base = stack_base - sentry_size; diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 3eee3d137..5c594dcbc 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -316,8 +316,7 @@ SparcLiveProcess::argsInit(int pageSize) stack_size = stack_base - stack_min; // Allocate space for the stack - pTable->allocate(roundDown(stack_min, pageSize), - roundUp(stack_size, pageSize)); + allocateMem(roundDown(stack_min, pageSize), roundUp(stack_size, pageSize)); // map out initial stack contents IntType sentry_base = stack_base - sentry_size; diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 79a140776..f5ba787c9 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -167,7 +167,7 @@ X86_64LiveProcess::initState() argsInit(sizeof(uint64_t), VMPageSize); // Set up the vsyscall page for this process. - pTable->allocate(vsyscallPage.base, vsyscallPage.size); + allocateMem(vsyscallPage.base, vsyscallPage.size); uint8_t vtimeBlob[] = { 0x48,0xc7,0xc0,0xc9,0x00,0x00,0x00, // mov $0xc9,%rax 0x0f,0x05, // syscall @@ -265,7 +265,7 @@ I386LiveProcess::initState() * Set up a GDT for this process. The whole GDT wouldn't really be for * this process, but the only parts we care about are. */ - pTable->allocate(_gdtStart, _gdtSize); + allocateMem(_gdtStart, _gdtSize); uint64_t zero = 0; assert(_gdtSize % sizeof(zero) == 0); for (Addr gdtCurrent = _gdtStart; @@ -274,7 +274,7 @@ I386LiveProcess::initState() } // Set up the vsyscall page for this process. - pTable->allocate(vsyscallPage.base, vsyscallPage.size); + allocateMem(vsyscallPage.base, vsyscallPage.size); uint8_t vsyscallBlob[] = { 0x51, // push %ecx 0x52, // push %edp @@ -577,8 +577,7 @@ X86LiveProcess::argsInit(int pageSize, stack_size = stack_base - stack_min; // map memory - pTable->allocate(roundDown(stack_min, pageSize), - roundUp(stack_size, pageSize)); + allocateMem(roundDown(stack_min, pageSize), roundUp(stack_size, pageSize)); // map out initial stack contents IntType sentry_base = stack_base - sentry_size; diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index 09cbb166d..4da4cfe53 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -564,7 +564,7 @@ class Tru64 : public OperatingSystem stack_base, stack_size); // map memory - process->pTable->allocate(rounded_stack_base, rounded_stack_size); + process->allocateMem(rounded_stack_base, rounded_stack_size); argp->address = gtoh(rounded_stack_base); argp.copyOut(tc->getMemPort()); @@ -683,7 +683,7 @@ class Tru64 : public OperatingSystem // Register this as a valid address range with the process base_addr = roundDown(base_addr, VMPageSize); int size = cur_addr - base_addr; - process->pTable->allocate(base_addr, roundUp(size, VMPageSize)); + process->allocateMem(base_addr, roundUp(size, VMPageSize)); config.copyOut(tc->getMemPort()); slot_state.copyOut(tc->getMemPort()); diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc index 745872319..7622c2d48 100644 --- a/src/mem/page_table.cc +++ b/src/mem/page_table.cc @@ -45,16 +45,14 @@ #include "debug/MMU.hh" #include "mem/page_table.hh" #include "sim/faults.hh" -#include "sim/process.hh" #include "sim/sim_object.hh" -#include "sim/system.hh" using namespace std; using namespace TheISA; -PageTable::PageTable(Process *_process, Addr _pageSize) +PageTable::PageTable(const std::string &__name, uint64_t _pid, Addr _pageSize) : pageSize(_pageSize), offsetMask(mask(floorLog2(_pageSize))), - process(_process) + pid(_pid), _name(__name) { assert(isPowerOf2(pageSize)); pTableCache[0].vaddr = 0; @@ -67,21 +65,20 @@ PageTable::~PageTable() } void -PageTable::allocate(Addr vaddr, int64_t size, bool clobber) +PageTable::map(Addr vaddr, Addr paddr, int64_t size, bool clobber) { // starting address must be page aligned assert(pageOffset(vaddr) == 0); DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr+ size); - for (; size > 0; size -= pageSize, vaddr += pageSize) { + for (; size > 0; size -= pageSize, vaddr += pageSize, paddr += pageSize) { if (!clobber && (pTable.find(vaddr) != pTable.end())) { // already mapped fatal("PageTable::allocate: address 0x%x already mapped", vaddr); } - pTable[vaddr] = TheISA::TlbEntry(process->M5_pid, vaddr, - process->system->new_page()); + pTable[vaddr] = TheISA::TlbEntry(pid, vaddr, paddr); updateCache(vaddr, pTable[vaddr]); } } @@ -108,11 +105,11 @@ PageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr) } void -PageTable::deallocate(Addr vaddr, int64_t size) +PageTable::unmap(Addr vaddr, int64_t size) { assert(pageOffset(vaddr) == 0); - DPRINTF(MMU, "Deallocating page: %#x-%#x\n", vaddr, vaddr+ size); + DPRINTF(MMU, "Unmapping page: %#x-%#x\n", vaddr, vaddr+ size); for (; size > 0; size -= pageSize, vaddr += pageSize) { PTableItr iter = pTable.find(vaddr); @@ -208,7 +205,7 @@ PageTable::serialize(std::ostream &os) PTableItr iter = pTable.begin(); PTableItr end = pTable.end(); while (iter != end) { - os << "\n[" << csprintf("%s.Entry%d", process->name(), count) << "]\n"; + os << "\n[" << csprintf("%s.Entry%d", name(), count) << "]\n"; paramOut(os, "vaddr", iter->first); iter->second.serialize(os); @@ -230,9 +227,9 @@ PageTable::unserialize(Checkpoint *cp, const std::string §ion) pTable.clear(); while(i < count) { - paramIn(cp, csprintf("%s.Entry%d", process->name(), i), "vaddr", vaddr); + paramIn(cp, csprintf("%s.Entry%d", name(), i), "vaddr", vaddr); entry = new TheISA::TlbEntry(); - entry->unserialize(cp, csprintf("%s.Entry%d", process->name(), i)); + entry->unserialize(cp, csprintf("%s.Entry%d", name(), i)); pTable[vaddr] = *entry; ++i; } diff --git a/src/mem/page_table.hh b/src/mem/page_table.hh index d60f4a433..b1b5227be 100644 --- a/src/mem/page_table.hh +++ b/src/mem/page_table.hh @@ -46,8 +46,6 @@ #include "mem/request.hh" #include "sim/serialize.hh" -class Process; - /** * Page Table Declaration. */ @@ -68,20 +66,25 @@ class PageTable const Addr pageSize; const Addr offsetMask; - Process *process; + const uint64_t pid; + const std::string _name; public: - PageTable(Process *_process, Addr _pageSize = TheISA::VMPageSize); + PageTable(const std::string &__name, uint64_t _pid, + Addr _pageSize = TheISA::VMPageSize); ~PageTable(); + // for DPRINTF compatibility + const std::string name() const { return _name; } + Addr pageAlign(Addr a) { return (a & ~offsetMask); } Addr pageOffset(Addr a) { return (a & offsetMask); } - void allocate(Addr vaddr, int64_t size, bool clobber = false); + void map(Addr vaddr, Addr paddr, int64_t size, bool clobber = false); void remap(Addr vaddr, int64_t size, Addr new_vaddr); - void deallocate(Addr vaddr, int64_t size); + void unmap(Addr vaddr, int64_t size); /** * Check if any pages in a region are already allocated diff --git a/src/mem/translating_port.cc b/src/mem/translating_port.cc index 80c68c6bd..3ea728349 100644 --- a/src/mem/translating_port.cc +++ b/src/mem/translating_port.cc @@ -86,8 +86,8 @@ TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size) if (!pTable->translate(gen.addr(), paddr)) { if (allocating == Always) { - pTable->allocate(roundDown(gen.addr(), VMPageSize), - VMPageSize); + process->allocateMem(roundDown(gen.addr(), VMPageSize), + VMPageSize); } else if (allocating == NextPage) { // check if we've accessed the next page on the stack if (!process->fixupStackFault(gen.addr())) @@ -123,8 +123,8 @@ TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size) if (!pTable->translate(gen.addr(), paddr)) { if (allocating == Always) { - pTable->allocate(roundDown(gen.addr(), VMPageSize), - VMPageSize); + process->allocateMem(roundDown(gen.addr(), VMPageSize), + VMPageSize); pTable->translate(gen.addr(), paddr); } else { return false; diff --git a/src/sim/process.cc b/src/sim/process.cc index 62b9b7002..ba106fb63 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -169,7 +169,7 @@ Process::Process(ProcessParams * params) mmap_start = mmap_end = 0; nxm_start = nxm_end = 0; - pTable = new PageTable(this); + pTable = new PageTable(name(), M5_pid); // other parameters will be initialized when the program is loaded } @@ -328,13 +328,21 @@ Process::sim_fd_obj(int tgt_fd) return &fd_map[tgt_fd]; } +void +Process::allocateMem(Addr vaddr, int64_t size, bool clobber) +{ + int npages = divCeil(size, (int64_t)VMPageSize); + Addr paddr = system->allocPhysPages(npages); + pTable->map(vaddr, paddr, size, clobber); +} + bool Process::fixupStackFault(Addr vaddr) { // Check if this is already on the stack and there's just no page there // yet. if (vaddr >= stack_min && vaddr < stack_base) { - pTable->allocate(roundDown(vaddr, VMPageSize), VMPageSize); + allocateMem(roundDown(vaddr, VMPageSize), VMPageSize); return true; } @@ -347,7 +355,7 @@ Process::fixupStackFault(Addr vaddr) fatal("Maximum stack size exceeded\n"); if (stack_base - stack_min > 8 * 1024 * 1024) fatal("Over max stack size for one thread\n"); - pTable->allocate(stack_min, TheISA::PageBytes); + allocateMem(stack_min, TheISA::PageBytes); inform("Increasing stack size by one page."); }; return true; diff --git a/src/sim/process.hh b/src/sim/process.hh index d48b1b463..4c31597b4 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -212,6 +212,8 @@ class Process : public SimObject virtual void syscall(int64_t callnum, ThreadContext *tc) = 0; + void allocateMem(Addr vaddr, int64_t size, bool clobber = false); + /// Attempt to fix up a fault at vaddr by allocating a page on the stack. /// @return Whether the fault has been fixed. bool fixupStackFault(Addr vaddr); diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 6873d4aa4..203eaff2a 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -166,8 +166,7 @@ brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point, VMPageSize); !gen.done(); gen.next()) { if (!p->pTable->translate(gen.addr())) - p->pTable->allocate(roundDown(gen.addr(), VMPageSize), - VMPageSize); + p->allocateMem(roundDown(gen.addr(), VMPageSize), VMPageSize); // if the address is already there, zero it out else { diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 9bcf58844..50bf1a52f 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -677,7 +677,7 @@ mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext * if (new_length > old_length) { if ((start + old_length) == process->mmap_end) { uint64_t diff = new_length - old_length; - process->pTable->allocate(process->mmap_end, diff); + process->allocateMem(process->mmap_end, diff); process->mmap_end += diff; return start; } else { @@ -691,15 +691,15 @@ mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext * process->mmap_end, process->mmap_end + new_length, new_length); start = process->mmap_end; // add on the remaining unallocated pages - process->pTable->allocate(start + old_length, new_length - old_length); + process->allocateMem(start + old_length, + new_length - old_length); process->mmap_end += new_length; warn("returning %08p as start\n", start); return start; } } } else { - process->pTable->deallocate(start + new_length, old_length - - new_length); + process->pTable->unmap(start + new_length, old_length - new_length); return start; } } @@ -1065,7 +1065,7 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) } } - p->pTable->allocate(start, length, clobber); + p->allocateMem(start, length, clobber); return start; } diff --git a/src/sim/system.cc b/src/sim/system.cc index 81a8a0574..c58830c10 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -275,10 +275,10 @@ System::replaceThreadContext(ThreadContext *tc, int context_id) #if !FULL_SYSTEM Addr -System::new_page() +System::allocPhysPages(int npages) { Addr return_addr = pagePtr << LogVMPageSize; - ++pagePtr; + pagePtr += npages; if (return_addr >= physmem->size()) fatal("Out of memory, please increase size of physical memory."); return return_addr; diff --git a/src/sim/system.hh b/src/sim/system.hh index a6bc47fc0..ed5193dfd 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -287,7 +287,9 @@ class System : public SimObject #else - Addr new_page(); + /// Allocate npages contiguous unused physical pages + /// @return Starting address of first page + Addr allocPhysPages(int npages); #endif // FULL_SYSTEM