sim-se: Fix mremap for downward growing mmap regions
authorRico Amslinger <rico.amslinger@informatik.uni-augsburg.de>
Mon, 18 Sep 2017 11:44:06 +0000 (13:44 +0200)
committerRico Amslinger <rico.amslinger@informatik.uni-augsburg.de>
Thu, 28 Sep 2017 07:55:18 +0000 (07:55 +0000)
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>

src/sim/syscall_emul.hh

index 7efd7c7e65e54ff931fce56155a9c959cdb5e6e8..fa0959f0ee481a3024e70fdc0019a3c145426b22 100644 (file)
@@ -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");