diff options
author | Ali Saidi <saidi@eecs.umich.edu> | 2007-05-09 15:37:46 -0400 |
---|---|---|
committer | Ali Saidi <saidi@eecs.umich.edu> | 2007-05-09 15:37:46 -0400 |
commit | 37b45e3c8cb2aef57e1d5dd8efd46705b8d46c16 (patch) | |
tree | 6a4d803e04308139788ee55db97bb37b743ab492 | |
parent | a38c79ec22918b02c529c930827e64e440984d29 (diff) | |
download | gem5-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.cc | 1 | ||||
-rw-r--r-- | src/arch/x86/process.cc | 1 | ||||
-rw-r--r-- | src/cpu/thread_state.cc | 5 | ||||
-rw-r--r-- | src/mem/translating_port.cc | 17 | ||||
-rw-r--r-- | src/mem/translating_port.hh | 13 | ||||
-rw-r--r-- | src/sim/faults.cc | 17 | ||||
-rw-r--r-- | src/sim/process.cc | 27 | ||||
-rw-r--r-- | src/sim/process.hh | 27 | ||||
-rw-r--r-- | src/sim/process_impl.hh | 75 |
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 §ion); }; 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 |