diff options
author | Rico Amslinger <rico.amslinger@informatik.uni-augsburg.de> | 2017-09-18 13:44:06 +0200 |
---|---|---|
committer | Rico Amslinger <rico.amslinger@informatik.uni-augsburg.de> | 2017-09-28 07:55:18 +0000 |
commit | 1ff5e31e53cc1f6ae27285a456f380327dc09a0b (patch) | |
tree | a49ccb6d07ee53214b00da76881721e1bef17537 /src | |
parent | 0b77e05cb21ad946f12b67cf3336ba92b2a1a522 (diff) | |
download | gem5-1ff5e31e53cc1f6ae27285a456f380327dc09a0b.tar.xz |
sim-se: Fix mremap for downward growing mmap regions
mremapFunc(...) did not respect Process::mmapGrowsDown(). This resulted
in an attempt to remap into an already allocated region and a panic in
FuncPageTable::allocate(...). This behavior can be observed in
435.gromacs.
Change-Id: Ib3ad33816126c76506d69679bdcefa7a98ef69f9
Reviewed-on: https://gem5-review.googlesource.com/4700
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Brandon Potter <Brandon.Potter@amd.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/sim/syscall_emul.hh | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 7efd7c7e6..fa0959f0e 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -932,6 +932,8 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) if ((start + old_length) == mmap_end && (!use_provided_address || provided_address == start)) { + // This case cannot occur when growing downward, as + // start is greater than or equal to mmap_end. uint64_t diff = new_length - old_length; process->allocateMem(mmap_end, diff); mem_state->setMmapEnd(mmap_end + diff); @@ -941,8 +943,15 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); return -ENOMEM; } else { - uint64_t new_start = use_provided_address ? - provided_address : mmap_end; + uint64_t new_start = provided_address; + if (!use_provided_address) { + new_start = process->mmapGrowsDown() ? + mmap_end - new_length : mmap_end; + mmap_end = process->mmapGrowsDown() ? + new_start : mmap_end + new_length; + mem_state->setMmapEnd(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, @@ -951,10 +960,11 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) process->allocateMem(new_start + old_length, new_length - old_length, use_provided_address /* clobber */); - if (!use_provided_address) - mem_state->setMmapEnd(mmap_end + new_length); if (use_provided_address && - new_start + new_length > mem_state->getMmapEnd()) { + ((new_start + new_length > mem_state->getMmapEnd() && + !process->mmapGrowsDown()) || + (new_start < mem_state->getMmapEnd() && + process->mmapGrowsDown()))) { // something fishy going on here, at least notify the user // @todo: increase mmap_end? warn("mmap region limit exceeded with MREMAP_FIXED\n"); |