changeset b0d7c64ada19 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=b0d7c64ada19
description:
        syscall_emul: implement MAP_FIXED option to mmap()

diffstat:

 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(-)

diffs (234 lines):

diff -r 30d0e4c249b5 -r b0d7c64ada19 src/arch/alpha/linux/linux.hh
--- a/src/arch/alpha/linux/linux.hh     Sat Oct 22 16:52:07 2011 -0700
+++ b/src/arch/alpha/linux/linux.hh     Sat Oct 22 22:30:07 2011 -0700
@@ -69,6 +69,7 @@
 
     /// For mmap().
     static const unsigned TGT_MAP_ANONYMOUS = 0x10;
+    static const unsigned TGT_MAP_FIXED     = 0x100;
 
     //@{
     /// For getsysinfo().
diff -r 30d0e4c249b5 -r b0d7c64ada19 src/arch/alpha/tru64/tru64.hh
--- a/src/arch/alpha/tru64/tru64.hh     Sat Oct 22 16:52:07 2011 -0700
+++ b/src/arch/alpha/tru64/tru64.hh     Sat Oct 22 22:30:07 2011 -0700
@@ -64,6 +64,7 @@
 
     /// For mmap().
     static const unsigned TGT_MAP_ANONYMOUS = 0x10;
+    static const unsigned TGT_MAP_FIXED     = 0x100;
 
     //@{
     /// For getsysinfo().
diff -r 30d0e4c249b5 -r b0d7c64ada19 src/arch/arm/linux/linux.hh
--- a/src/arch/arm/linux/linux.hh       Sat Oct 22 16:52:07 2011 -0700
+++ b/src/arch/arm/linux/linux.hh       Sat Oct 22 22:30:07 2011 -0700
@@ -91,6 +91,7 @@
 
     /// For mmap().
     static const unsigned TGT_MAP_ANONYMOUS = 0x20;
+    static const unsigned TGT_MAP_FIXED     = 0x10;
 
     //@{
     /// For getrusage().
diff -r 30d0e4c249b5 -r b0d7c64ada19 src/arch/mips/linux/linux.hh
--- a/src/arch/mips/linux/linux.hh      Sat Oct 22 16:52:07 2011 -0700
+++ b/src/arch/mips/linux/linux.hh      Sat Oct 22 22:30:07 2011 -0700
@@ -65,6 +65,7 @@
 
     /// For mmap().
     static const unsigned TGT_MAP_ANONYMOUS = 0x800;
+    static const unsigned TGT_MAP_FIXED     = 0x10;
 
     //@{
     /// For getsysinfo().
diff -r 30d0e4c249b5 -r b0d7c64ada19 src/arch/power/linux/linux.hh
--- a/src/arch/power/linux/linux.hh     Sat Oct 22 16:52:07 2011 -0700
+++ b/src/arch/power/linux/linux.hh     Sat Oct 22 22:30:07 2011 -0700
@@ -127,6 +127,7 @@
 
     /// For mmap().
     static const unsigned TGT_MAP_ANONYMOUS = 0x20;
+    static const unsigned TGT_MAP_FIXED     = 0x10;
 
     //@{
     /// ioctl() command codes.
diff -r 30d0e4c249b5 -r b0d7c64ada19 src/arch/sparc/linux/linux.hh
--- a/src/arch/sparc/linux/linux.hh     Sat Oct 22 16:52:07 2011 -0700
+++ b/src/arch/sparc/linux/linux.hh     Sat Oct 22 22:30:07 2011 -0700
@@ -77,6 +77,7 @@
     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 -r 30d0e4c249b5 -r b0d7c64ada19 src/arch/sparc/solaris/solaris.hh
--- a/src/arch/sparc/solaris/solaris.hh Sat Oct 22 16:52:07 2011 -0700
+++ b/src/arch/sparc/solaris/solaris.hh Sat Oct 22 22:30:07 2011 -0700
@@ -59,6 +59,7 @@
     static const int NUM_OPEN_FLAGS;
 
     static const unsigned TGT_MAP_ANONYMOUS = 0x100;
+    static const unsigned TGT_MAP_FIXED     = 0x10;
 };
 
 #endif
diff -r 30d0e4c249b5 -r b0d7c64ada19 src/arch/x86/linux/linux.hh
--- a/src/arch/x86/linux/linux.hh       Sat Oct 22 16:52:07 2011 -0700
+++ b/src/arch/x86/linux/linux.hh       Sat Oct 22 22:30:07 2011 -0700
@@ -88,6 +88,7 @@
     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 @@
     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 -r 30d0e4c249b5 -r b0d7c64ada19 src/mem/page_table.cc
--- a/src/mem/page_table.cc     Sat Oct 22 16:52:07 2011 -0700
+++ b/src/mem/page_table.cc     Sat Oct 22 22:30:07 2011 -0700
@@ -67,7 +67,7 @@
 }
 
 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 @@
     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]);
     }
 }
@@ -128,6 +125,21 @@
 }
 
 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)
 {
     Addr page_addr = pageAlign(vaddr);
diff -r 30d0e4c249b5 -r b0d7c64ada19 src/mem/page_table.hh
--- a/src/mem/page_table.hh     Sat Oct 22 16:52:07 2011 -0700
+++ b/src/mem/page_table.hh     Sat Oct 22 22:30:07 2011 -0700
@@ -79,11 +79,19 @@
     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.
      * @return entry The page table entry corresponding to vaddr.
diff -r 30d0e4c249b5 -r b0d7c64ada19 src/sim/syscall_emul.hh
--- a/src/sim/syscall_emul.hh   Sat Oct 22 16:52:07 2011 -0700
+++ b/src/sim/syscall_emul.hh   Sat Oct 22 22:30:07 2011 -0700
@@ -1027,20 +1027,45 @@
         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;
 }
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to