diff options
Diffstat (limited to 'src/sim')
-rw-r--r-- | src/sim/mem_state.hh | 100 | ||||
-rw-r--r-- | src/sim/process.cc | 40 | ||||
-rw-r--r-- | src/sim/process.hh | 39 | ||||
-rw-r--r-- | src/sim/syscall_emul.cc | 19 | ||||
-rw-r--r-- | src/sim/syscall_emul.hh | 27 |
5 files changed, 144 insertions, 81 deletions
diff --git a/src/sim/mem_state.hh b/src/sim/mem_state.hh new file mode 100644 index 000000000..03a719752 --- /dev/null +++ b/src/sim/mem_state.hh @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Brandon Potter + */ + +#ifndef SRC_SIM_MEM_STATE_HH +#define SRC_SIM_MEM_STATE_HH + +/** + * This class holds the memory state for the Process class and all of its + * derived, architecture-specific children. + * + * The fields held in this class dynamically change as the process object + * is run in the simulator. They are updated by system calls and faults; + * each change represents a modification to the process address space. + * The stack, heap, and mmap boundaries are held with this class along with + * the base of the next thread stack. + * + * The class is meant to be allocated dynamically and shared through a + * pointer interface because two process can potentially share their virtual + * address space if certain options are passed into the clone(2). + */ +class MemState +{ + public: + MemState(Addr brk_point, Addr stack_base, Addr max_stack_size, + Addr next_thread_stack_base, Addr mmap_end) + : _brkPoint(brk_point), _stackBase(stack_base), _stackSize(0), + _maxStackSize(max_stack_size), _stackMin(0), + _nextThreadStackBase(next_thread_stack_base), _mmapEnd(mmap_end) + { } + + MemState& + operator=(const MemState &in) + { + if (this == &in) + return *this; + + _brkPoint = in._brkPoint; + _stackBase = in._stackBase; + _stackSize = in._stackSize; + _maxStackSize = in._maxStackSize; + _stackMin = in._stackMin; + _nextThreadStackBase = in._nextThreadStackBase; + _mmapEnd = in._mmapEnd; + return *this; + } + + Addr getBrkPoint() const { return _brkPoint; } + Addr getStackBase() const { return _stackBase; } + Addr getStackSize() const { return _stackSize; } + Addr getMaxStackSize() const { return _maxStackSize; } + Addr getStackMin() const { return _stackMin; } + Addr getNextThreadStackBase() const { return _nextThreadStackBase; } + Addr getMmapEnd() const { return _mmapEnd; } + + void setBrkPoint(Addr brk_point) { _brkPoint = brk_point; } + void setStackBase(Addr stack_base) { _stackBase = stack_base; } + void setStackSize(Addr stack_size) { _stackSize = stack_size; } + void setMaxStackSize(Addr max_stack) { _maxStackSize = max_stack; } + void setStackMin(Addr stack_min) { _stackMin = stack_min; } + void setNextThreadStackBase(Addr ntsb) { _nextThreadStackBase = ntsb; } + void setMmapEnd(Addr mmap_end) { _mmapEnd = mmap_end; } + + private: + Addr _brkPoint; + Addr _stackBase; + Addr _stackSize; + Addr _maxStackSize; + Addr _stackMin; + Addr _nextThreadStackBase; + Addr _mmapEnd; +}; + +#endif diff --git a/src/sim/process.cc b/src/sim/process.cc index 7cfaf6530..e516e2a05 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -111,7 +111,6 @@ Process::Process(ProcessParams * params, ObjectFile * obj_file) _pid(params->pid), _ppid(params->ppid), _pgid(params->pgid), drivers(params->drivers), fds(make_shared<FDArray>(params->input, params->output, params->errout)), - maxStackSize(params->maxStackSize), childClearTID(0) { if (_pid >= System::maxPID) @@ -136,7 +135,6 @@ Process::Process(ProcessParams * params, ObjectFile * obj_file) _tgid = params->pid; exitGroup = new bool(); - memState = new MemState(); sigchld = new bool(); if (!debugSymbolTable) { @@ -164,7 +162,6 @@ Process::clone(ThreadContext *otc, ThreadContext *ntc, np->pTable = pTable; ntc->getMemProxy().setPageTable(np->pTable); - delete np->memState; np->memState = memState; } else { /** @@ -323,24 +320,28 @@ Process::replicatePage(Addr vaddr, Addr new_paddr, ThreadContext *old_tc, bool Process::fixupStackFault(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 >= memState->stackMin && vaddr < memState->stackBase) { + 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 < memState->stackMin - && vaddr >= memState->stackBase - maxStackSize) { - while (vaddr < memState->stackMin) { - memState->stackMin -= TheISA::PageBytes; - if (memState->stackBase - memState->stackMin > maxStackSize) + 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(memState->stackMin, TheISA::PageBytes); + allocateMem(stack_min, TheISA::PageBytes); inform("Increasing stack size by one page."); }; + memState->setStackMin(stack_min); return true; } return false; @@ -349,12 +350,6 @@ Process::fixupStackFault(Addr vaddr) void Process::serialize(CheckpointOut &cp) const { - SERIALIZE_SCALAR(memState->brkPoint); - SERIALIZE_SCALAR(memState->stackBase); - SERIALIZE_SCALAR(memState->stackSize); - SERIALIZE_SCALAR(memState->stackMin); - SERIALIZE_SCALAR(memState->nextThreadStackBase); - SERIALIZE_SCALAR(memState->mmapEnd); pTable->serialize(cp); /** * Checkpoints for file descriptors currently do not work. Need to @@ -372,12 +367,6 @@ Process::serialize(CheckpointOut &cp) const void Process::unserialize(CheckpointIn &cp) { - UNSERIALIZE_SCALAR(memState->brkPoint); - UNSERIALIZE_SCALAR(memState->stackBase); - UNSERIALIZE_SCALAR(memState->stackSize); - UNSERIALIZE_SCALAR(memState->stackMin); - UNSERIALIZE_SCALAR(memState->nextThreadStackBase); - UNSERIALIZE_SCALAR(memState->mmapEnd); pTable->unserialize(cp); /** * Checkpoints for file descriptors currently do not work. Need to @@ -446,13 +435,14 @@ Process::updateBias() // We are allocating the memory area; set the bias to the lowest address // in the allocated memory region. - Addr *end = &memState->mmapEnd; - Addr ld_bias = mmapGrowsDown() ? *end - interp_mapsize : *end; + Addr mmap_end = memState->getMmapEnd(); + Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end; // Adjust the process mmap area to give the interpreter room; the real // execve system call would just invoke the kernel's internal mmap // functions to make these adjustments. - *end = mmapGrowsDown() ? ld_bias : *end + interp_mapsize; + mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize; + memState->setMmapEnd(mmap_end); interp->updateBias(ld_bias); } diff --git a/src/sim/process.hh b/src/sim/process.hh index 52a06bedd..da538f8da 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -47,6 +47,7 @@ #include "mem/se_translating_port_proxy.hh" #include "sim/fd_array.hh" #include "sim/fd_entry.hh" +#include "sim/mem_state.hh" #include "sim/sim_object.hh" struct ProcessParams; @@ -62,40 +63,6 @@ class ThreadContext; class Process : public SimObject { public: - - struct MemState - { - Addr brkPoint; - Addr stackBase; - unsigned stackSize; - Addr stackMin; - Addr nextThreadStackBase; - Addr mmapEnd; - - MemState() - : brkPoint(0), stackBase(0), stackSize(0), stackMin(0), - nextThreadStackBase(0), mmapEnd(0) - { } - - MemState& - operator=(const MemState &in) - { - if (this == &in) - return *this; - - brkPoint = in.brkPoint; - stackBase = in.stackBase; - stackSize = in.stackSize; - stackMin = in.stackMin; - nextThreadStackBase = in.nextThreadStackBase; - mmapEnd = in.mmapEnd; - return *this; - } - - void serialize(CheckpointOut &cp) const; - void unserialize(CheckpointIn &cp); - }; - Process(ProcessParams *params, ObjectFile *obj_file); void serialize(CheckpointOut &cp) const override; @@ -236,9 +203,7 @@ class Process : public SimObject std::shared_ptr<FDArray> fds; bool *exitGroup; - - Addr maxStackSize; - MemState *memState; + std::shared_ptr<MemState> memState; /** * Calls a futex wakeup at the address specified by this pointer when diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 07899ec9a..f61de229c 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -150,22 +150,25 @@ brkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) int index = 0; Addr new_brk = p->getSyscallArg(tc, index); + std::shared_ptr<MemState> mem_state = p->memState; + Addr brk_point = mem_state->getBrkPoint(); + // 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) - return p->memState->brkPoint; + return brk_point; - if (new_brk > p->memState->brkPoint) { + if (new_brk > brk_point) { // might need to allocate some new pages - for (ChunkGenerator gen(p->memState->brkPoint, - new_brk - p->memState->brkPoint, + 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; + uint8_t zero = 0; SETranslatingPortProxy &tp = tc->getMemProxy(); // split non-page aligned accesses @@ -183,10 +186,10 @@ brkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) } } - p->memState->brkPoint = new_brk; + mem_state->setBrkPoint(new_brk); DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n", - p->memState->brkPoint); - return p->memState->brkPoint; + mem_state->getBrkPoint()); + return mem_state->getBrkPoint(); } SyscallReturn diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 8a34c3415..8cca6ebcb 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -885,11 +885,14 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) new_length = roundUp(new_length, TheISA::PageBytes); if (new_length > old_length) { - if ((start + old_length) == process->memState->mmapEnd && + std::shared_ptr<MemState> mem_state = process->memState; + Addr mmap_end = mem_state->getMmapEnd(); + + if ((start + old_length) == mmap_end && (!use_provided_address || provided_address == start)) { uint64_t diff = new_length - old_length; - process->allocateMem(process->memState->mmapEnd, diff); - process->memState->mmapEnd += diff; + process->allocateMem(mmap_end, diff); + mem_state->setMmapEnd(mmap_end + diff); return start; } else { if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) { @@ -897,7 +900,7 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) return -ENOMEM; } else { uint64_t new_start = use_provided_address ? - provided_address : process->memState->mmapEnd; + provided_address : mmap_end; process->pTable->remap(start, old_length, new_start); warn("mremapping to new vaddr %08p-%08p, adding %d\n", new_start, new_start + new_length, @@ -907,9 +910,9 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) new_length - old_length, use_provided_address /* clobber */); if (!use_provided_address) - process->memState->mmapEnd += new_length; + mem_state->setMmapEnd(mmap_end + new_length); if (use_provided_address && - new_start + new_length > process->memState->mmapEnd) { + new_start + new_length > mem_state->getMmapEnd()) { // something fishy going on here, at least notify the user // @todo: increase mmap_end? warn("mmap region limit exceeded with MREMAP_FIXED\n"); @@ -1214,7 +1217,6 @@ cloneFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) pp->executable.assign(*(new std::string(p->progName()))); pp->cmd.push_back(*(new std::string(p->progName()))); pp->system = p->system; - pp->maxStackSize = p->maxStackSize; pp->cwd.assign(p->getcwd()); pp->input.assign("stdin"); pp->output.assign("stdout"); @@ -1457,9 +1459,13 @@ mmapImpl(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, // Extend global mmap region if necessary. Note that we ignore the // start address unless MAP_FIXED is specified. if (!(tgt_flags & OS::TGT_MAP_FIXED)) { - Addr *end = &p->memState->mmapEnd; - start = p->mmapGrowsDown() ? *end - length : *end; - *end = p->mmapGrowsDown() ? start : *end + length; + std::shared_ptr<MemState> mem_state = p->memState; + Addr mmap_end = mem_state->getMmapEnd(); + + start = p->mmapGrowsDown() ? mmap_end - length : mmap_end; + mmap_end = p->mmapGrowsDown() ? start : mmap_end + length; + + mem_state->setMmapEnd(mmap_end); } DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n", @@ -1768,7 +1774,6 @@ execveFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) pp->errout.assign("cerr"); pp->cwd.assign(p->getcwd()); pp->system = p->system; - pp->maxStackSize = p->maxStackSize; /** * Prevent process object creation with identical PIDs (which will trip * a fatal check in Process constructor). The execve call is supposed to |