fix the translating ports so it can add a page on a fault
authorAli Saidi <saidi@eecs.umich.edu>
Wed, 9 May 2007 19:37:46 +0000 (15:37 -0400)
committerAli Saidi <saidi@eecs.umich.edu>
Wed, 9 May 2007 19:37:46 +0000 (15:37 -0400)
--HG--
extra : convert_revision : 56f6f2cbf4e92b7f2dd8c9453831fab86d83ef80

src/arch/sparc/process.cc
src/arch/x86/process.cc
src/cpu/thread_state.cc
src/mem/translating_port.cc
src/mem/translating_port.hh
src/sim/faults.cc
src/sim/process.cc
src/sim/process.hh
src/sim/process_impl.hh [new file with mode: 0644]

index e4774ab5402497c703db63ffa5ee81483abf8c80..d595664a0d07b0021a761cafd693698b13470620 100644 (file)
@@ -39,6 +39,7 @@
 #include "base/misc.hh"
 #include "cpu/thread_context.hh"
 #include "mem/page_table.hh"
+#include "sim/process_impl.hh"
 #include "mem/translating_port.hh"
 #include "sim/system.hh"
 
index e6d1e4921ac4b08e8419b41293b10eb76cfe8f4c..af749459835b25cb7d442f0d4dc945a1c94b7782 100644 (file)
@@ -95,6 +95,7 @@
 #include "cpu/thread_context.hh"
 #include "mem/page_table.hh"
 #include "mem/translating_port.hh"
+#include "sim/process_impl.hh"
 #include "sim/system.hh"
 
 using namespace std;
index 4b65ca4b8bc4c456ea19ffb775cbd5bd6754c1a6..be8f822f2eb10b4436688e416cd3dd2f93ca62d0 100644 (file)
@@ -169,9 +169,8 @@ ThreadState::getMemPort()
         return port;
 
     /* Use this port to for syscall emulation writes to memory. */
-    port = new TranslatingPort(csprintf("%s-%d-funcport",
-                                        baseCpu->name(), tid),
-                               process->pTable, false);
+    port = new TranslatingPort(csprintf("%s-%d-funcport", baseCpu->name(), tid),
+                               process, TranslatingPort::NextPage);
 
     connectToMemFunc(port);
 
index d2c854086b01d3067a1a53c409fc1ba089814e2d..54de6625e089b7416e5e087f0adce244fea277ea 100644 (file)
 #include "mem/port.hh"
 #include "mem/translating_port.hh"
 #include "mem/page_table.hh"
+#include "sim/process.hh"
 
 using namespace TheISA;
 
 TranslatingPort::TranslatingPort(const std::string &_name,
-                                 PageTable *p_table, bool alloc)
-    : FunctionalPort(_name), pTable(p_table), allocating(alloc)
+                                 Process *p, AllocType alloc)
+    : FunctionalPort(_name), pTable(p->pTable), process(p),
+      allocating(alloc)
 { }
 
 TranslatingPort::~TranslatingPort()
