Brandon Potter has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/12306
Change subject: syscall_emul: move members of Process to MemState
......................................................................
syscall_emul: move members of Process to MemState
This changeset moves memory-related functionality from the
Process class to the MemState class. The goal is to create
an object to manage the memory for Syscall Emulation Mode;
ideally, that object has as much cohesion as possible.
Change-Id: I5e6afecbd47e9c46998c4d6a1091d1f4fb698a71
---
M src/arch/alpha/faults.cc
M src/arch/alpha/process.cc
M src/arch/alpha/process.hh
M src/arch/arm/linux/process.cc
M src/arch/arm/process.cc
M src/arch/arm/remote_gdb.cc
M src/arch/arm/tlb.cc
M src/arch/generic/tlb.cc
M src/arch/mips/process.cc
M src/arch/mips/remote_gdb.cc
M src/arch/mips/tlb.cc
M src/arch/power/process.cc
M src/arch/power/remote_gdb.cc
M src/arch/power/tlb.cc
M src/arch/riscv/process.cc
M src/arch/riscv/process.hh
M src/arch/riscv/remote_gdb.cc
M src/arch/riscv/tlb.cc
M src/arch/sparc/faults.cc
M src/arch/sparc/process.cc
M src/arch/sparc/process.hh
M src/arch/sparc/remote_gdb.cc
M src/arch/x86/process.cc
M src/arch/x86/process.hh
M src/arch/x86/remote_gdb.cc
M src/arch/x86/tlb.cc
M src/cpu/thread_context.hh
M src/gpu-compute/compute_unit.cc
M src/gpu-compute/gpu_tlb.cc
M src/gpu-compute/shader.cc
M src/mem/se_translating_port_proxy.cc
M src/mem/se_translating_port_proxy.hh
M src/sim/SConscript
M src/sim/faults.cc
A src/sim/mem_state.cc
M src/sim/mem_state.hh
R src/sim/mem_state_impl.hh
M src/sim/process.cc
M src/sim/process.hh
M src/sim/syscall_emul.hh
40 files changed, 893 insertions(+), 386 deletions(-)
diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc
index 3433844..38c886f 100644
--- a/src/arch/alpha/faults.cc
+++ b/src/arch/alpha/faults.cc
@@ -196,11 +196,12 @@
}
Process *p = tc->getProcessPtr();
- const EmulationPageTable::Entry *pte = p->pTable->lookup(pc);
+ auto mem_state = p->memState;
+ const EmulationPageTable::Entry *pte = mem_state->_pTable->lookup(pc);
panic_if(!pte, "Tried to execute unmapped address %#x.\n", pc);
VAddr vaddr(pc);
- TlbEntry entry(p->pTable->pid(), vaddr.page(), pte->paddr,
+ TlbEntry entry(mem_state->_pTable->pid(), vaddr.page(), pte->paddr,
pte->flags & EmulationPageTable::Uncacheable,
pte->flags & EmulationPageTable::ReadOnly);
dynamic_cast<TLB *>(tc->getITBPtr())->insert(vaddr.page(), entry);
@@ -215,11 +216,10 @@
}
Process *p = tc->getProcessPtr();
- const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr);
- if (!pte && p->fixupStackFault(vaddr))
- pte = p->pTable->lookup(vaddr);
+ auto mem_state = p->memState;
+ const EmulationPageTable::Entry *pte = mem_state->lookup(vaddr);
panic_if(!pte, "Tried to access unmapped address %#x.\n", (Addr)vaddr);
- TlbEntry entry(p->pTable->pid(), vaddr.page(), pte->paddr,
+ TlbEntry entry(mem_state->_pTable->pid(), vaddr.page(), pte->paddr,
pte->flags & EmulationPageTable::Uncacheable,
pte->flags & EmulationPageTable::ReadOnly);
dynamic_cast<TLB *>(tc->getDTBPtr())->insert(vaddr.page(), entry);
diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc
index 98931a6..bc7c974 100644
--- a/src/arch/alpha/process.cc
+++ b/src/arch/alpha/process.cc
@@ -41,7 +41,7 @@
#include "params/Process.hh"
#include "sim/aux_vector.hh"
#include "sim/byteswap.hh"
-#include "sim/process_impl.hh"
+#include "sim/mem_state_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"
@@ -49,11 +49,8 @@
using namespace std;
AlphaProcess::AlphaProcess(ProcessParams *params, ObjectFile *objFile)
- : Process(params,
- new EmulationPageTable(params->name, params->pid, PageBytes),
- objFile)
+ : Process(params, objFile)
{
- fatal_if(params->useArchPT, "Arch page tables not implemented.");
Addr brk_point = objFile->dataBase() + objFile->dataSize() +
objFile->bssSize();
brk_point = roundUp(brk_point, PageBytes);
@@ -70,8 +67,11 @@
// Set pointer for next thread stack. Reserve 8M for main stack.
Addr next_thread_stack_base = stack_base - max_stack_size;
- memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
- next_thread_stack_base, mmap_end);
+ auto p_table = make_shared<EmulationPageTable>(params->name,
params->pid,
+ PageBytes);
+ memState = make_shared<MemState>(this, brk_point, stack_base,
+ max_stack_size,
next_thread_stack_base,
+ mmap_end, params->system, p_table);
}
void
@@ -145,8 +145,9 @@
memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
memState->setStackSize(memState->getStackBase() -
memState->getStackMin());
// map memory
- allocateMem(memState->getStackMin(), roundUp(memState->getStackSize(),
- pageSize));
+ memState->allocateMem(memState->getStackMin(),
+ roundUp(memState->getStackSize(), pageSize)
+ -1, 0);
// map out initial stack contents
Addr argv_array_base = memState->getStackMin() + intSize; // room for
argc
diff --git a/src/arch/alpha/process.hh b/src/arch/alpha/process.hh
index 28ecd68..5003fab 100644
--- a/src/arch/alpha/process.hh
+++ b/src/arch/alpha/process.hh
@@ -55,10 +55,6 @@
void setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val)
override;
void setSyscallReturn(ThreadContext *tc,
SyscallReturn return_value) override;
-
- // override default implementation in Process as the mmap
- // region for Alpha platforms grows upward
- virtual bool mmapGrowsDown() const override { return false; }
};
#endif // __ARCH_ALPHA_PROCESS_HH__
diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc
index d271364..abbac72 100644
--- a/src/arch/arm/linux/process.cc
+++ b/src/arch/arm/linux/process.cc
@@ -1674,8 +1674,8 @@
ArmLinuxProcess32::initState()
{
ArmProcess32::initState();
- allocateMem(commPage, PageBytes);
- ThreadContext *tc = system->getThreadContext(contextIds[0]);
+
+ memState->allocateMem(commPage, PageBytes);
uint8_t swiNeg1[] = {
0xff, 0xff, 0xff, 0xef // swi -1
diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc
index 3a7e46b..4d6f468 100644
--- a/src/arch/arm/process.cc
+++ b/src/arch/arm/process.cc
@@ -54,7 +54,7 @@
#include "params/Process.hh"
#include "sim/aux_vector.hh"
#include "sim/byteswap.hh"
-#include "sim/process_impl.hh"
+#include "sim/mem_state_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"
@@ -63,12 +63,9 @@
ArmProcess::ArmProcess(ProcessParams *params, ObjectFile *objFile,
ObjectFile::Arch _arch)
- : Process(params,
- new EmulationPageTable(params->name, params->pid, PageBytes),
- objFile),
+ : Process(params, objFile),
arch(_arch)
{
- fatal_if(params->useArchPT, "Arch page tables not implemented.");
}
ArmProcess32::ArmProcess32(ProcessParams *params, ObjectFile *objFile,
@@ -82,8 +79,11 @@
Addr next_thread_stack_base = stack_base - max_stack_size;
Addr mmap_end = 0x40000000L;
- memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
- next_thread_stack_base, mmap_end);
+ auto p_table = make_shared<EmulationPageTable>(params->name,
params->pid,
+ PageBytes);
+ memState = make_shared<MemState>(this, brk_point, stack_base,
+ max_stack_size,
next_thread_stack_base,
+ mmap_end, params->system, p_table);
}
ArmProcess64::ArmProcess64(ProcessParams *params, ObjectFile *objFile,
@@ -97,8 +97,11 @@
Addr next_thread_stack_base = stack_base - max_stack_size;
Addr mmap_end = 0x4000000000L;
- memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
- next_thread_stack_base, mmap_end);
+ auto p_table = make_shared<EmulationPageTable>(params->name,
params->pid,
+ PageBytes);
+ memState = make_shared<MemState>(this, brk_point, stack_base,
+ max_stack_size,
next_thread_stack_base,
+ mmap_end, params->system, p_table);
}
void
@@ -293,7 +296,7 @@
memState->setStackSize(memState->getStackBase() -
memState->getStackMin());
// map memory
- allocateMem(roundDown(memState->getStackMin(), pageSize),
+ memState->allocateMem(roundDown(memState->getStackMin(), pageSize),
roundUp(memState->getStackSize(), pageSize));
// map out initial stack contents
diff --git a/src/arch/arm/remote_gdb.cc b/src/arch/arm/remote_gdb.cc
index f191937..5ade136 100644
--- a/src/arch/arm/remote_gdb.cc
+++ b/src/arch/arm/remote_gdb.cc
@@ -186,9 +186,11 @@
DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
return true;
} else {
- // Check to make sure the first byte is mapped into the processes
- // address space.
- return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
+ // Check if the virtual address is valid and map a physical page
if it
+ // hasn't been already
+ auto process = context()->getProcessPtr();
+ auto mem_state = process->memState;
+ return mem_state->translate(va);
}
}
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 79eef1b..26b482d 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -593,8 +593,9 @@
Addr paddr;
Process *p = tc->getProcessPtr();
+ auto mem_state = p->memState;
- if (!p->pTable->translate(vaddr, paddr))
+ if (!mem_state->_pTable->translate(vaddr, paddr))
return std::make_shared<GenericPageTableFault>(vaddr_tainted);
req->setPaddr(paddr);
diff --git a/src/arch/generic/tlb.cc b/src/arch/generic/tlb.cc
index aebdd4b..a5dd858 100644
--- a/src/arch/generic/tlb.cc
+++ b/src/arch/generic/tlb.cc
@@ -42,9 +42,11 @@
if (FullSystem)
panic("Generic translation shouldn't be used in full system
mode.\n");
- Process * p = tc->getProcessPtr();
+ auto p = tc->getProcessPtr();
+ auto mem_state = p->memState;
+ auto p_table = mem_state->_pTable;
- Fault fault = p->pTable->translate(req);
+ Fault fault = p_table->translate(req);
if (fault != NoFault)
return fault;
diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc
index 32c58ae..37831a4 100644
--- a/src/arch/mips/process.cc
+++ b/src/arch/mips/process.cc
@@ -41,8 +41,8 @@
#include "mem/page_table.hh"
#include "params/Process.hh"
#include "sim/aux_vector.hh"
+#include "sim/mem_state_impl.hh"
#include "sim/process.hh"
-#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"
@@ -50,11 +50,8 @@
using namespace MipsISA;
MipsProcess::MipsProcess(ProcessParams *params, ObjectFile *objFile)
- : Process(params,
- new EmulationPageTable(params->name, params->pid, PageBytes),
- objFile)
+ : Process(params, objFile)
{
- fatal_if(params->useArchPT, "Arch page tables not implemented.");
// Set up stack. On MIPS, stack starts at the top of kuseg
// user address space. MIPS stack grows down from here
Addr stack_base = 0x7FFFFFFF;
@@ -72,8 +69,11 @@
// Set up region for mmaps. Start it 1GB above the top of the heap.
Addr mmap_end = brk_point + 0x40000000L;
- memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
- next_thread_stack_base, mmap_end);
+ auto p_table = make_shared<EmulationPageTable>(params->name,
params->pid,
+ PageBytes);
+ memState = make_shared<MemState>(this, brk_point, stack_base,
+ max_stack_size,
next_thread_stack_base,
+ mmap_end, params->system, p_table);
}
void
@@ -157,8 +157,8 @@
memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
memState->setStackSize(memState->getStackBase() -
memState->getStackMin());
// map memory
- allocateMem(memState->getStackMin(), roundUp(memState->getStackSize(),
- pageSize));
+ memState->allocateMem(memState->getStackMin(),
+ roundUp(memState->getStackSize(), pageSize));
// map out initial stack contents; leave room for argc
IntType argv_array_base = memState->getStackMin() + intSize;
diff --git a/src/arch/mips/remote_gdb.cc b/src/arch/mips/remote_gdb.cc
index d490fa5..37c3d66 100644
--- a/src/arch/mips/remote_gdb.cc
+++ b/src/arch/mips/remote_gdb.cc
@@ -162,10 +162,12 @@
bool
RemoteGDB::acc(Addr va, size_t len)
{
- // Check to make sure the first byte is mapped into the processes
address
- // space.
+ // Check if the virtual address is valid and map a physical page if it
+ // hasn't been already
panic_if(FullSystem, "acc not implemented for MIPS FS!");
- return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
+ auto process = context()->getProcessPtr();
+ auto mem_state = process->memState;
+ return mem_state->translate(va);
}
void
diff --git a/src/arch/mips/tlb.cc b/src/arch/mips/tlb.cc
index 46e250b..34845a5 100644
--- a/src/arch/mips/tlb.cc
+++ b/src/arch/mips/tlb.cc
@@ -288,8 +288,9 @@
panic("translateInst not implemented in MIPS.\n");
Process * p = tc->getProcessPtr();
+ auto mem_state = p->memState;
- Fault fault = p->pTable->translate(req);
+ Fault fault = mem_state->_pTable->translate(req);
if (fault != NoFault)
return fault;
@@ -302,9 +303,9 @@
if (FullSystem)
panic("translateData not implemented in MIPS.\n");
- Process * p = tc->getProcessPtr();
-
- Fault fault = p->pTable->translate(req);
+ auto p = tc->getProcessPtr();
+ auto mem_state = p->memState;
+ Fault fault = mem_state->_pTable->translate(req);
if (fault != NoFault)
return fault;
diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc
index d02e20b..d52246a 100644
--- a/src/arch/power/process.cc
+++ b/src/arch/power/process.cc
@@ -42,7 +42,7 @@
#include "mem/page_table.hh"
#include "params/Process.hh"
#include "sim/aux_vector.hh"
-#include "sim/process_impl.hh"
+#include "sim/mem_state_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"
@@ -50,11 +50,8 @@
using namespace PowerISA;
PowerProcess::PowerProcess(ProcessParams *params, ObjectFile *objFile)
- : Process(params,
- new EmulationPageTable(params->name, params->pid, PageBytes),
- objFile)
+ : Process(params, objFile)
{
- fatal_if(params->useArchPT, "Arch page tables not implemented.");
// Set up break point (Top of Heap)
Addr brk_point = objFile->dataBase() + objFile->dataSize() +
objFile->bssSize();
@@ -70,8 +67,11 @@
// Set up region for mmaps. For now, start at bottom of kuseg space.
Addr mmap_end = 0x70000000L;
- memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
- next_thread_stack_base, mmap_end);
+ auto p_table = make_shared<EmulationPageTable>(params->name,
params->pid,
+ PageBytes);
+ memState = make_shared<MemState>(this, brk_point, stack_base,
+ max_stack_size,
next_thread_stack_base,
+ mmap_end, params->system, p_table);
}
void
@@ -203,8 +203,8 @@
memState->setStackSize(memState->getStackBase() - stack_min);
// map memory
- allocateMem(roundDown(stack_min, pageSize),
- roundUp(memState->getStackSize(), pageSize));
+ memState->allocateMem(roundDown(stack_min, pageSize),
+ roundUp(memState->getStackSize(), pageSize));
// map out initial stack contents
uint32_t sentry_base = memState->getStackBase() - sentry_size;
diff --git a/src/arch/power/remote_gdb.cc b/src/arch/power/remote_gdb.cc
index b4082e0..78babd2 100644
--- a/src/arch/power/remote_gdb.cc
+++ b/src/arch/power/remote_gdb.cc
@@ -168,7 +168,9 @@
// port proxy to read/writeBlob. I (bgs) am not convinced the first
byte
// check is enough.
panic_if(FullSystem, "acc not implemented for POWER FS!");
- return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
+ auto process = context()->getProcessPtr();
+ auto mem_state = process->memState;
+ return mem_state->translate(va);
}
void
diff --git a/src/arch/power/tlb.cc b/src/arch/power/tlb.cc
index 703b92e..2f39a02 100644
--- a/src/arch/power/tlb.cc
+++ b/src/arch/power/tlb.cc
@@ -288,9 +288,9 @@
return std::make_shared<AlignmentFault>();
}
- Process * p = tc->getProcessPtr();
-
- Fault fault = p->pTable->translate(req);
+ auto p = tc->getProcessPtr();
+ auto mem_state = p->memState;
+ Fault fault = mem_state->_pTable->translate(req);
if (fault != NoFault)
return fault;
@@ -301,8 +301,9 @@
TLB::translateData(const RequestPtr &req, ThreadContext *tc, bool write)
{
Process * p = tc->getProcessPtr();
+ auto mem_state = p->memState;
- Fault fault = p->pTable->translate(req);
+ Fault fault = mem_state->_pTable->translate(req);
if (fault != NoFault)
return fault;
diff --git a/src/arch/riscv/process.cc b/src/arch/riscv/process.cc
index 08ab436..a1f0b42 100644
--- a/src/arch/riscv/process.cc
+++ b/src/arch/riscv/process.cc
@@ -53,8 +53,8 @@
#include "mem/page_table.hh"
#include "params/Process.hh"
#include "sim/aux_vector.hh"
+#include "sim/mem_state_impl.hh"
#include "sim/process.hh"
-#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"
@@ -62,19 +62,19 @@
using namespace RiscvISA;
RiscvProcess::RiscvProcess(ProcessParams *params, ObjectFile *objFile) :
- Process(params,
- new EmulationPageTable(params->name, params->pid,
PageBytes),
- objFile)
+ Process(params, objFile)
{
- fatal_if(params->useArchPT, "Arch page tables not implemented.");
const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
const Addr max_stack_size = 8 * 1024 * 1024;
const Addr next_thread_stack_base = stack_base - max_stack_size;
const Addr brk_point = roundUp(objFile->bssBase() + objFile->bssSize(),
PageBytes);
const Addr mmap_end = 0x4000000000000000L;
- memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
- next_thread_stack_base, mmap_end);
+ auto p_table = make_shared<EmulationPageTable>(params->name,
params->pid,
+ PageBytes);
+ memState = make_shared<MemState>(this, brk_point, stack_base,
+ max_stack_size,
next_thread_stack_base,
+ mmap_end, params->system, p_table);
}
void
@@ -123,8 +123,8 @@
sizeof(Addr) + 2 * sizeof(IntType) * auxv.size();
stack_top &= -2*sizeof(Addr);
memState->setStackSize(memState->getStackBase() - stack_top);
- allocateMem(roundDown(stack_top, pageSize),
- roundUp(memState->getStackSize(), pageSize));
+ memState->allocateMem(roundDown(stack_top, pageSize),
+ roundUp(memState->getStackSize(), pageSize));
// Copy random bytes (for AT_RANDOM) to stack
memState->setStackMin(memState->getStackMin() - RandomBytes);
diff --git a/src/arch/riscv/process.hh b/src/arch/riscv/process.hh
index bda278e..afc2ad5 100644
--- a/src/arch/riscv/process.hh
+++ b/src/arch/riscv/process.hh
@@ -61,8 +61,6 @@
RiscvISA::IntReg val) override;
void setSyscallReturn(ThreadContext *tc,
SyscallReturn return_value) override;
-
- virtual bool mmapGrowsDown() const override { return false; }
};
#endif // __RISCV_PROCESS_HH__
diff --git a/src/arch/riscv/remote_gdb.cc b/src/arch/riscv/remote_gdb.cc
index 6d56a93..3ba5b14 100644
--- a/src/arch/riscv/remote_gdb.cc
+++ b/src/arch/riscv/remote_gdb.cc
@@ -157,7 +157,9 @@
RemoteGDB::acc(Addr va, size_t len)
{
panic_if(FullSystem, "acc not implemented for RISCV FS!");
- return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
+ auto process = context()->getProcessPtr();
+ auto mem_state = process->memState;
+ return mem_state->translate(va);
}
void
diff --git a/src/arch/riscv/tlb.cc b/src/arch/riscv/tlb.cc
index 494ec4c..c1cfcd0 100644
--- a/src/arch/riscv/tlb.cc
+++ b/src/arch/riscv/tlb.cc
@@ -309,8 +309,9 @@
}
} else {
Process * p = tc->getProcessPtr();
+ auto mem_state = p->memState;
- Fault fault = p->pTable->translate(req);
+ Fault fault = mem_state->_pTable->translate(req);
if (fault != NoFault)
return fault;
@@ -355,8 +356,9 @@
return make_shared<GenericPageTableFault>(req->getVaddr());
Process * p = tc->getProcessPtr();
+ auto mem_state = p->memState;
- Fault fault = p->pTable->translate(req);
+ Fault fault = mem_state->_pTable->translate(req);
if (fault != NoFault)
return fault;
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc
index 6375fa5..018cf0a 100644
--- a/src/arch/sparc/faults.cc
+++ b/src/arch/sparc/faults.cc
@@ -630,10 +630,11 @@
}
Process *p = tc->getProcessPtr();
- const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr);
+ auto mem_state = p->memState;
+ const EmulationPageTable::Entry *pte =
mem_state->_pTable->lookup(vaddr);
panic_if(!pte, "Tried to execute unmapped address %#x.\n", vaddr);
- Addr alignedvaddr = p->pTable->pageAlign(vaddr);
+ Addr alignedvaddr = mem_state->_pTable->pageAlign(vaddr);
// Grab fields used during instruction translation to figure out
// which context to use.
@@ -663,7 +664,7 @@
// the logic works out to the following for the context.
int context_id = (is_real_address || trapped) ? 0 : primary_context;
- TlbEntry entry(p->pTable->pid(), alignedvaddr, pte->paddr,
+ TlbEntry entry(mem_state->_pTable->pid(), alignedvaddr, pte->paddr,
pte->flags & EmulationPageTable::Uncacheable,
pte->flags & EmulationPageTable::ReadOnly);
@@ -685,12 +686,11 @@
}
Process *p = tc->getProcessPtr();
- const EmulationPageTable::Entry *pte = p->pTable->lookup(vaddr);
- if (!pte && p->fixupStackFault(vaddr))
- pte = p->pTable->lookup(vaddr);
+ auto mem_state = p->memState;
+ const EmulationPageTable::Entry *pte = mem_state->lookup(vaddr);
panic_if(!pte, "Tried to access unmapped address %#x.\n", vaddr);
- Addr alignedvaddr = p->pTable->pageAlign(vaddr);
+ Addr alignedvaddr = mem_state->_pTable->pageAlign(vaddr);
// Grab fields used during data translation to figure out
// which context to use.
@@ -750,7 +750,7 @@
// The partition id distinguishes between virtualized environments.
int const partition_id = 0;
- TlbEntry entry(p->pTable->pid(), alignedvaddr, pte->paddr,
+ TlbEntry entry(mem_state->_pTable->pid(), alignedvaddr, pte->paddr,
pte->flags & EmulationPageTable::Uncacheable,
pte->flags & EmulationPageTable::ReadOnly);
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index c98c9b7..68c4b22 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -44,7 +44,7 @@
#include "mem/page_table.hh"
#include "params/Process.hh"
#include "sim/aux_vector.hh"
-#include "sim/process_impl.hh"
+#include "sim/mem_state_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"
@@ -56,12 +56,9 @@
SparcProcess::SparcProcess(ProcessParams *params, ObjectFile *objFile,
Addr _StackBias)
- : Process(params,
- new EmulationPageTable(params->name, params->pid, PageBytes),
- objFile),
+ : Process(params, objFile),
StackBias(_StackBias)
{
- fatal_if(params->useArchPT, "Arch page tables not implemented.");
// Initialize these to 0s
fillStart = 0;
spillStart = 0;
@@ -328,8 +325,8 @@
memState->setStackSize(memState->getStackBase() -
memState->getStackMin());
// Allocate space for the stack
- allocateMem(roundDown(memState->getStackMin(), pageSize),
- roundUp(memState->getStackSize(), pageSize));
+ memState->allocateMem(roundDown(memState->getStackMin(), pageSize),
+ roundUp(memState->getStackSize(), pageSize));
// map out initial stack contents
IntType sentry_base = memState->getStackBase() - sentry_size;
diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh
index d7e0967..10a89e9 100644
--- a/src/arch/sparc/process.hh
+++ b/src/arch/sparc/process.hh
@@ -39,6 +39,7 @@
#include "arch/sparc/isa_traits.hh"
#include "base/loader/object_file.hh"
#include "mem/page_table.hh"
+#include "params/Process.hh"
#include "sim/byteswap.hh"
#include "sim/process.hh"
@@ -95,10 +96,14 @@
// Set up region for mmaps.
Addr mmap_end = 0x70000000;
- memState = std::make_shared<MemState>(brk_point, stack_base,
+ auto p_table = std::make_shared<EmulationPageTable>(params->name,
+ params->pid,
+
SparcISA::PageBytes);
+ memState = std::make_shared<MemState>(this, brk_point, stack_base,
max_stack_size,
next_thread_stack_base,
- mmap_end);
+ mmap_end, params->system,
+ p_table);
}
void initState();
@@ -139,10 +144,14 @@
// Set up region for mmaps.
Addr mmap_end = 0xfffff80000000000ULL;
- memState = std::make_shared<MemState>(brk_point, stack_base,
+ auto p_table = std::make_shared<EmulationPageTable>(params->name,
+ params->pid,
+
SparcISA::PageBytes);
+ memState = std::make_shared<MemState>(this, brk_point, stack_base,
max_stack_size,
next_thread_stack_base,
- mmap_end);
+ mmap_end, params->system,
+ p_table);
}
void initState();
diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc
index 057cea1..c4b96dc 100644
--- a/src/arch/sparc/remote_gdb.cc
+++ b/src/arch/sparc/remote_gdb.cc
@@ -167,7 +167,9 @@
} else {
// Check to make sure the first byte is mapped into the processes
// address space.
- return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
+ auto process = context()->getProcessPtr();
+ auto mem_state = process->memState;
+ return mem_state->translate(va);
}
}
diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index f5fccf0..a19ec43 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -62,7 +62,7 @@
#include "mem/page_table.hh"
#include "params/Process.hh"
#include "sim/aux_vector.hh"
-#include "sim/process_impl.hh"
+#include "sim/mem_state_impl.hh"
#include "sim/syscall_desc.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"
@@ -107,14 +107,8 @@
X86Process::X86Process(ProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs)
- : Process(params, params->useArchPT ?
- static_cast<EmulationPageTable *>(
- new ArchPageTable(params->name, params->pid,
- params->system,
PageBytes)) :
- new EmulationPageTable(params->name, params->pid,
- PageBytes),
- objFile),
- syscallDescs(_syscallDescs), numSyscallDescs(_numSyscallDescs)
+ : Process(params, objFile), syscallDescs(_syscallDescs),
+ numSyscallDescs(_numSyscallDescs)
{
}
@@ -143,8 +137,20 @@
Addr next_thread_stack_base = stack_base - max_stack_size;
Addr mmap_end = 0x7FFFF7FFF000ULL;
- memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
- next_thread_stack_base, mmap_end);
+ auto p_table = params->useArchPT ?
+ static_pointer_cast<EmulationPageTable>(
+ make_shared<ArchPageTable>(params->name,
params->pid,
+ params->system,
PageBytes)) :
+ make_shared<EmulationPageTable>(params->name,
params->pid,
+ PageBytes);
+ memState = make_shared<MemState>(this, brk_point, stack_base,
+ max_stack_size,
next_thread_stack_base,
+ mmap_end, params->system, p_table);
+}
+
+void
+X86_64Process::init()
+{
}
void
@@ -180,8 +186,15 @@
Addr next_thread_stack_base = stack_base - max_stack_size;
Addr mmap_end = 0xB7FFF000ULL;
- memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
- next_thread_stack_base, mmap_end);
+ auto p_table = params->useArchPT ?
+ static_pointer_cast<EmulationPageTable>(
+ make_shared<ArchPageTable>(params->name,
params->pid,
+ params->system,
PageBytes)) :
+ make_shared<EmulationPageTable>(params->name,
params->pid,
+ PageBytes);
+ memState = make_shared<MemState>(this, brk_point, stack_base,
+ max_stack_size,
next_thread_stack_base,
+ mmap_end, params->system, p_table);
}
SyscallDesc*
@@ -199,8 +212,11 @@
argsInit(PageBytes);
+ auto p_table = memState->_pTable;
+
// Set up the vsyscall page for this process.
- allocateMem(vsyscallPage.base, vsyscallPage.size);
+ memState->mapVMARegion(vsyscallPage.base, vsyscallPage.size, -1, 0);
+ const auto &virt_mem = memState->getVirtMem();
uint8_t vtimeBlob[] = {
0x48,0xc7,0xc0,0xc9,0x00,0x00,0x00, // mov $0xc9,%rax
0x0f,0x05, // syscall
@@ -410,7 +426,7 @@
CR0 cr2 = 0;
tc->setMiscReg(MISCREG_CR2, cr2);
- CR3 cr3 = dynamic_cast<ArchPageTable *>(pTable)->basePtr();
+ CR3 cr3 =
dynamic_pointer_cast<ArchPageTable>(p_table)->basePtr();
tc->setMiscReg(MISCREG_CR3, cr3);
CR4 cr4 = 0;
@@ -543,21 +559,21 @@
physProxy.writeBlob(pfHandlerPhysAddr, faultBlob,
sizeof(faultBlob));
/* Syscall handler */
- pTable->map(syscallCodeVirtAddr, syscallCodePhysAddr,
- PageBytes, false);
+ p_table->map(syscallCodeVirtAddr, syscallCodePhysAddr,
+ PageBytes, false);
/* GDT */
- pTable->map(GDTVirtAddr, gdtPhysAddr, PageBytes, false);
+ p_table->map(GDTVirtAddr, gdtPhysAddr, PageBytes, false);
/* IDT */
- pTable->map(IDTVirtAddr, idtPhysAddr, PageBytes, false);
+ p_table->map(IDTVirtAddr, idtPhysAddr, PageBytes, false);
/* TSS */
- pTable->map(TSSVirtAddr, tssPhysAddr, PageBytes, false);
+ p_table->map(TSSVirtAddr, tssPhysAddr, PageBytes, false);
/* IST */
- pTable->map(ISTVirtAddr, istPhysAddr, PageBytes, false);
+ p_table->map(ISTVirtAddr, istPhysAddr, PageBytes, false);
/* PF handler */
- pTable->map(PFHandlerVirtAddr, pfHandlerPhysAddr, PageBytes,
false);
+ p_table->map(PFHandlerVirtAddr, pfHandlerPhysAddr, PageBytes,
false);
/* MMIO region for m5ops */
- pTable->map(MMIORegionVirtAddr, MMIORegionPhysAddr,
- 16 * PageBytes, false);
+ p_table->map(MMIORegionVirtAddr, MMIORegionPhysAddr,
+ 16 * PageBytes, false);
} else {
for (int i = 0; i < contextIds.size(); i++) {
ThreadContext * tc = system->getThreadContext(contextIds[i]);
@@ -641,7 +657,8 @@
* Set up a GDT for this process. The whole GDT wouldn't really be for
* this process, but the only parts we care about are.
*/
- allocateMem(_gdtStart, _gdtSize);
+ memState->allocateMem(_gdtStart, _gdtSize);
+ const auto &virt_mem = memState->getVirtMem();
uint64_t zero = 0;
assert(_gdtSize % sizeof(zero) == 0);
for (Addr gdtCurrent = _gdtStart;
@@ -650,7 +667,7 @@
}
// Set up the vsyscall page for this process.
- allocateMem(vsyscallPage.base, vsyscallPage.size);
+ memState->allocateMem(vsyscallPage.base, vsyscallPage.size);
uint8_t vsyscallBlob[] = {
0x51, // push %ecx
0x52, // push %edp
@@ -955,15 +972,17 @@
Addr stack_min = stack_base - space_needed;
stack_min = roundDown(stack_min, align);
- unsigned stack_size = stack_base - stack_min;
- stack_size = roundUp(stack_size, pageSize);
- memState->setStackSize(stack_size);
+ /**
+ * Map the maximum stack area as valid to make things easier to
maintain.
+ * Keep in mind that the stack grows downward so the mapping looks
+ * backwards here.
+ */
+ Addr max_stack_size = memState->getMaxStackSize();
+ Addr stack_end = roundDown(stack_base - max_stack_size, pageSize);
- // map memory
- Addr stack_end = roundDown(stack_base - stack_size, pageSize);
+ memState->mapVMARegion(stack_end, max_stack_size, -1, 0);
- DPRINTF(Stack, "Mapping the stack: 0x%x %dB\n", stack_end, stack_size);
- allocateMem(stack_end, stack_size);
+ DPRINTF(Stack, "Mapping the stack: 0x%x %dB\n", stack_end,
max_stack_size);
// map out initial stack contents
IntType sentry_base = stack_base - sentry_size;
@@ -1037,9 +1056,6 @@
// There doesn't need to be any segment base added in since we're
dealing
// with the flat segmentation model.
tc->pcState(getStartPC());
-
- // Align the "stack_min" to a page boundary.
- memState->setStackMin(roundDown(stack_min, pageSize));
}
void
diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh
index b9052c4..53eabe0 100644
--- a/src/arch/x86/process.hh
+++ b/src/arch/x86/process.hh
@@ -132,6 +132,7 @@
VSyscallPage vsyscallPage;
public:
+ void init() override;
void argsInit(int pageSize);
void initState() override;
diff --git a/src/arch/x86/remote_gdb.cc b/src/arch/x86/remote_gdb.cc
index 9564593..5d4ea4f 100644
--- a/src/arch/x86/remote_gdb.cc
+++ b/src/arch/x86/remote_gdb.cc
@@ -88,7 +88,11 @@
BaseTLB::Read);
return fault == NoFault;
} else {
- return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
+ // Check if the virtual address is valid and map a physical page
if it
+ // hasn't been already
+ auto process = context()->getProcessPtr();
+ auto mem_state = process->memState;
+ return mem_state->translate(va);
}
}
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index 8e83208..b4bc66a 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -231,7 +231,7 @@
AddrRange m5opRange(0xFFFF0000, 0xFFFFFFFF);
- if (m5opRange.contains(paddr)) {
+ if (!FullSystem && m5opRange.contains(paddr)) {
req->setFlags(Request::MMAPPED_IPR | Request::GENERIC_IPR |
Request::STRICT_ORDER);
req->setPaddr(GenericISA::iprAddressPseudoInst((paddr >> 8) & 0xFF,
@@ -358,25 +358,24 @@
entry = lookup(vaddr);
assert(entry);
} else {
- Process *p = tc->getProcessPtr();
+ DPRINTF(TLB, "Handling a TLB miss for "
+ "address %#x at pc %#x.\n",
+ vaddr, tc->instAddr());
+
+ auto p = tc->getProcessPtr();
+ auto mem_state = p->memState;
const EmulationPageTable::Entry *pte =
- p->pTable->lookup(vaddr);
- if (!pte && mode != Execute) {
- // Check if we just need to grow the stack.
- if (p->fixupStackFault(vaddr)) {
- // If we did, lookup the entry for the new
page.
- pte = p->pTable->lookup(vaddr);
- }
- }
+ mem_state->lookup(vaddr);
if (!pte) {
return std::make_shared<PageFault>(vaddr, true,
mode,
true, false);
} else {
- Addr alignedVaddr = p->pTable->pageAlign(vaddr);
+ Addr alignedVaddr =
+ mem_state->_pTable->pageAlign(vaddr);
DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
pte->paddr);
entry = insert(alignedVaddr, TlbEntry(
- p->pTable->pid(), alignedVaddr, pte->paddr,
+ p->pid(), alignedVaddr, pte->paddr,
pte->flags &
EmulationPageTable::Uncacheable,
pte->flags &
EmulationPageTable::ReadOnly));
}
diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh
index 1c534a1..b4a037d 100644
--- a/src/cpu/thread_context.hh
+++ b/src/cpu/thread_context.hh
@@ -47,6 +47,7 @@
#include <iostream>
#include <string>
+#include "arch/generic/tlb.hh"
#include "arch/registers.hh"
#include "arch/types.hh"
#include "base/types.hh"
@@ -60,7 +61,6 @@
class Decoder;
}
class BaseCPU;
-class BaseTLB;
class CheckerCPU;
class Checkpoint;
class EndQuiesceEvent;
diff --git a/src/gpu-compute/compute_unit.cc
b/src/gpu-compute/compute_unit.cc
index fd328ad..158ae64 100644
--- a/src/gpu-compute/compute_unit.cc
+++ b/src/gpu-compute/compute_unit.cc
@@ -784,12 +784,10 @@
Addr paddr;
- if (!p->pTable->translate(vaddr, paddr)) {
- if (!p->fixupStackFault(vaddr)) {
+ if (!p->memState->translate(vaddr, paddr)) {
panic("CU%d: WF[%d][%d]: Fault on addr %#x!\n",
cu_id, gpuDynInst->simdId, gpuDynInst->wfSlotId,
vaddr);
- }
}
}
diff --git a/src/gpu-compute/gpu_tlb.cc b/src/gpu-compute/gpu_tlb.cc
index fea6183..9e116af 100644
--- a/src/gpu-compute/gpu_tlb.cc
+++ b/src/gpu-compute/gpu_tlb.cc
@@ -808,17 +808,19 @@
DPRINTF(GPUTLB, "Handling a TLB miss for
address %#x "
"at pc %#x.\n", vaddr, tc->instAddr());
- Process *p = tc->getProcessPtr();
+ auto p = tc->getProcessPtr();
+ auto mem_state = p->memState;
+ auto p_table = mem_state->_pTable;
const EmulationPageTable::Entry *pte =
- p->pTable->lookup(vaddr);
+ p_table->lookup(vaddr);
if (!pte && mode != BaseTLB::Execute) {
// penalize a "page fault" more
if (timing)
latency += missLatency2;
- if (p->fixupStackFault(vaddr))
- pte = p->pTable->lookup(vaddr);
+ if (mem_state->fixupFault(vaddr))
+ pte = p_table->lookup(vaddr);
}
if (!pte) {
@@ -826,7 +828,7 @@
mode, true,
false);
} else {
- Addr alignedVaddr =
p->pTable->pageAlign(vaddr);
+ Addr alignedVaddr = p_table->pageAlign(vaddr);
DPRINTF(GPUTLB, "Mapping %#x to %#x\n",
alignedVaddr, pte->paddr);
@@ -1332,17 +1334,15 @@
TranslationState *sender_state =
safe_cast<TranslationState*>(pkt->senderState);
- Process *p = sender_state->tc->getProcessPtr();
+ auto p = sender_state->tc->getProcessPtr();
+ auto mem_state = p->memState;
Addr vaddr = pkt->req->getVaddr();
#ifndef NDEBUG
- Addr alignedVaddr = p->pTable->pageAlign(vaddr);
+ auto p_table = mem_state->_pTable;
+ Addr alignedVaddr = p_table->pageAlign(vaddr);
assert(alignedVaddr == virtPageAddr);
#endif
- const EmulationPageTable::Entry *pte =
p->pTable->lookup(vaddr);
- if (!pte && sender_state->tlbMode != BaseTLB::Execute &&
- p->fixupStackFault(vaddr)) {
- pte = p->pTable->lookup(vaddr);
- }
+ const EmulationPageTable::Entry *pte =
mem_state->lookup(vaddr);
if (pte) {
DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr,
@@ -1533,20 +1533,18 @@
DPRINTF(GPUTLB, "Doing a page walk for address %#x\n",
virt_page_addr);
- Process *p = tc->getProcessPtr();
+ auto p = tc->getProcessPtr();
+ auto mem_state = p->memState;
Addr vaddr = pkt->req->getVaddr();
#ifndef NDEBUG
- Addr alignedVaddr = p->pTable->pageAlign(vaddr);
+ auto p_table = mem_state->_pTable;
+ Addr alignedVaddr = p_table->pageAlign(vaddr);
assert(alignedVaddr == virt_page_addr);
#endif
const EmulationPageTable::Entry *pte =
- p->pTable->lookup(vaddr);
- if (!pte && sender_state->tlbMode != BaseTLB::Execute &&
- p->fixupStackFault(vaddr)) {
- pte = p->pTable->lookup(vaddr);
- }
+ mem_state->lookup(vaddr);
if (!sender_state->prefetch) {
// no PageFaults are permitted after
diff --git a/src/gpu-compute/shader.cc b/src/gpu-compute/shader.cc
index d0bd41a..f3cb9ef 100644
--- a/src/gpu-compute/shader.cc
+++ b/src/gpu-compute/shader.cc
@@ -84,7 +84,7 @@
Process *proc = gpuTc->getProcessPtr();
auto mem_state = proc->memState;
- if (proc->mmapGrowsDown()) {
+ if (mem_state->mmapGrowsDown()) {
DPRINTF(HSAIL, "GROWS DOWN");
start = mem_state->getMmapEnd() - length;
mem_state->setMmapEnd(start);
@@ -100,7 +100,7 @@
DPRINTF(HSAIL,"Shader::mmap start= %#x, %#x\n", start, length);
- proc->allocateMem(start, length);
+ mem_state->allocateMem(start, length);
return start;
}
diff --git a/src/mem/se_translating_port_proxy.cc
b/src/mem/se_translating_port_proxy.cc
index bb30ffb..c0dbdcc 100644
--- a/src/mem/se_translating_port_proxy.cc
+++ b/src/mem/se_translating_port_proxy.cc
@@ -44,21 +44,22 @@
#include "mem/se_translating_port_proxy.hh"
+#include <cassert>
#include <string>
#include "arch/isa_traits.hh"
#include "base/chunk_generator.hh"
#include "config/the_isa.hh"
#include "mem/page_table.hh"
-#include "sim/process.hh"
-#include "sim/system.hh"
+#include "sim/mem_state.hh"
using namespace TheISA;
-SETranslatingPortProxy::SETranslatingPortProxy(MasterPort& port, Process
*p,
- AllocType alloc)
- : PortProxy(port, p->system->cacheLineSize()), pTable(p->pTable),
- process(p), allocating(alloc)
+SETranslatingPortProxy::SETranslatingPortProxy(MasterPort& port,
+ unsigned cache_line_size,
+ MemState *mem_state,
+ AllocType alloc)
+ : PortProxy(port, cache_line_size), _memState(mem_state),
allocating(alloc)
{ }
SETranslatingPortProxy::~SETranslatingPortProxy()
@@ -72,8 +73,8 @@
for (ChunkGenerator gen(addr, size, PageBytes); !gen.done();
gen.next()) {
Addr paddr;
- if (!pTable->translate(gen.addr(),paddr))
- return false;
+ if (!_memState->translate(gen.addr(), paddr))
+ return false;
PortProxy::readBlobPhys(paddr, 0, p + prevSize, gen.size());
prevSize += gen.size();
@@ -99,19 +100,19 @@
for (ChunkGenerator gen(addr, size, PageBytes); !gen.done();
gen.next()) {
Addr paddr;
- if (!pTable->translate(gen.addr(), paddr)) {
+ if (!_memState->translate(gen.addr(), paddr)) {
if (allocating == Always) {
- process->allocateMem(roundDown(gen.addr(), PageBytes),
- PageBytes);
- } else if (allocating == NextPage) {
- // check if we've accessed the next page on the stack
- if (!process->fixupStackFault(gen.addr()))
- panic("Page table fault when accessing virtual
address %#x "
- "during functional write\n", gen.addr());
+ _memState->allocateMem(roundDown(gen.addr(), PageBytes),
+ PageBytes);
+ } else if (allocating == OnDemand) {
+ // check if we've accessed an unallocated physical page
+ if (!_memState->fixupFault(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);
+ _memState->translate(gen.addr(), paddr);
}
PortProxy::writeBlobPhys(paddr, 0, p + prevSize, gen.size());
@@ -135,11 +136,11 @@
for (ChunkGenerator gen(addr, size, PageBytes); !gen.done();
gen.next()) {
Addr paddr;
- if (!pTable->translate(gen.addr(), paddr)) {
+ if (!_memState->translate(gen.addr(), paddr)) {
if (allocating == Always) {
- process->allocateMem(roundDown(gen.addr(), PageBytes),
- PageBytes);
- pTable->translate(gen.addr(), paddr);
+ _memState->allocateMem(roundDown(gen.addr(), PageBytes),
+ PageBytes);
+ _memState->translate(gen.addr(), paddr);
} else {
return false;
}
@@ -170,7 +171,7 @@
c = *str++;
Addr paddr;
- if (!pTable->translate(vaddr++, paddr))
+ if (!_memState->translate(vaddr++, paddr))
return false;
PortProxy::writeBlob(paddr, &c, 1);
@@ -196,7 +197,7 @@
while (true) {
Addr paddr;
- if (!pTable->translate(vaddr++, paddr))
+ if (!_memState->translate(vaddr++, paddr))
return false;
PortProxy::readBlob(paddr, &c, 1);
diff --git a/src/mem/se_translating_port_proxy.hh
b/src/mem/se_translating_port_proxy.hh
index 04bfd8a..1ebb8cb 100644
--- a/src/mem/se_translating_port_proxy.hh
+++ b/src/mem/se_translating_port_proxy.hh
@@ -45,10 +45,11 @@
#ifndef __MEM_SE_TRANSLATING_PORT_PROXY_HH__
#define __MEM_SE_TRANSLATING_PORT_PROXY_HH__
+#include <memory>
+
#include "mem/port_proxy.hh"
-class EmulationPageTable;
-class Process;
+class MemState;
/**
* @file
@@ -71,20 +72,18 @@
enum AllocType {
Always,
Never,
- NextPage
+ OnDemand
};
private:
- EmulationPageTable *pTable;
- Process *process;
+ MemState *_memState;
AllocType allocating;
public:
- SETranslatingPortProxy(MasterPort& port, Process* p, AllocType alloc);
- ~SETranslatingPortProxy();
+ SETranslatingPortProxy(MasterPort& port, unsigned cache_line_size,
+ MemState *mem_state, AllocType alloc);
+ virtual ~SETranslatingPortProxy();
- void setPageTable(EmulationPageTable *p) { pTable = p; }
- void setProcess(Process *p) { process = p; }
bool tryReadBlob(Addr addr, uint8_t *p, int size) const;
bool tryWriteBlob(Addr addr, const uint8_t *p, int size) const;
bool tryMemsetBlob(Addr addr, uint8_t val, int size) const;
diff --git a/src/sim/SConscript b/src/sim/SConscript
index ed3da4c..321159a 100644
--- a/src/sim/SConscript
+++ b/src/sim/SConscript
@@ -83,6 +83,7 @@
Source('process.cc')
Source('fd_array.cc')
Source('fd_entry.cc')
+ Source('mem_state.cc')
Source('pseudo_inst.cc')
Source('syscall_emul.cc')
Source('syscall_desc.cc')
diff --git a/src/sim/faults.cc b/src/sim/faults.cc
index 0606080..c3c1919 100644
--- a/src/sim/faults.cc
+++ b/src/sim/faults.cc
@@ -68,8 +68,9 @@
{
bool handled = false;
if (!FullSystem) {
- Process *p = tc->getProcessPtr();
- handled = p->fixupStackFault(vaddr);
+ auto p = tc->getProcessPtr();
+ auto mem_state = p->memState;
+ handled = mem_state->fixupFault(vaddr);
}
if (!handled)
panic("Page table fault when accessing virtual address %#x\n",
vaddr);
diff --git a/src/sim/mem_state.cc b/src/sim/mem_state.cc
new file mode 100644
index 0000000..794d25b
--- /dev/null
+++ b/src/sim/mem_state.cc
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 2017 Advanced Micro Devices, Inc.
+ * 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.
+ *
+ * Author: Michael LeBeane
+ * Brandon Potter
+ */
+
+#include "sim/mem_state.hh"
+
+#include <cassert>
+
+#include "mem/se_translating_port_proxy.hh"
+#include "mem/vma.hh"
+#include "sim/process.hh"
+#include "sim/syscall_debug_macros.hh"
+#include "sim/system.hh"
+
+MemState::MemState(Process *owner, Addr brk_point, Addr stack_base,
+ Addr max_stack_size, Addr next_thread_stack_base,
+ Addr mmap_end, System *system,
+ std::shared_ptr<EmulationPageTable> p_table)
+ : _pTable(p_table), _ownerProcesses{owner}, _brkPoint(brk_point),
+ _stackBase(stack_base), _maxStackSize(max_stack_size),
+ _nextThreadStackBase(next_thread_stack_base),
+ _mmapEnd(mmap_end),
+ _endBrkPoint(brk_point),
+ _virtMem(system->getSystemPort(), system->cacheLineSize(), this,
+ SETranslatingPortProxy::Always)
+{
+}
+
+MemState&
+MemState::operator=(const MemState &other)
+{
+ if (this == &other)
+ return *this;
+
+ _brkPoint = other._brkPoint;
+ _stackBase = other._stackBase;
+ _maxStackSize = other._maxStackSize;
+ _nextThreadStackBase = other._nextThreadStackBase;
+ _mmapEnd = other._mmapEnd;
+ _vmaList = other._vmaList; /* This assignment does a deep copy. */
+
+ /* Do a page-table deep copy between the two MemState objects. */
+ typedef std::vector<std::pair<Addr,Addr>> MapVec;
+ MapVec mappings;
+ other._pTable->getMappings(&mappings);
+ for (auto map : mappings) {
+ Addr paddr, vaddr = map.first;
+ bool alloc_page = !(_pTable->translate(vaddr, paddr));
+ replicatePage(other, vaddr, paddr, alloc_page);
+ }
+
+ return *this;
+}
+
+void
+MemState::addOwner(Process *owner)
+{
+ auto it = _ownerProcesses.begin();
+ while (it != _ownerProcesses.end()) {
+ if (*it == owner)
+ break;
+ it++;
+ }
+
+ if (it == _ownerProcesses.end())
+ _ownerProcesses.push_back(owner);
+}
+
+void
+MemState::removeOwner(Process *owner)
+{
+ auto it = _ownerProcesses.begin();
+ while (it != _ownerProcesses.end()) {
+ if (*it == owner)
+ break;
+ it++;
+ }
+
+ if (it != _ownerProcesses.end())
+ _ownerProcesses.erase(it);
+}
+
+void
+MemState::updateBrkRegion(Addr old_brk, Addr new_brk)
+{
+ /**
+ * To make this simple, avoid reducing the heap memory area if the
+ * new_brk point is less than the old_brk; this occurs when the heap is
+ * receding because the application has given back memory. The brk
point
+ * is still tracked in the MemState class as an independent field so
that
+ * it can be returned to the application; we just do not update the
+ * VMA region unless we expand it out.
+ */
+ if (new_brk < old_brk)
+ return;
+
+ /**
+ * The VMAs must be page aligned but the break point can be set on
+ * byte boundaries. Ensure that the restriction is maintained here by
+ * extending the request out to the end of the page. (The roundUp
+ * function will not round up an already aligned page.)
+ */
+ new_brk = roundUp(new_brk, TheISA::PageBytes);
+
+ /**
+ * Create a new mapping for the heap region. We only create a mapping
+ * for the extra memory that is requested so we do not create a
situation
+ * where there can be overlapping mappings in the VMA regions.
+ * Since we do not track the type of the region and we also do not
+ * coalesce the regions together, we can create a fragmented set of
+ * heap VMAs. To resolve this, we keep the furthest point ever mapped
+ * by the _endBrkPoint field.
+ */
+ if (new_brk > _endBrkPoint) {
+ /**
+ * Note that the heap regions are always contiguous but there is no
+ * mechanism right now to coalesce VMAs together that belong to the
+ * same region with similar access permissions. This could be
+ * implemented if it actually becomes necessary; probably only
+ * necessary if the list becomes too long to walk.
+ */
+ mapVMARegion(_endBrkPoint, new_brk - _endBrkPoint, -1, 0);
+ _endBrkPoint = new_brk;
+ }
+}
+
+void
+MemState::mapVMARegion(Addr start_addr, Addr length, int sim_fd, Addr
offset)
+{
+ DPRINTF(SyscallVerbose, "vma: creating region [0x%x - 0x%x]\n",
+ start_addr, start_addr + length - 1);
+
+ /**
+ * Avoid creating a region that has preexisting mappings. This should
+ * not happen under normal circumstances so consider this to be a bug.
+ */
+ auto end = start_addr + length;
+ for (auto start = start_addr; start < end; start += TheISA::PageBytes)
+ assert(_pTable->lookup(start) == nullptr);
+
+ /**
+ * Record the region in our list structure.
+ */
+ _vmaList.emplace_back(start_addr, length, sim_fd, offset);
+}
+
+void
+MemState::unmapVMARegion(Addr start_addr, Addr length)
+{
+ Addr end_addr = start_addr + length - 1;
+ const AddrRange range(start_addr, end_addr);
+
+ auto vma = std::begin(_vmaList);
+ while (vma != std::end(_vmaList)) {
+ if (vma->isStrictSuperset(range)) {
+ DPRINTF(SyscallVerbose, "vma: split region [0x%x - 0x%x] into "
+ "[0x%x - 0x%x] and [0x%x - 0x%x]\n",
+ vma->start(), vma->end(),
+ vma->start(), start_addr - 1,
+ end_addr + 1, vma->end());
+ /**
+ * Need to split into two smaller regions.
+ * Create a clone of the old VMA and slice it to the right.
+ */
+ _vmaList.push_back(*vma);
+ _vmaList.back().sliceRegionRight(start_addr);
+
+ /**
+ * Slice old VMA to encapsulate the left region.
+ */
+ vma->sliceRegionLeft(end_addr);
+
+ /**
+ * Region cannot be in any more VMA, because it is completely
+ * contained in this one!
+ */
+ break;
+ } else if (vma->isSubset(range)) {
+ DPRINTF(SyscallVerbose, "vma: destroying region [0x%x -
0x%x]\n",
+ vma->start(), vma->end());
+ /**
+ * Need to nuke the existing VMA.
+ */
+ vma = _vmaList.erase(vma);
+
+ continue;
+
+ } else if (vma->intersects(range)) {
+ /**
+ * Trim up the existing VMA.
+ */
+ if (vma->start() < start_addr) {
+ DPRINTF(SyscallVerbose, "vma: resizing region [0x%x -
0x%x] "
+ "into [0x%x - 0x%x]\n",
+ vma->start(), vma->end(),
+ vma->start(), start_addr - 1);
+ /**
+ * Overlaps from the right.
+ */
+ vma->sliceRegionRight(start_addr);
+ } else {
+ DPRINTF(SyscallVerbose, "vma: resizing region [0x%x -
0x%x] "
+ "into [0x%x - 0x%x]\n",
+ vma->start(), vma->end(),
+ end_addr + 1, vma->end());
+ /**
+ * Overlaps from the left.
+ */
+ vma->sliceRegionLeft(end_addr);
+ }
+ }
+
+ vma++;
+ }
+
+ updateTLBs();
+
+ do {
+ if (!_pTable->isUnmapped(start_addr, TheISA::PageBytes))
+ _pTable->unmap(start_addr, TheISA::PageBytes);
+
+ start_addr += TheISA::PageBytes;
+
+ /**
+ * The regions need to always be page-aligned otherwise the while
+ * condition will loop indefinitely. (The Addr type is currently
+ * defined to be uint64_t in src/base/types.hh; it can underflow
+ * since it is unsigned.)
+ */
+ length -= TheISA::PageBytes;
+ } while (length > 0);
+}
+
+void
+MemState::remapVMARegion(Addr start_addr, Addr new_start_addr,
+ Addr length)
+{
+ Addr end_addr = start_addr + length - 1;
+ const AddrRange range(start_addr, end_addr);
+
+ auto vma = std::begin(_vmaList);
+ while (vma != std::end(_vmaList)) {
+ if (vma->isStrictSuperset(range)) {
+ /**
+ * Create clone of the old VMA and slice right.
+ */
+ _vmaList.push_back(*vma);
+ _vmaList.back().sliceRegionRight(start_addr);
+
+ /**
+ * Create clone of the old VMA and slice it left.
+ */
+ _vmaList.push_back(*vma);
+ _vmaList.back().sliceRegionLeft(end_addr);
+
+ /**
+ * Slice the old VMA left and right to adjust the file backing,
+ * then overwrite the virtual addresses!
+ */
+ vma->sliceRegionLeft(start_addr - 1);
+ vma->sliceRegionRight(end_addr + 1);
+ vma->remap(new_start_addr);
+
+ /**
+ * The region cannot be in any more VMAs, because it is
+ * completely contained in this one!
+ */
+ break;
+ } else if (vma->isSubset(range)) {
+ /**
+ * Just go ahead and remap it!
+ */
+ vma->remap(vma->start() - start_addr + new_start_addr);
+ } else if (vma->intersects(range)) {
+ /**
+ * Create a clone of the old VMA.
+ */
+ _vmaList.push_back(*vma);
+
+ if (vma->start() < start_addr) {
+ /**
+ * Overlaps from the right.
+ */
+ _vmaList.back().sliceRegionRight(start_addr);
+
+ /**
+ * Remap the old region.
+ */
+ vma->sliceRegionLeft(start_addr - 1);
+ vma->remap(new_start_addr);
+ } else {
+ /**
+ * Overlaps from the left.
+ */
+ _vmaList.back().sliceRegionLeft(end_addr);
+
+ /**
+ * Remap the old region.
+ */
+ vma->sliceRegionRight(end_addr + 1);
+ vma->remap(new_start_addr + vma->start() - start_addr);
+ }
+ }
+
+ vma++;
+ }
+
+ updateTLBs();
+
+ do {
+ if (!_pTable->isUnmapped(start_addr, TheISA::PageBytes))
+ _pTable->remap(start_addr, TheISA::PageBytes, new_start_addr);
+
+ start_addr += TheISA::PageBytes;
+
+ /**
+ * The regions need to always be page-aligned otherwise the while
+ * condition will loop indefinitely. (The Addr type is currently
+ * defined to be uint64_t in src/base/types.hh; it can underflow
+ * since it is unsigned.)
+ */
+ length -= TheISA::PageBytes;
+ } while (length > 0);
+}
+
+bool
+MemState::translate(Addr va)
+{
+ return (_pTable->translate(va) || fixupFault(va));
+}
+
+bool
+MemState::translate(Addr va, Addr &pa)
+{
+ return (_pTable->translate(va, pa) || (fixupFault(va) &&
+ _pTable->translate(va, pa)));
+}
+
+const EmulationPageTable::Entry*
+MemState::lookup(Addr va)
+{
+ auto entry = _pTable->lookup(va);
+ if (entry == nullptr) {
+ fixupFault(va);
+ entry = _pTable->lookup(va);
+ }
+ return entry;
+}
+
+bool
+MemState::fixupFault(Addr vaddr)
+{
+ /**
+ * Check if we are accessing a mapped virtual address. If so then we
+ * just haven't allocated it a physical page yet and can do so here.
+ */
+ for (const auto &vma : _vmaList) {
+ if (vma.contains(vaddr)) {
+ Addr vpage_start = roundDown(vaddr, TheISA::PageBytes);
+ allocateMem(vpage_start, TheISA::PageBytes);
+
+ /**
+ * We are assuming that fresh pages are zero-filled, so there
is
+ * no need to zero them out when there is no backing file.
+ * This assumption will not hold true if/when physical pages
+ * are recycled.
+ */
+ if (vma.hasHostBuf()) {
+ vma.fillMemPages(vpage_start, TheISA::PageBytes, _virtMem);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+MemState::map(Addr vaddr, Addr paddr, int size, bool cacheable)
+{
+ auto flags = cacheable ? EmulationPageTable::MappingFlags(0) :
+ EmulationPageTable::Uncacheable;
+ _pTable->map(vaddr, paddr, size, flags);
+ return true;
+}
+
+void
+MemState::allocateMem(Addr vaddr, int64_t size, bool clobber)
+{
+ int npages = divCeil(size, (int64_t)TheISA::PageBytes);
+ Addr paddr = system()->allocPhysPages(npages);
+ auto flags = clobber ? EmulationPageTable::Clobber :
+ EmulationPageTable::MappingFlags(0);
+ _pTable->map(vaddr, paddr, size, flags);
+}
+
+void
+MemState::replicatePage(const MemState &in, Addr vaddr, Addr new_paddr,
+ bool allocate_page)
+{
+ if (allocate_page)
+ new_paddr = system()->allocPhysPages(1);
+
+ /**
+ * Read from old physical page.
+ */
+ uint8_t *buf_p = new uint8_t[TheISA::PageBytes];
+ in._virtMem.readBlob(vaddr, buf_p, TheISA::PageBytes);
+
+ /**
+ * Create new mapping in process address space by clobbering existing
+ * mapping (if any existed) and then write to the new physical page.
+ */
+ bool clobber = true;
+ _pTable->map(vaddr, new_paddr, TheISA::PageBytes, clobber);
+ _virtMem.writeBlob(vaddr, buf_p, TheISA::PageBytes);
+ delete[] buf_p;
+}
+
+System *
+MemState::system() const
+{
+ /**
+ * Grab the system field from one of our parent processes; we assume
+ * that the processes will all belong to the same system object.
+ */
+ assert(_ownerProcesses.size());
+ return _ownerProcesses[0]->system;
+}
+
+void
+MemState::updateTLBs()
+{
+ /**
+ * FIXME: Flush only the necessary translation look-aside buffer
entries.
+ *
+ * The following code results in functionally correct execution, but
real
+ * systems do not flush all entries when a single mapping changes since
+ * it tanks performance. The problem is that there is no general method
+ * across all of the implementations which can flush just part of the
+ * address space.
+ */
+ for (auto tc : system()->threadContexts) {
+ tc->getDTBPtr()->flushAll();
+ tc->getITBPtr()->flushAll();
+ }
+}
diff --git a/src/sim/mem_state.hh b/src/sim/mem_state.hh
index ca07a64..a8485c8 100644
--- a/src/sim/mem_state.hh
+++ b/src/sim/mem_state.hh
@@ -31,47 +31,44 @@
#ifndef SRC_SIM_MEM_STATE_HH
#define SRC_SIM_MEM_STATE_HH
+#include <sys/mman.h>
+
+#include <list>
+#include <memory>
+#include <vector>
+
+#include "mem/page_table.hh"
+#include "mem/se_translating_port_proxy.hh"
#include "sim/serialize.hh"
+class Process;
+class ProcessParams;
+class System;
+
/**
* This class holds the memory state for the Process class and all of its
* derived, architecture-specific children.
*
- * The fields held in this class dynamically change as the process object
- * is run in the simulator. They are updated by system calls and faults;
- * each change represents a modification to the process address space.
- * The stack, heap, and mmap boundaries are held with this class along with
- * the base of the next thread stack.
+ * The class fields change dynamically as the process object is run in the
+ * simulator. They are updated by system calls and faults. Each change
+ * represents a modification to the process address space.
*
* The class is meant to be allocated dynamically and shared through a
- * pointer interface because two process can potentially share their
virtual
- * address space if certain options are passed into the clone(2).
+ * pointer interface. Multiple process can potentially share their virtual
+ * address space if specific options are passed into the clone(2) system
call.
*/
class MemState : public Serializable
{
public:
- MemState(Addr brk_point, Addr stack_base, Addr max_stack_size,
- Addr next_thread_stack_base, Addr mmap_end)
- : _brkPoint(brk_point), _stackBase(stack_base), _stackSize(0),
- _maxStackSize(max_stack_size), _stackMin(0),
- _nextThreadStackBase(next_thread_stack_base), _mmapEnd(mmap_end)
- { }
+ MemState(Process *owner, Addr brk_point, Addr stack_base,
+ Addr max_stack_size, Addr next_thread_stack_base,
+ Addr mmap_end, System *system,
+ std::shared_ptr<EmulationPageTable> p_table);
- MemState&
- operator=(const MemState &in)
- {
- if (this == &in)
- return *this;
+ MemState& operator=(const MemState &in);
- _brkPoint = in._brkPoint;
- _stackBase = in._stackBase;
- _stackSize = in._stackSize;
- _maxStackSize = in._maxStackSize;
- _stackMin = in._stackMin;
- _nextThreadStackBase = in._nextThreadStackBase;
- _mmapEnd = in._mmapEnd;
- return *this;
- }
+ void addOwner(Process *owner);
+ void removeOwner(Process *owner);
Addr getBrkPoint() const { return _brkPoint; }
Addr getStackBase() const { return _stackBase; }
@@ -80,7 +77,6 @@
Addr getStackMin() const { return _stackMin; }
Addr getNextThreadStackBase() const { return _nextThreadStackBase; }
Addr getMmapEnd() const { return _mmapEnd; }
-
void setBrkPoint(Addr brk_point) { _brkPoint = brk_point; }
void setStackBase(Addr stack_base) { _stackBase = stack_base; }
void setStackSize(Addr stack_size) { _stackSize = stack_size; }
@@ -89,6 +85,91 @@
void setNextThreadStackBase(Addr ntsb) { _nextThreadStackBase = ntsb; }
void setMmapEnd(Addr mmap_end) { _mmapEnd = mmap_end; }
+ const SETranslatingPortProxy& getVirtMem() const { return _virtMem; }
+
+ /**
+ * This method returns a flag which specifies the direction of growth
for
+ * the mmap region in process address space.
+ *
+ * @return true if the mmap region grows downward and false otherwise
+ */
+ virtual bool mmapGrowsDown() const
+#if THE_ISA == ALPHA_ISA || THE_ISA == RISCV_ISA
+ { return false; }
+#else
+ { return true; }
+#endif
+
+ /**
+ * These methods perform the same behavior as the methods in the
+ * PageTable class with the additional semantic that they will attempt
to
+ * allocate physical pages (frames) to resolve faults.
+ * vaddr is valid but the page table does not have an entry yet.
+ */
+ bool translate(Addr va);
+ bool translate(Addr va, Addr &pa);
+ const EmulationPageTable::Entry *lookup(Addr va);
+
+ /**
+ * Maps a contiguous range of virtual addresses in this process's
+ * address space to a contiguous range of physical addresses.
+ * This function exists primarily to expose the map operation to
+ * python, so that configuration scripts can set up mappings in SE
mode.
+ *
+ * @param vaddr The starting virtual address of the range.
+ * @param paddr The starting physical address of the range.
+ * @param size The length of the range in bytes.
+ * @param cacheable Specifies whether accesses are cacheable.
+ * @return True if the map operation was successful. (At this point in
+ * time, the map operation always succeeds.)
+ */
+ bool map(Addr vaddr, Addr paddr, int size, bool cacheable = true);
+
+ /**
+ * Attempt to fix up a fault at vaddr by allocating a page. The fault
+ * likely occurred because a virtual page which does not have physical
+ * page assignment is being accessed.
+ *
+ * @param vaddr The virtual address which is causing the fault.
+ * @return Whether the fault has been fixed.
+ */
+ bool fixupFault(Addr vaddr);
+
+ /**
+ * Given the vaddr and size, this method will chunk the allocation into
+ * page granularity and then request physical pages (frames) from the
+ * system object. After retrieving a frame, the method updates the page
+ * table mappings.
+ *
+ * @param vaddr The virtual address in need of a frame allocation.
+ * @param size The size in bytes of the requested mapping.
+ * @param clobber This flag specifies whether mappings in the page
tables
+ * can be overwritten and replaced with the new mapping.
+ */
+ void allocateMem(Addr vaddr, int64_t size, bool clobber = false);
+
+ /**
+ * The _pTable member is either an architectural page table object or a
+ * functional page table object. Both implementations share the same
API
+ * and can be accessed through this base class object.
+ */
+ std::shared_ptr<EmulationPageTable> _pTable;
+
+ /**
+ * This port proxy provides a handle to access the process address
space
+ * (represented by this object). In SE Mode, all references to the
+ * process address space (using virtual addresses) should be directed
+ * through this proxy.
+ *
+ * Creating duplicates or storing copies of this proxy in other
+ * objects is frowned upon; please do not do it! Note, the proxy is
+ * owned by this object and will become obsolete if this object
+ * deconstructs. (This will happen if all processes release their hold
+ * on this object; this is particularly an issue when calling the exec
+ * system call.)
+ */
+ const SETranslatingPortProxy& getVirtProxy() { return _virtMem; }
+
void
serialize(CheckpointOut &cp) const override
{
@@ -113,6 +194,22 @@
}
private:
+ void replicatePage(const MemState &in, Addr vaddr, Addr new_paddr,
+ bool alloc_page);
+
+ void updateTLBs();
+
+ System * system() const;
+
+ void checkAlign(Addr start, Addr length);
+
+ /**
+ * Holds the list of Process objects which have a reference to this
+ * MemState object. The owner Processes act as parents in an object
tree
+ * for MemState.
+ */
+ std::vector<Process*> _ownerProcesses;
+
Addr _brkPoint;
Addr _stackBase;
Addr _stackSize;
@@ -120,6 +217,18 @@
Addr _stackMin;
Addr _nextThreadStackBase;
Addr _mmapEnd;
+
+ /**
+ * Keeps record of the furthest mapped heap location for the VMAs.
+ */
+ Addr _endBrkPoint;
+
+ /**
+ * The _virtMem member acts as a proxy for accessing virtual memory.
This
+ * handle is responsible for reading and writing blobs and strings
both to
+ * and from the virtual memory space for Process objects.
+ */
+ SETranslatingPortProxy _virtMem;
};
#endif
diff --git a/src/sim/process_impl.hh b/src/sim/mem_state_impl.hh
similarity index 82%
rename from src/sim/process_impl.hh
rename to src/sim/mem_state_impl.hh
index 3f3d6ae..b3c59e2 100644
--- a/src/sim/process_impl.hh
+++ b/src/sim/mem_state_impl.hh
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * Copyright (c) 2017 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,10 +28,12 @@
*
* Authors: Nathan Binkert
* Steve Reinhardt
+ * Brandon Potter
*/
-#ifndef __SIM_PROCESS_IMPL_HH__
-#define __SIM_PROCESS_IMPL_HH__
+
+#ifndef __SIM_MEM_STATE_IMPL_HH__
+#define __SIM_MEM_STATE_IMPL_HH__
#include <string>
#include <vector>
@@ -41,22 +44,22 @@
template<class AddrType>
void
copyStringArray(std::vector<std::string> &strings,
- AddrType array_ptr, AddrType data_ptr,
- SETranslatingPortProxy& memProxy)
+ AddrType array_ptr, AddrType data_ptr,
+ const SETranslatingPortProxy& mem_proxy)
{
AddrType data_ptr_swap;
for (std::vector<std::string>::size_type i = 0; i < strings.size();
++i) {
data_ptr_swap = TheISA::htog(data_ptr);
- memProxy.writeBlob(array_ptr, (uint8_t*)&data_ptr_swap,
+ mem_proxy.writeBlob(array_ptr, (uint8_t*)&data_ptr_swap,
sizeof(AddrType));
- memProxy.writeString(data_ptr, strings[i].c_str());
+ mem_proxy.writeString(data_ptr, strings[i].c_str());
array_ptr += sizeof(AddrType);
data_ptr += strings[i].size() + 1;
}
// add NULL terminator
data_ptr = 0;
- memProxy.writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType));
+ mem_proxy.writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType));
}
#endif
diff --git a/src/sim/process.cc b/src/sim/process.cc
index 5a4f3d5..3a3f66a 100644
--- a/src/sim/process.cc
+++ b/src/sim/process.cc
@@ -63,7 +63,6 @@
#include "base/statistics.hh"
#include "config/the_isa.hh"
#include "cpu/thread_context.hh"
-#include "mem/page_table.hh"
#include "params/Process.hh"
#include "sim/emul_driver.hh"
#include "sim/fd_array.hh"
@@ -103,12 +102,9 @@
using namespace std;
using namespace TheISA;
-Process::Process(ProcessParams *params, EmulationPageTable *pTable,
- ObjectFile *obj_file)
+Process::Process(ProcessParams *params, ObjectFile *obj_file)
: SimObject(params), system(params->system),
- useArchPT(params->useArchPT),
kvmInSE(params->kvmInSE),
- pTable(pTable),
objFile(obj_file),
argv(params->cmd), envp(params->env),
host_cwd(checkPathRedirect(params->cwd)), tgt_cwd(params->cwd),
@@ -118,7 +114,8 @@
_pid(params->pid), _ppid(params->ppid),
_pgid(params->pgid), drivers(params->drivers),
fds(make_shared<FDArray>(params->input, params->output,
params->errout)),
- childClearTID(0)
+ childClearTID(0),
+ _params(params)
{
if (_pid >= System::maxPID)
fatal("_pid is too large: %d", _pid);
@@ -174,26 +171,9 @@
* and the old process. Changes in one will be visible in the other
* due to the pointer use.
*/
- delete np->pTable;
- np->pTable = pTable;
- ntc->getMemProxy().setPageTable(np->pTable);
-
np->memState = memState;
+ memState->addOwner(np);
} else {
- /**
- * Duplicate the process memory address space. The state needs to
be
- * copied over (rather than using pointers to share everything).
- */
- typedef std::vector<pair<Addr,Addr>> MapVec;
- MapVec mappings;
- pTable->getMappings(&mappings);
-
- for (auto map : mappings) {
- Addr paddr, vaddr = map.first;
- bool alloc_page = !(np->pTable->translate(vaddr, paddr));
- np->replicatePage(vaddr, paddr, otc, ntc, alloc_page);
- }
-
*np->memState = *memState;
}
@@ -294,8 +274,6 @@
// mark this context as active so it will start ticking.
tc->activate();
-
- pTable->initState(tc);
}
DrainState
@@ -306,76 +284,17 @@
}
void
-Process::allocateMem(Addr vaddr, int64_t size, bool clobber)
-{
- int npages = divCeil(size, (int64_t)PageBytes);
- Addr paddr = system->allocPhysPages(npages);
- pTable->map(vaddr, paddr, size,
- clobber ? EmulationPageTable::Clobber :
- EmulationPageTable::MappingFlags(0));
-}
-
-void
-Process::replicatePage(Addr vaddr, Addr new_paddr, ThreadContext *old_tc,
- ThreadContext *new_tc, bool allocate_page)
-{
- if (allocate_page)
- new_paddr = system->allocPhysPages(1);
-
- // Read from old physical page.
- uint8_t *buf_p = new uint8_t[PageBytes];
- old_tc->getMemProxy().readBlob(vaddr, buf_p, PageBytes);
-
- // Create new mapping in process address space by clobbering existing
- // mapping (if any existed) and then write to the new physical page.
- bool clobber = true;
- pTable->map(vaddr, new_paddr, PageBytes, clobber);
- new_tc->getMemProxy().writeBlob(vaddr, buf_p, PageBytes);
- delete[] buf_p;
-}
-
-bool
-Process::fixupStackFault(Addr vaddr)
-{
- Addr stack_min = memState->getStackMin();
- Addr stack_base = memState->getStackBase();
- Addr max_stack_size = memState->getMaxStackSize();
-
- // Check if this is already on the stack and there's just no page there
- // yet.
- if (vaddr >= stack_min && vaddr < stack_base) {
- allocateMem(roundDown(vaddr, PageBytes), PageBytes);
- return true;
- }
-
- // We've accessed the next page of the stack, so extend it to include
- // this address.
- if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) {
- while (vaddr < stack_min) {
- stack_min -= TheISA::PageBytes;
- if (stack_base - stack_min > max_stack_size)
- fatal("Maximum stack size exceeded\n");
- allocateMem(stack_min, TheISA::PageBytes);
- inform("Increasing stack size by one page.");
- }
- memState->setStackMin(stack_min);
- return true;
- }
- return false;
-}
-
-void
Process::serialize(CheckpointOut &cp) const
{
- memState->serialize(cp);
- pTable->serialize(cp);
+ warn("Checkpoints in SE mode currently do not work.");
/**
* Checkpoints for file descriptors currently do not work. Need to
* come back and fix them at a later date.
*/
- warn("Checkpoints for file descriptors currently do not work.");
#if 0
+ memState->serialize(cp);
+ pTable->serialize(cp);
for (int x = 0; x < fds->getSize(); x++)
(*fds)[x].serializeSection(cp, csprintf("FDEntry%d", x));
#endif
@@ -385,14 +304,10 @@
void
Process::unserialize(CheckpointIn &cp)
{
+ warn("Checkpoints in SE mode currently do not work.");
+#if 0
memState->unserialize(cp);
pTable->unserialize(cp);
- /**
- * Checkpoints for file descriptors currently do not work. Need to
- * come back and fix them at a later date.
- */
- warn("Checkpoints for file descriptors currently do not work.");
-#if 0
for (int x = 0; x < fds->getSize(); x++)
(*fds)[x]->unserializeSection(cp, csprintf("FDEntry%d", x));
fds->restoreFileOffsets();
@@ -403,15 +318,6 @@
// found.
}
-bool
-Process::map(Addr vaddr, Addr paddr, int size, bool cacheable)
-{
- pTable->map(vaddr, paddr, size,
- cacheable ? EmulationPageTable::MappingFlags(0) :
- EmulationPageTable::Uncacheable);
- return true;
-}
-
void
Process::syscall(int64_t callnum, ThreadContext *tc, Fault *fault)
{
@@ -503,12 +409,13 @@
// We are allocating the memory area; set the bias to the lowest
address
// in the allocated memory region.
Addr mmap_end = memState->getMmapEnd();
- Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end;
+ Addr ld_bias = memState->mmapGrowsDown() ?
+ mmap_end - interp_mapsize : mmap_end;
// Adjust the process mmap area to give the interpreter room; the real
// execve system call would just invoke the kernel's internal mmap
// functions to make these adjustments.
- mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize;
+ mmap_end = memState->mmapGrowsDown() ? ld_bias : mmap_end +
interp_mapsize;
memState->setMmapEnd(mmap_end);
interp->updateBias(ld_bias);
diff --git a/src/sim/process.hh b/src/sim/process.hh
index a888b1b..35d1c31 100644
--- a/src/sim/process.hh
+++ b/src/sim/process.hh
@@ -36,7 +36,6 @@
#include <inttypes.h>
-#include <map>
#include <string>
#include <vector>
@@ -62,8 +61,7 @@
class Process : public SimObject
{
public:
- Process(ProcessParams *params, EmulationPageTable *pTable,
- ObjectFile *obj_file);
+ Process(ProcessParams *params, ObjectFile *obj_file);
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
@@ -123,12 +121,6 @@
// override of virtual SimObject method: register statistics
void regStats() override;
- void allocateMem(Addr vaddr, int64_t size, bool clobber = false);
-
- /// Attempt to fix up a fault at vaddr by allocating a page on the
stack.
- /// @return Whether the fault has been fixed.
- bool fixupStackFault(Addr vaddr);
-
// After getting registered with system object, tell process which
// system-wide context id it is assigned.
void
@@ -146,30 +138,10 @@
*/
void revokeThreadContext(int context_id);
- /**
- * Does mmap region grow upward or downward from mmapEnd? Most
- * platforms grow downward, but a few (such as Alpha) grow upward
- * instead, so they can override this method to return false.
- */
- virtual bool mmapGrowsDown() const { return true; }
-
- /**
- * Maps a contiguous range of virtual addresses in this process's
- * address space to a contiguous range of physical addresses.
- * This function exists primarily to expose the map operation to
- * python, so that configuration scripts can set up mappings in SE
mode.
- *
- * @param vaddr The starting virtual address of the range.
- * @param paddr The starting physical address of the range.
- * @param size The length of the range in bytes.
- * @param cacheable Specifies whether accesses are cacheable.
- * @return True if the map operation was successful. (At this
- * point in time, the map operation always succeeds.)
- */
- bool map(Addr vaddr, Addr paddr, int size, bool cacheable = true);
-
- void replicatePage(Addr vaddr, Addr new_paddr, ThreadContext *old_tc,
- ThreadContext *new_tc, bool alloc_page);
+ bool map(Addr vaddr, Addr paddr, int size, bool cacheable = true)
+ {
+ return memState->map(vaddr, paddr, size, cacheable);
+ };
virtual void clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *new_p, TheISA::IntReg flags);
@@ -182,11 +154,8 @@
Stats::Scalar numSyscalls; // track how many system calls are executed
- bool useArchPT; // flag for using architecture specific page table
bool kvmInSE; // running KVM requires special initialization
- EmulationPageTable *pTable;
-
ObjectFile *objFile;
std::vector<std::string> argv;
std::vector<std::string> envp;
@@ -212,7 +181,6 @@
std::shared_ptr<FDArray> fds;
bool *exitGroup;
- std::shared_ptr<MemState> memState;
/**
* Calls a futex wakeup at the address specified by this pointer when
@@ -222,6 +190,10 @@
// Process was forked with SIGCHLD set.
bool *sigchld;
+
+ ProcessParams *_params;
+
+ std::shared_ptr<MemState> memState;
};
#endif // __PROCESS_HH__
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 41c0c51..dfc6ac0 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -1477,6 +1477,10 @@
ptidBuf.copyOut(parent_virt_mem);
}
+ auto child_mem_state = cp->memState;
+ if (flags & OS::TGT_CLONE_THREAD) {
+ auto child_p_table = child_mem_state->_pTable;
+ }
cp->initState();
p->clone(tc, ctc, cp, flags);
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/12306
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I5e6afecbd47e9c46998c4d6a1091d1f4fb698a71
Gerrit-Change-Number: 12306
Gerrit-PatchSet: 1
Gerrit-Owner: Brandon Potter <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev