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 "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "sim/process_impl.hh"
#include "mem/translating_port.hh"
#include "sim/system.hh"

View 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;

View 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);

View file

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

View file

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

View 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

View 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)
{

View 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);
};

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