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.
This commit is contained in:
parent
4d5f2c28a8
commit
6f9d294e86
17 changed files with 59 additions and 52 deletions
|
@ -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
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -86,7 +86,7 @@ TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size)
|
|||
|
||||
if (!pTable->translate(gen.addr(), paddr)) {
|
||||
if (allocating == Always) {
|
||||
pTable->allocate(roundDown(gen.addr(), VMPageSize),
|
||||
process->allocateMem(roundDown(gen.addr(), VMPageSize),
|
||||
VMPageSize);
|
||||
} else if (allocating == NextPage) {
|
||||
// check if we've accessed the next page on the stack
|
||||
|
@ -123,7 +123,7 @@ TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size)
|
|||
|
||||
if (!pTable->translate(gen.addr(), paddr)) {
|
||||
if (allocating == Always) {
|
||||
pTable->allocate(roundDown(gen.addr(), VMPageSize),
|
||||
process->allocateMem(roundDown(gen.addr(), VMPageSize),
|
||||
VMPageSize);
|
||||
pTable->translate(gen.addr(), paddr);
|
||||
} else {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue