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>
This commit is contained in:
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user