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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user