@@ -81,13 +83,18 @@ TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size)
     for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
 
         if (!pTable->translate(gen.addr(), paddr)) {
-            if (allocating) {
+            if (allocating == Always) {
                 pTable->allocate(roundDown(gen.addr(), VMPageSize),
                                  VMPageSize);
-                pTable->translate(gen.addr(), paddr);
+            } else if (allocating == NextPage) {
+                // check if we've accessed the next page on the stack
+                if (!process->checkAndAllocNextPage(gen.addr()))
+                    panic("Page table fault when accessing virtual address %#x "
+                            "during functional write\n", gen.addr());
             } else {
                 return false;
             }
+            pTable->translate(gen.addr(), paddr);
         }
 
         Port::writeBlob(paddr, p + prevSize, gen.size());
@@ -113,7 +120,7 @@ TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size)
     for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
 
         if (!pTable->translate(gen.addr(), paddr)) {
-            if (allocating) {
+            if (allocating == Always) {
                 pTable->allocate(roundDown(gen.addr(), VMPageSize),
                                  VMPageSize);
                 pTable->translate(gen.addr(), paddr);
index 7354278bac2c003d1571918221090791717fb6f6..76c7947be9be809f34cdf48bc876e2f161488793 100644 (file)
 #include "mem/port.hh"
 
 class PageTable;
+class Process;
 
 class TranslatingPort : public FunctionalPort
 {
+  public:
+    enum AllocType {
+        Always,
+        Never,
+        NextPage
+    };
+
   private:
     PageTable *pTable;
-    bool allocating;
+    Process *process;
+    AllocType allocating;
 
   public:
     TranslatingPort(const std::string &_name,
-                    PageTable *p_table, bool alloc = false);
+                    Process *p, AllocType alloc);
     virtual ~TranslatingPort();
 
     bool tryReadBlob(Addr addr, uint8_t *p, int size);
index b09bbc17716f1922c8ce62763863fbeaa6c057c6..fe62874d7fc8a85d0db7bf0b0ad3874ce60836c5 100644 (file)
@@ -61,21 +61,8 @@ void PageTableFault::invoke(ThreadContext *tc)
 {
     Process *p = tc->getProcessPtr();
 
-    // We've accessed the next page of the stack, so extend the stack
-    // to cover it.
-    if(vaddr < p->stack_min && vaddr >= p->stack_min - TheISA::PageBytes)
-    {
-        p->stack_min -= TheISA::PageBytes;
-        if(p->stack_base - p->stack_min > 8*1024*1024)
-            fatal("Over max stack size for one thread\n");
-        p->pTable->allocate(p->stack_min, TheISA::PageBytes);
-        warn("Increasing stack size by one page.");
-    }
-    // Otherwise, we have an unexpected page fault. Report that fact,
-    // and what address was accessed to cause the fault.
-    else
-    {
+    if (!p->checkAndAllocNextPage(vaddr))
         panic("Page table fault when accessing virtual address %#x\n", vaddr);
-    }
+
 }
 #endif
index 68239fa523016c450287251b358adbf193f87cef..8b273d59100b6f18b5c4ce2c5c2e400670657632 100644 (file)
@@ -47,6 +47,7 @@
 #include "mem/translating_port.hh"
 #include "sim/builder.hh"
 #include "sim/process.hh"
+#include "sim/process_impl.hh"
 #include "sim/stats.hh"
 #include "sim/syscall_emul.hh"
 #include "sim/system.hh"
@@ -182,7 +183,8 @@ Process::startup()
 
     Port *mem_port;
     mem_port = system->physmem->getPort("functional");
-    initVirtMem = new TranslatingPort("process init port", pTable, true);
+    initVirtMem = new TranslatingPort("process init port", this,
+            TranslatingPort::Always);
     mem_port->setPeer(initVirtMem);
     initVirtMem->setPeer(mem_port);
 }
@@ -250,6 +252,29 @@ Process::sim_fd(int tgt_fd)
     return fd_map[tgt_fd];
 }
 
+bool
+Process::checkAndAllocNextPage(Addr vaddr)
+{
+    // if this is an initial write we might not have
+    if (vaddr >= stack_min && vaddr < stack_base) {
+        pTable->allocate(roundDown(vaddr, VMPageSize), VMPageSize);
+        return true;
+    }
+
+    // We've accessed the next page of the stack, so extend the stack
+    // to cover it.
+    if(vaddr < stack_min && vaddr >= stack_min - TheISA::PageBytes)
+    {
+        stack_min -= TheISA::PageBytes;
+        if(stack_base - stack_min > 8*1024*1024)
+            fatal("Over max stack size for one thread\n");
+        pTable->allocate(stack_min, TheISA::PageBytes);
+        warn("Increasing stack size by one page.");
+        return true;
+    }
+    return false;
+}
+
 void
 Process::serialize(std::ostream &os)
 {
index dd64fa607dabd26b08c4c5faece3443672235fd2..fa46b9c952e2d466cd110a94afa03f3915e8adbc 100644 (file)
@@ -45,7 +45,6 @@
 #include <vector>
 
 #include "base/statistics.hh"
-#include "mem/translating_port.hh"
 #include "sim/host.hh"
 #include "sim/sim_object.hh"
 
@@ -60,28 +59,6 @@ namespace TheISA
     class RemoteGDB;
 }
 
-//This needs to be templated for cases where 32 bit pointers are needed.
-template<class AddrType>
-void
-copyStringArray(std::vector<std::string> &strings,
-        AddrType array_ptr, AddrType data_ptr,
-        TranslatingPort* memPort)
-{
-    AddrType data_ptr_swap;
-    for (int i = 0; i < strings.size(); ++i) {
-        data_ptr_swap = htog(data_ptr);
-        memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap,
-                sizeof(AddrType));
-        memPort->writeString(data_ptr, strings[i].c_str());
-        array_ptr += sizeof(AddrType);
-        data_ptr += strings[i].size() + 1;
-    }
-    // add NULL terminator
-    data_ptr = 0;
-
-    memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType));
-}
-
 class Process : public SimObject
 {
   public:
@@ -194,6 +171,10 @@ class Process : public SimObject
 
     virtual void syscall(int64_t callnum, ThreadContext *tc) = 0;
 
+    // check if the this addr is on the next available page and allocate it
+    // if it's not we'll panic
+    bool checkAndAllocNextPage(Addr vaddr);
+
     void serialize(std::ostream &os);
     void unserialize(Checkpoint *cp, const std::string &section);
 };
diff --git a/src/sim/process_impl.hh b/src/sim/process_impl.hh
new file mode 100644 (file)
index 0000000..a3519fe
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ *          Steve Reinhardt
+ */
+
+#ifndef __SIM_PROCESS_IMPL_HH__
+#define __SIM_PROCESS_IMPL_HH__
+
+//
+// The purpose of this code is to fake the loader & syscall mechanism
+// when there's no OS: thus there's no reason to use it in FULL_SYSTEM
+// mode when we do have an OS.
+//
+#include "config/full_system.hh"
+
+#if !FULL_SYSTEM
+
+#include <string>
+#include <vector>
+
+#include "mem/translating_port.hh"
+
+
+//This needs to be templated for cases where 32 bit pointers are needed.
+template<class AddrType>
+void
+copyStringArray(std::vector<std::string> &strings,
+        AddrType array_ptr, AddrType data_ptr,
+        TranslatingPort* memPort)
+{
+    AddrType data_ptr_swap;
+    for (int i = 0; i < strings.size(); ++i) {
+        data_ptr_swap = htog(data_ptr);
+        memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap,
+                sizeof(AddrType));
+        memPort->writeString(data_ptr, strings[i].c_str());
+        array_ptr += sizeof(AddrType);
+        data_ptr += strings[i].size() + 1;
+    }
+    // add NULL terminator
+    data_ptr = 0;
+
+    memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType));
+}
+
+
+#endif // !FULL_SYSTEM
+
+#endif