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;
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;
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;
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);
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);
}
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);
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;
#include "cpu/thread_context.hh"
#include "debug/Faults.hh"
#include "sim/full_system.hh"
+#include "sim/process.hh"
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)
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
}
// 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
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;
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;
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);
}
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);
}
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);
if (timing)
latency += missLatency2;
- if (p->fixupStackFault(vaddr))
+ if (p->fixupFault(vaddr))
pte = p->pTable->lookup(vaddr);
}
#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);
}
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);
}
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;
}
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);
}
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
/// 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.
// 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);
-
- // 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->updateBrkRegion(brk_point, new_brk);
- mem_state->setBrkPoint(new_brk);
DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
mem_state->getBrkPoint());
+
return mem_state->getBrkPoint();
}