sim-se: Switch to new MemState API

Switch over to the new MemState API by specifying memory regions for
stack in each ISA, changing brkFunc to use MemState for heap memory,
and calling the MemState fixup in fixupStackFault (renamed to just
fixupFault).

Change-Id: Ie3559a68ce476daedf1a3f28b168a8fbc7face5e
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/25366
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Matthew Poremba
2020-03-17 15:47:44 -05:00
parent 56ee199b3d
commit 5c2fb0c652
18 changed files with 32 additions and 80 deletions

View File

@@ -371,8 +371,8 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex)
memState->setStackSize(memState->getStackBase() - memState->getStackMin());
// map memory
allocateMem(roundDown(memState->getStackMin(), pageSize),
roundUp(memState->getStackSize(), pageSize));
memState->mapRegion(roundDown(memState->getStackMin(), pageSize),
roundUp(memState->getStackSize(), pageSize), "stack");
// map out initial stack contents
IntType sentry_base = memState->getStackBase() - sentry_size;

View File

@@ -151,8 +151,8 @@ MipsProcess::argsInit(int pageSize)
memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
memState->setStackSize(memState->getStackBase() - memState->getStackMin());
// map memory
allocateMem(memState->getStackMin(), roundUp(memState->getStackSize(),
pageSize));
memState->mapRegion(memState->getStackMin(),
roundUp(memState->getStackSize(), pageSize), "stack");
// map out initial stack contents; leave room for argc
IntType argv_array_base = memState->getStackMin() + intSize;

View File

@@ -200,8 +200,8 @@ PowerProcess::argsInit(int intSize, int pageSize)
memState->setStackSize(memState->getStackBase() - stack_min);
// map memory
allocateMem(roundDown(stack_min, pageSize),
roundUp(memState->getStackSize(), pageSize));
memState->mapRegion(roundDown(stack_min, pageSize),
roundUp(memState->getStackSize(), pageSize), "stack");
// map out initial stack contents
uint32_t sentry_base = memState->getStackBase() - sentry_size;

View File

@@ -147,8 +147,8 @@ RiscvProcess::argsInit(int pageSize)
addrSize + 2 * sizeof(IntType) * auxv.size();
stack_top &= -2*addrSize;
memState->setStackSize(memState->getStackBase() - stack_top);
allocateMem(roundDown(stack_top, pageSize),
roundUp(memState->getStackSize(), pageSize));
memState->mapRegion(roundDown(stack_top, pageSize),
roundUp(memState->getStackSize(), pageSize), "stack");
// Copy random bytes (for AT_RANDOM) to stack
memState->setStackMin(memState->getStackMin() - RandomBytes);

View File

