summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Saidi <saidi@eecs.umich.edu>2007-05-09 15:37:46 -0400
committerAli Saidi <saidi@eecs.umich.edu>2007-05-09 15:37:46 -0400
commit37b45e3c8cb2aef57e1d5dd8efd46705b8d46c16 (patch)
tree6a4d803e04308139788ee55db97bb37b743ab492
parenta38c79ec22918b02c529c930827e64e440984d29 (diff)
downloadgem5-37b45e3c8cb2aef57e1d5dd8efd46705b8d46c16.tar.xz
fix the translating ports so it can add a page on a fault
--HG-- extra : convert_revision : 56f6f2cbf4e92b7f2dd8c9453831fab86d83ef80
-rw-r--r--src/arch/sparc/process.cc1
-rw-r--r--src/arch/x86/process.cc1
-rw-r--r--src/cpu/thread_state.cc5
-rw-r--r--src/mem/translating_port.cc17
-rw-r--r--src/mem/translating_port.hh13
-rw-r--r--src/sim/faults.cc17
-rw-r--r--src/sim/process.cc27
-rw-r--r--src/sim/process.hh27
-rw-r--r--src/sim/process_impl.hh75
9 files changed, 134 insertions, 49 deletions
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index e4774ab54..d595664a0 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -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"
diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index e6d1e4921..af7494598 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -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;
diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc
index 4b65ca4b8..be8f822f2 100644
--- a/src/cpu/thread_state.cc
+++ b/src/cpu/thread_state.cc
@@ -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);
diff --git a/src/mem/translating_port.cc b/src/mem/translating_port.cc
index d2c854086..54de6625e 100644
--- a/src/mem/translating_port.cc
+++ b/src/mem/translating_port.cc
@@ -34,12 +34,14 @@
#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);
diff --git a/src/mem/translating_port.hh b/src/mem/translating_port.hh
index 7354278ba..76c7947be 100644
--- a/src/mem/translating_port.hh
+++ b/src/mem/translating_port.hh
@@ -35,16 +35,25 @@
#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);
diff --git a/src/sim/faults.cc b/src/sim/faults.cc
index b09bbc177..fe62874d7 100644
--- a/src/sim/faults.cc
+++ b/src/sim/faults.cc
@@ -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
diff --git a/src/sim/process.cc b/src/sim/process.cc
index 68239fa52..8b273d591 100644
--- a/src/sim/process.cc
+++ b/src/sim/process.cc
@@ -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)
{
diff --git a/src/sim/process.hh b/src/sim/process.hh
index dd64fa607..fa46b9c95 100644
--- a/src/sim/process.hh
+++ b/src/sim/process.hh
@@ -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
index 000000000..a3519fe39
--- /dev/null
+++ b/src/sim/process_impl.hh
@@ -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