fix the translating ports so it can add a page on a fault

--HG--
extra : convert_revision : 56f6f2cbf4e92b7f2dd8c9453831fab86d83ef80
This commit is contained in:
Ali Saidi 2007-05-09 15:37:46 -04:00
parent a38c79ec22
commit 37b45e3c8c
9 changed files with 134 additions and 49 deletions

View file

@ -39,6 +39,7 @@
#include "base/misc.hh" #include "base/misc.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
#include "mem/page_table.hh" #include "mem/page_table.hh"
#include "sim/process_impl.hh"
#include "mem/translating_port.hh" #include "mem/translating_port.hh"
#include "sim/system.hh" #include "sim/system.hh"

View file

@ -95,6 +95,7 @@
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
#include "mem/page_table.hh" #include "mem/page_table.hh"
#include "mem/translating_port.hh" #include "mem/translating_port.hh"
#include "sim/process_impl.hh"
#include "sim/system.hh" #include "sim/system.hh"
using namespace std; using namespace std;

View file

@ -169,9 +169,8 @@ ThreadState::getMemPort()
return port; return port;
/* Use this port to for syscall emulation writes to memory. */ /* Use this port to for syscall emulation writes to memory. */
port = new TranslatingPort(csprintf("%s-%d-funcport", port = new TranslatingPort(csprintf("%s-%d-funcport", baseCpu->name(), tid),
baseCpu->name(), tid), process, TranslatingPort::NextPage);
process->pTable, false);
connectToMemFunc(port); connectToMemFunc(port);

View file

@ -34,12 +34,14 @@
#include "mem/port.hh" #include "mem/port.hh"
#include "mem/translating_port.hh" #include "mem/translating_port.hh"
#include "mem/page_table.hh" #include "mem/page_table.hh"
#include "sim/process.hh"
using namespace TheISA; using namespace TheISA;
TranslatingPort::TranslatingPort(const std::string &_name, TranslatingPort::TranslatingPort(const std::string &_name,
PageTable *p_table, bool alloc) Process *p, AllocType alloc)
: FunctionalPort(_name), pTable(p_table), allocating(alloc) : FunctionalPort(_name), pTable(p->pTable), process(p),
allocating(alloc)
{ } { }
TranslatingPort::~TranslatingPort() 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()) { for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
if (!pTable->translate(gen.addr(), paddr)) { if (!pTable->translate(gen.addr(), paddr)) {
if (allocating) { if (allocating == Always) {
pTable->allocate(roundDown(gen.addr(), VMPageSize), pTable->allocate(roundDown(gen.addr(), VMPageSize),
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 { } else {
return false; return false;
} }
pTable->translate(gen.addr(), paddr);
} }
Port::writeBlob(paddr, p + prevSize, gen.size()); 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()) { for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) {
if (!pTable->translate(gen.addr(), paddr)) { if (!pTable->translate(gen.addr(), paddr)) {
if (allocating) { if (allocating == Always) {
pTable->allocate(roundDown(gen.addr(), VMPageSize), pTable->allocate(roundDown(gen.addr(), VMPageSize),
VMPageSize); VMPageSize);
pTable->translate(gen.addr(), paddr); pTable->translate(gen.addr(), paddr);

View file

@ -35,16 +35,25 @@
#include "mem/port.hh" #include "mem/port.hh"
class PageTable; class PageTable;
class Process;
class TranslatingPort : public FunctionalPort class TranslatingPort : public FunctionalPort
{ {
public:
enum AllocType {
Always,
Never,
NextPage
};
private: private:
PageTable *pTable; PageTable *pTable;
bool allocating; Process *process;
AllocType allocating;
public: public:
TranslatingPort(const std::string &_name, TranslatingPort(const std::string &_name,
PageTable *p_table, bool alloc = false); Process *p, AllocType alloc);
virtual ~TranslatingPort(); virtual ~TranslatingPort();
bool tryReadBlob(Addr addr, uint8_t *p, int size); bool tryReadBlob(Addr addr, uint8_t *p, int size);

View file

@ -61,21 +61,8 @@ void PageTableFault::invoke(ThreadContext *tc)
{ {
Process *p = tc->getProcessPtr(); Process *p = tc->getProcessPtr();
// We've accessed the next page of the stack, so extend the stack if (!p->checkAndAllocNextPage(vaddr))
// 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
{
panic("Page table fault when accessing virtual address %#x\n", vaddr); panic("Page table fault when accessing virtual address %#x\n", vaddr);
}
} }
#endif #endif

View file

@ -47,6 +47,7 @@
#include "mem/translating_port.hh" #include "mem/translating_port.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
#include "sim/process.hh" #include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/stats.hh" #include "sim/stats.hh"
#include "sim/syscall_emul.hh" #include "sim/syscall_emul.hh"
#include "sim/system.hh" #include "sim/system.hh"
@ -182,7 +183,8 @@ Process::startup()
Port *mem_port; Port *mem_port;
mem_port = system->physmem->getPort("functional"); 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); mem_port->setPeer(initVirtMem);
initVirtMem->setPeer(mem_port); initVirtMem->setPeer(mem_port);
} }
@ -250,6 +252,29 @@ Process::sim_fd(int tgt_fd)
return fd_map[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 void
Process::serialize(std::ostream &os) Process::serialize(std::ostream &os)
{ {

View file

@ -45,7 +45,6 @@
#include <vector> #include <vector>
#include "base/statistics.hh" #include "base/statistics.hh"
#include "mem/translating_port.hh"
#include "sim/host.hh" #include "sim/host.hh"
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
@ -60,28 +59,6 @@ namespace TheISA
class RemoteGDB; 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 class Process : public SimObject
{ {
public: public:
@ -194,6 +171,10 @@ class Process : public SimObject
virtual void syscall(int64_t callnum, ThreadContext *tc) = 0; 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 serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section); void unserialize(Checkpoint *cp, const std::string &section);
}; };

75
src/sim/process_impl.hh Normal file
View file

@ -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