From 4d5f2c28a88f83d390e80407f55a8a02ead33878 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 22 Oct 2011 22:30:07 -0700 Subject: syscall_emul: implement MAP_FIXED option to mmap() --- src/arch/alpha/linux/linux.hh | 1 + src/arch/alpha/tru64/tru64.hh | 1 + src/arch/arm/linux/linux.hh | 1 + src/arch/mips/linux/linux.hh | 1 + src/arch/power/linux/linux.hh | 1 + src/arch/sparc/linux/linux.hh | 1 + src/arch/sparc/solaris/solaris.hh | 1 + src/arch/x86/linux/linux.hh | 2 ++ src/mem/page_table.cc | 26 ++++++++++++++++------ src/mem/page_table.hh | 10 ++++++++- src/sim/syscall_emul.hh | 47 ++++++++++++++++++++++++++++++--------- 11 files changed, 73 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/linux/linux.hh b/src/arch/alpha/linux/linux.hh index c728ce1fb..3304816c3 100644 --- a/src/arch/alpha/linux/linux.hh +++ b/src/arch/alpha/linux/linux.hh @@ -69,6 +69,7 @@ class AlphaLinux : public Linux /// For mmap(). static const unsigned TGT_MAP_ANONYMOUS = 0x10; + static const unsigned TGT_MAP_FIXED = 0x100; //@{ /// For getsysinfo(). diff --git a/src/arch/alpha/tru64/tru64.hh b/src/arch/alpha/tru64/tru64.hh index 0ee12973c..f0cad8289 100644 --- a/src/arch/alpha/tru64/tru64.hh +++ b/src/arch/alpha/tru64/tru64.hh @@ -64,6 +64,7 @@ class AlphaTru64 : public Tru64 /// For mmap(). static const unsigned TGT_MAP_ANONYMOUS = 0x10; + static const unsigned TGT_MAP_FIXED = 0x100; //@{ /// For getsysinfo(). diff --git a/src/arch/arm/linux/linux.hh b/src/arch/arm/linux/linux.hh index 33e48fc93..40d586aaf 100644 --- a/src/arch/arm/linux/linux.hh +++ b/src/arch/arm/linux/linux.hh @@ -91,6 +91,7 @@ class ArmLinux : public Linux /// For mmap(). static const unsigned TGT_MAP_ANONYMOUS = 0x20; + static const unsigned TGT_MAP_FIXED = 0x10; //@{ /// For getrusage(). diff --git a/src/arch/mips/linux/linux.hh b/src/arch/mips/linux/linux.hh index a2418cfb6..949cce8aa 100644 --- a/src/arch/mips/linux/linux.hh +++ b/src/arch/mips/linux/linux.hh @@ -65,6 +65,7 @@ class MipsLinux : public Linux /// For mmap(). static const unsigned TGT_MAP_ANONYMOUS = 0x800; + static const unsigned TGT_MAP_FIXED = 0x10; //@{ /// For getsysinfo(). diff --git a/src/arch/power/linux/linux.hh b/src/arch/power/linux/linux.hh index 1bfc9cbd8..45ca048a0 100644 --- a/src/arch/power/linux/linux.hh +++ b/src/arch/power/linux/linux.hh @@ -127,6 +127,7 @@ class PowerLinux : public Linux /// For mmap(). static const unsigned TGT_MAP_ANONYMOUS = 0x20; + static const unsigned TGT_MAP_FIXED = 0x10; //@{ /// ioctl() command codes. diff --git a/src/arch/sparc/linux/linux.hh b/src/arch/sparc/linux/linux.hh index 1f7567d43..8ac408812 100644 --- a/src/arch/sparc/linux/linux.hh +++ b/src/arch/sparc/linux/linux.hh @@ -77,6 +77,7 @@ class SparcLinux : public Linux static const int NUM_OPEN_FLAGS; static const unsigned TGT_MAP_ANONYMOUS = 0x20; + static const unsigned TGT_MAP_FIXED = 0x10; typedef struct { int64_t uptime; /* Seconds since boot */ diff --git a/src/arch/sparc/solaris/solaris.hh b/src/arch/sparc/solaris/solaris.hh index df2565027..8222addab 100644 --- a/src/arch/sparc/solaris/solaris.hh +++ b/src/arch/sparc/solaris/solaris.hh @@ -59,6 +59,7 @@ class SparcSolaris : public Solaris static const int NUM_OPEN_FLAGS; static const unsigned TGT_MAP_ANONYMOUS = 0x100; + static const unsigned TGT_MAP_FIXED = 0x10; }; #endif diff --git a/src/arch/x86/linux/linux.hh b/src/arch/x86/linux/linux.hh index 99b09f405..4e5d43d45 100644 --- a/src/arch/x86/linux/linux.hh +++ b/src/arch/x86/linux/linux.hh @@ -88,6 +88,7 @@ class X86Linux64 : public Linux static const int NUM_OPEN_FLAGS; static const unsigned TGT_MAP_ANONYMOUS = 0x20; + static const unsigned TGT_MAP_FIXED = 0x10; typedef struct { uint64_t iov_base; // void * @@ -158,6 +159,7 @@ class X86Linux32 : public Linux static const int NUM_OPEN_FLAGS; static const unsigned TGT_MAP_ANONYMOUS = 0x20; + static const unsigned TGT_MAP_FIXED = 0x10; typedef struct { int32_t uptime; /* Seconds since boot */ diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc index a94d92480..745872319 100644 --- a/src/mem/page_table.cc +++ b/src/mem/page_table.cc @@ -67,7 +67,7 @@ PageTable::~PageTable() } void -PageTable::allocate(Addr vaddr, int64_t size) +PageTable::allocate(Addr vaddr, int64_t size, bool clobber) { // starting address must be page aligned assert(pageOffset(vaddr) == 0); @@ -75,16 +75,13 @@ PageTable::allocate(Addr vaddr, int64_t size) DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr+ size); for (; size > 0; size -= pageSize, vaddr += pageSize) { - PTableItr iter = pTable.find(vaddr); - - if (iter != pTable.end()) { + if (!clobber && (pTable.find(vaddr) != pTable.end())) { // already mapped - fatal("PageTable::allocate: address 0x%x already mapped", - vaddr); + fatal("PageTable::allocate: address 0x%x already mapped", vaddr); } pTable[vaddr] = TheISA::TlbEntry(process->M5_pid, vaddr, - process->system->new_page()); + process->system->new_page()); updateCache(vaddr, pTable[vaddr]); } } @@ -127,6 +124,21 @@ PageTable::deallocate(Addr vaddr, int64_t size) } +bool +PageTable::isUnmapped(Addr vaddr, int64_t size) +{ + // starting address must be page aligned + assert(pageOffset(vaddr) == 0); + + for (; size > 0; size -= pageSize, vaddr += pageSize) { + if (pTable.find(vaddr) != pTable.end()) { + return false; + } + } + + return true; +} + bool PageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry) { diff --git a/src/mem/page_table.hh b/src/mem/page_table.hh index 61da5f322..d60f4a433 100644 --- a/src/mem/page_table.hh +++ b/src/mem/page_table.hh @@ -79,10 +79,18 @@ class PageTable Addr pageAlign(Addr a) { return (a & ~offsetMask); } Addr pageOffset(Addr a) { return (a & offsetMask); } - void allocate(Addr vaddr, int64_t size); + void allocate(Addr vaddr, int64_t size, bool clobber = false); void remap(Addr vaddr, int64_t size, Addr new_vaddr); void deallocate(Addr vaddr, int64_t size); + /** + * Check if any pages in a region are already allocated + * @param vaddr The starting virtual address of the region. + * @param size The length of the region. + * @return True if no pages in the region are mapped. + */ + bool isUnmapped(Addr vaddr, int64_t size); + /** * Lookup function * @param vaddr The virtual address. diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index d119adc24..9bcf58844 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -1027,20 +1027,45 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) return -EINVAL; } - if (start != 0) { - warn("mmap: ignoring suggested map address 0x%x, using 0x%x", - start, p->mmap_end); + // are we ok with clobbering existing mappings? only set this to + // true if the user has been warned. + bool clobber = false; + + // try to use the caller-provided address if there is one + bool use_provided_address = (start != 0); + + if (use_provided_address) { + // check to see if the desired address is already in use + if (!p->pTable->isUnmapped(start, length)) { + // there are existing mappings in the desired range + // whether we clobber them or not depends on whether the caller + // specified MAP_FIXED + if (flags & OS::TGT_MAP_FIXED) { + // MAP_FIXED specified: clobber existing mappings + warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n", + start); + clobber = true; + } else { + // MAP_FIXED not specified: ignore suggested start address + warn("mmap: ignoring suggested map address 0x%x\n", start); + use_provided_address = false; + } + } } - // pick next address from our "mmap region" - if (OS::mmapGrowsDown()) { - start = p->mmap_end - length; - p->mmap_end = start; - } else { - start = p->mmap_end; - p->mmap_end += length; + if (!use_provided_address) { + // no address provided, or provided address unusable: + // pick next address from our "mmap region" + if (OS::mmapGrowsDown()) { + start = p->mmap_end - length; + p->mmap_end = start; + } else { + start = p->mmap_end; + p->mmap_end += length; + } } - p->pTable->allocate(start, length); + + p->pTable->allocate(start, length, clobber); return start; } -- cgit v1.2.3