From 1ff5e31e53cc1f6ae27285a456f380327dc09a0b Mon Sep 17 00:00:00 2001 From: Rico Amslinger Date: Mon, 18 Sep 2017 13:44:06 +0200 Subject: [PATCH] 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 Maintainer: Brandon Potter --- src/sim/syscall_emul.hh | 20 +++++++++++++++----- 1 file 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"); -- 2.30.2