@@ -392,7 +392,7 @@ TLB::translateFunctional(const RequestPtr &req, ThreadContext *tc, Mode mode)
if (!pte && mode != Execute) {
// Check if we just need to grow the stack.
if (process->fixupStackFault(vaddr)) {
if (process->fixupFault(vaddr)) {
// If we did, lookup the entry for the new page.
pte = process->pTable->lookup(vaddr);
}

View File

@@ -683,7 +683,7 @@ FastDataAccessMMUMiss::invoke(ThreadContext *tc, const StaticInstPtr &inst)
Process *p = tc->getProcessPtr();
const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr);
if (!pte && p->fixupStackFault(vaddr))
if (!pte && p->fixupFault(vaddr))
pte = p->pTable->lookup(vaddr);
panic_if(!pte, "Tried to access unmapped address %#x.\n", vaddr);

View File

@@ -317,8 +317,8 @@ SparcProcess::argsInit(int pageSize)
memState->setStackSize(memState->getStackBase() - memState->getStackMin());
// Allocate space for the stack
allocateMem(roundDown(memState->getStackMin(), pageSize),
roundUp(memState->getStackSize(), pageSize));
memState->mapRegion(roundDown(memState->getStackMin(), pageSize),
roundUp(memState->getStackSize(), pageSize), "stack");
// map out initial stack contents
IntType sentry_base = memState->getStackBase() - sentry_size;

View File

@@ -47,6 +47,7 @@
#include "cpu/thread_context.hh"
#include "debug/Faults.hh"
#include "sim/full_system.hh"
#include "sim/process.hh"
namespace X86ISA
{
@@ -151,7 +152,7 @@ namespace X86ISA
} else {
tc->setMiscReg(MISCREG_CR2, (uint32_t)addr);
}
} else {
} else if (!tc->getProcessPtr()->fixupFault(addr)) {
PageFaultErrorCode code = errorCode;
const char *modeStr = "";
if (code.fetch)

View File

@@ -178,7 +178,7 @@ X86_64Process::initState()
argsInit(PageBytes);
// Set up the vsyscall page for this process.
allocateMem(vsyscallPage.base, vsyscallPage.size);
memState->mapRegion(vsyscallPage.base, vsyscallPage.size, "vsyscall");
uint8_t vtimeBlob[] = {
0x48,0xc7,0xc0,0xc9,0x00,0x00,0x00, // mov $0xc9,%rax
0x0f,0x05, // syscall
@@ -629,7 +629,7 @@ I386Process::initState()
}
// Set up the vsyscall page for this process.
allocateMem(vsyscallPage.base, vsyscallPage.size);
memState->mapRegion(vsyscallPage.base, vsyscallPage.size, "vsyscall");
uint8_t vsyscallBlob[] = {
0x51, // push %ecx
0x52, // push %edp
@@ -934,7 +934,7 @@ X86Process::argsInit(int pageSize,
Addr stack_end = roundDown(stack_base - stack_size, pageSize);
DPRINTF(Stack, "Mapping the stack: 0x%x %dB\n", stack_end, stack_size);
allocateMem(stack_end, stack_size);
memState->mapRegion(stack_end, stack_size, "stack");
// map out initial stack contents
IntType sentry_base = stack_base - sentry_size;

View File

@@ -49,7 +49,7 @@ m5PageFault(ThreadContext *tc)
DPRINTF(PseudoInst, "PseudoInst::m5PageFault()\n");
Process *p = tc->getProcessPtr();
if (!p->fixupStackFault(tc->readMiscReg(MISCREG_CR2))) {
if (!p->fixupFault(tc->readMiscReg(MISCREG_CR2))) {
PortProxy &proxy = tc->getVirtProxy();
// at this point we should have 6 values on the interrupt stack
int size = 6;

View File

@@ -399,7 +399,7 @@ TLB::translate(const RequestPtr &req,
p->pTable->lookup(vaddr);
if (!pte && mode != Execute) {
// Check if we just need to grow the stack.
if (p->fixupStackFault(vaddr)) {
if (p->fixupFault(vaddr)) {
// If we did, lookup the entry for the new page.
pte = p->pTable->lookup(vaddr);
}
@@ -487,7 +487,7 @@ TLB::translateFunctional(const RequestPtr &req, ThreadContext *tc, Mode mode)
if (!pte && mode != Execute) {
// Check if we just need to grow the stack.
if (process->fixupStackFault(vaddr)) {
if (process->fixupFault(vaddr)) {
// If we did, lookup the entry for the new page.
pte = process->pTable->lookup(vaddr);
}

View File

@@ -782,7 +782,7 @@ ComputeUnit::sendRequest(GPUDynInstPtr gpuDynInst, int index, PacketPtr pkt)
Addr paddr;
if (!p->pTable->translate(vaddr, paddr)) {
if (!p->fixupStackFault(vaddr)) {
if (!p->fixupFault(vaddr)) {
panic("CU%d: WF[%d][%d]: Fault on addr %#x!\n",
cu_id, gpuDynInst->simdId, gpuDynInst->wfSlotId,
vaddr);

View File

@@ -521,7 +521,7 @@ namespace X86ISA
if (timing)
latency += missLatency2;
if (p->fixupStackFault(vaddr))
if (p->fixupFault(vaddr))
pte = p->pTable->lookup(vaddr);
}
@@ -1044,7 +1044,7 @@ namespace X86ISA
#endif
const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr);
if (!pte && sender_state->tlbMode != BaseTLB::Execute &&
p->fixupStackFault(vaddr)) {
p->fixupFault(vaddr)) {
pte = p->pTable->lookup(vaddr);
}
@@ -1248,7 +1248,7 @@ namespace X86ISA
const EmulationPageTable::Entry *pte =
p->pTable->lookup(vaddr);
if (!pte && sender_state->tlbMode != BaseTLB::Execute &&
p->fixupStackFault(vaddr)) {
p->fixupFault(vaddr)) {
pte = p->pTable->lookup(vaddr);
}

View File

@@ -57,7 +57,7 @@ SETranslatingPortProxy::fixupAddr(Addr addr, BaseTLB::Mode mode) const
if (allocating == Always) {
process->allocateMem(roundDown(addr, pageBytes), pageBytes);
return true;
} else if (allocating == NextPage && process->fixupStackFault(addr)) {
} else if (allocating == NextPage && process->fixupFault(addr)) {
// We've accessed the next page on the stack.
return true;
}

View File

@@ -66,7 +66,7 @@ void GenericPageTableFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
bool handled = false;
if (!FullSystem) {
Process *p = tc->getProcessPtr();
handled = p->fixupStackFault(vaddr);
handled = p->fixupFault(vaddr);
}
if (!handled)
panic("Page table fault when accessing virtual address %#x\n", vaddr);

View File

@@ -352,33 +352,9 @@ Process::replicatePage(Addr vaddr, Addr new_paddr, ThreadContext *old_tc,
}
bool
Process::fixupStackFault(Addr vaddr)
Process::fixupFault(Addr vaddr)
{
Addr stack_min = memState->getStackMin();
Addr stack_base = memState->getStackBase();
Addr max_stack_size = memState->getMaxStackSize();
// Check if this is already on the stack and there's just no page there
// yet.
if (vaddr >= stack_min && vaddr < stack_base) {
allocateMem(roundDown(vaddr, PageBytes), PageBytes);
return true;
}
// We've accessed the next page of the stack, so extend it to include
// this address.
if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) {
while (vaddr < stack_min) {
stack_min -= TheISA::PageBytes;
if (stack_base - stack_min > max_stack_size)
fatal("Maximum stack size exceeded\n");
allocateMem(stack_min, TheISA::PageBytes);
inform("Increasing stack size by one page.");
}
memState->setStackMin(stack_min);
return true;
}
return false;
return memState->fixupFault(vaddr);
}
void

View File

@@ -108,7 +108,7 @@ class Process : public SimObject
/// 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);
bool fixupFault(Addr vaddr);
// After getting registered with system object, tell process which
// system-wide context id it is assigned.

View File

@@ -254,39 +254,14 @@ brkFunc(SyscallDesc *desc, ThreadContext *tc, Addr new_brk)
// in Linux at least, brk(0) returns the current break value
// (note that the syscall and the glibc function have different behavior)
if (new_brk == 0)
if (new_brk == 0 || (new_brk == brk_point))
return brk_point;
if (new_brk > brk_point) {
// might need to allocate some new pages
for (ChunkGenerator gen(brk_point,
new_brk - brk_point,
PageBytes); !gen.done(); gen.next()) {
if (!p->pTable->translate(gen.addr()))
p->allocateMem(roundDown(gen.addr(), PageBytes), PageBytes);
mem_state->updateBrkRegion(brk_point, new_brk);
// if the address is already there, zero it out
else {
uint8_t zero = 0;
PortProxy &tp = tc->getVirtProxy();
// split non-page aligned accesses
Addr next_page = roundUp(gen.addr(), PageBytes);
uint32_t size_needed = next_page - gen.addr();
tp.memsetBlob(gen.addr(), zero, size_needed);
if (gen.addr() + PageBytes > next_page &&
next_page < new_brk &&
p->pTable->translate(next_page)) {
size_needed = PageBytes - size_needed;
tp.memsetBlob(next_page, zero, size_needed);
}
}
}
}
mem_state->setBrkPoint(new_brk);
DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
mem_state->getBrkPoint());
return mem_state->getBrkPoint();
}