Make it so that all thread contexts are registered with the System, even in
SE. Process still keeps track of the tc's it owns, but registration occurs with the System, this eases the way for system-wide context Ids based on registration.
This commit is contained in:
@@ -67,12 +67,13 @@ AlphaLiveProcess::startup()
|
||||
|
||||
argsInit(MachineBytes, VMPageSize);
|
||||
|
||||
threadContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer());
|
||||
//Opperate in user mode
|
||||
threadContexts[0]->setMiscRegNoEffect(IPR_ICM, 0x18);
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
tc->setIntReg(GlobalPointerReg, objFile->globalPointer());
|
||||
//Operate in user mode
|
||||
tc->setMiscRegNoEffect(IPR_ICM, 0x18);
|
||||
//No super page mapping
|
||||
threadContexts[0]->setMiscRegNoEffect(IPR_MCSR, 0);
|
||||
tc->setMiscRegNoEffect(IPR_MCSR, 0);
|
||||
//Set this to 0 for now, but it should be unique for each process
|
||||
threadContexts[0]->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57);
|
||||
tc->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57);
|
||||
}
|
||||
|
||||
|
||||
@@ -112,44 +112,45 @@ SparcLiveProcess::startup()
|
||||
{
|
||||
Process::startup();
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
//From the SPARC ABI
|
||||
|
||||
//Setup default FP state
|
||||
threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
|
||||
tc->setMiscRegNoEffect(MISCREG_FSR, 0);
|
||||
|
||||
threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
|
||||
tc->setMiscRegNoEffect(MISCREG_TICK, 0);
|
||||
|
||||
/*
|
||||
* Register window management registers
|
||||
*/
|
||||
|
||||
//No windows contain info from other programs
|
||||
//threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
|
||||
threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
|
||||
//tc->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
|
||||
tc->setIntReg(NumIntArchRegs + 6, 0);
|
||||
//There are no windows to pop
|
||||
//threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
|
||||
threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
|
||||
//tc->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
|
||||
tc->setIntReg(NumIntArchRegs + 4, 0);
|
||||
//All windows are available to save into
|
||||
//threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
|
||||
threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
|
||||
//tc->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
|
||||
tc->setIntReg(NumIntArchRegs + 3, NWindows - 2);
|
||||
//All windows are "clean"
|
||||
//threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
|
||||
threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
|
||||
//tc->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
|
||||
tc->setIntReg(NumIntArchRegs + 5, NWindows);
|
||||
//Start with register window 0
|
||||
threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0);
|
||||
tc->setMiscRegNoEffect(MISCREG_CWP, 0);
|
||||
//Always use spill and fill traps 0
|
||||
//threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0);
|
||||
threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
|
||||
//tc->setMiscRegNoEffect(MISCREG_WSTATE, 0);
|
||||
tc->setIntReg(NumIntArchRegs + 7, 0);
|
||||
//Set the trap level to 0
|
||||
threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0);
|
||||
tc->setMiscRegNoEffect(MISCREG_TL, 0);
|
||||
//Set the ASI register to something fixed
|
||||
threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
|
||||
tc->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
|
||||
|
||||
/*
|
||||
* T1 specific registers
|
||||
*/
|
||||
//Turn on the icache, dcache, dtb translation, and itb translation.
|
||||
threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
|
||||
tc->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -160,8 +161,9 @@ Sparc32LiveProcess::startup()
|
||||
|
||||
SparcLiveProcess::startup();
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
//The process runs in user mode with 32 bit addresses
|
||||
threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x0a);
|
||||
tc->setMiscReg(MISCREG_PSTATE, 0x0a);
|
||||
|
||||
argsInit(32 / 8, VMPageSize);
|
||||
}
|
||||
@@ -174,8 +176,9 @@ Sparc64LiveProcess::startup()
|
||||
|
||||
SparcLiveProcess::startup();
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
//The process runs in user mode
|
||||
threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02);
|
||||
tc->setMiscReg(MISCREG_PSTATE, 0x02);
|
||||
|
||||
argsInit(sizeof(IntReg), VMPageSize);
|
||||
}
|
||||
@@ -391,20 +394,21 @@ SparcLiveProcess::argsInit(int pageSize)
|
||||
fillStart = stack_base;
|
||||
spillStart = fillStart + sizeof(MachInst) * numFillInsts;
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
//Set up the thread context to start running the process
|
||||
//assert(NumArgumentRegs >= 2);
|
||||
//threadContexts[0]->setIntReg(ArgumentReg[0], argc);
|
||||
//threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
|
||||
threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
|
||||
//tc->setIntReg(ArgumentReg[0], argc);
|
||||
//tc->setIntReg(ArgumentReg[1], argv_array_base);
|
||||
tc->setIntReg(StackPointerReg, stack_min - StackBias);
|
||||
|
||||
// %g1 is a pointer to a function that should be run at exit. Since we
|
||||
// don't have anything like that, it should be set to 0.
|
||||
threadContexts[0]->setIntReg(1, 0);
|
||||
tc->setIntReg(1, 0);
|
||||
|
||||
Addr prog_entry = objFile->entryPoint();
|
||||
threadContexts[0]->setPC(prog_entry);
|
||||
threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
|
||||
threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
|
||||
tc->setPC(prog_entry);
|
||||
tc->setNextPC(prog_entry + sizeof(MachInst));
|
||||
tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
|
||||
|
||||
//Align the "stack_min" to a page boundary.
|
||||
stack_min = roundDown(stack_min, pageSize);
|
||||
|
||||
@@ -146,8 +146,8 @@ X86LiveProcess::startup()
|
||||
|
||||
argsInit(sizeof(IntReg), VMPageSize);
|
||||
|
||||
for (int i = 0; i < threadContexts.size(); i++) {
|
||||
ThreadContext * tc = threadContexts[i];
|
||||
for (int i = 0; i < contextIds.size(); i++) {
|
||||
ThreadContext * tc = system->getThreadContext(contextIds[i]);
|
||||
|
||||
SegAttr dataAttr = 0;
|
||||
dataAttr.writable = 1;
|
||||
@@ -458,14 +458,15 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
|
||||
|
||||
initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
//Set the stack pointer register
|
||||
threadContexts[0]->setIntReg(StackPointerReg, stack_min);
|
||||
tc->setIntReg(StackPointerReg, stack_min);
|
||||
|
||||
Addr prog_entry = objFile->entryPoint();
|
||||
// There doesn't need to be any segment base added in since we're dealing
|
||||
// with the flat segmentation model.
|
||||
threadContexts[0]->setPC(prog_entry);
|
||||
threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
|
||||
tc->setPC(prog_entry);
|
||||
tc->setNextPC(prog_entry + sizeof(MachInst));
|
||||
|
||||
//Align the "stack_min" to a page boundary.
|
||||
stack_min = roundDown(stack_min, pageSize);
|
||||
|
||||
@@ -285,10 +285,9 @@ BaseCPU::registerThreadContexts()
|
||||
for (int i = 0; i < threadContexts.size(); ++i) {
|
||||
ThreadContext *tc = threadContexts[i];
|
||||
|
||||
#if FULL_SYSTEM
|
||||
system->registerThreadContext(tc);
|
||||
#else
|
||||
tc->getProcessPtr()->registerThreadContext(tc);
|
||||
#if !FULL_SYSTEM
|
||||
tc->getProcessPtr()->assignThreadContext(tc->cpuId());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -330,12 +329,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
|
||||
CpuEvent::replaceThreadContext(oldTC, newTC);
|
||||
|
||||
assert(newTC->cpuId() == oldTC->cpuId());
|
||||
#if FULL_SYSTEM
|
||||
system->replaceThreadContext(newTC, newTC->cpuId());
|
||||
#else
|
||||
assert(newTC->getProcessPtr() == oldTC->getProcessPtr());
|
||||
newTC->getProcessPtr()->replaceThreadContext(newTC, newTC->cpuId());
|
||||
#endif
|
||||
|
||||
if (DTRACE(Context))
|
||||
ThreadContext::compare(oldTC, newTC);
|
||||
|
||||
@@ -789,21 +789,18 @@ class Tru64 : public OperatingSystem
|
||||
slot_state.copyOut(tc->getMemPort());
|
||||
|
||||
// Find a free simulator thread context.
|
||||
for (int i = 0; i < process->numCpus(); ++i) {
|
||||
ThreadContext *tc = process->threadContexts[i];
|
||||
ThreadContext *tc = process->findFreeContext();
|
||||
if (tc) {
|
||||
// inactive context... grab it
|
||||
init_thread_context(tc, attrp, uniq_val);
|
||||
|
||||
if (tc->status() == ThreadContext::Unallocated) {
|
||||
// inactive context... grab it
|
||||
init_thread_context(tc, attrp, uniq_val);
|
||||
// This is supposed to be a port number, but we'll try
|
||||
// and get away with just sticking the thread index
|
||||
// here.
|
||||
*kidp = htog(thread_index);
|
||||
kidp.copyOut(tc->getMemPort());
|
||||
|
||||
// This is supposed to be a port number, but we'll try
|
||||
// and get away with just sticking the thread index
|
||||
// here.
|
||||
*kidp = htog(thread_index);
|
||||
kidp.copyOut(tc->getMemPort());
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fell out of loop... no available inactive context
|
||||
|
||||
@@ -204,35 +204,29 @@ Process::openOutputFile(const string &filename)
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Process::registerThreadContext(ThreadContext *tc)
|
||||
ThreadContext *
|
||||
Process::findFreeContext()
|
||||
{
|
||||
// add to list
|
||||
int myIndex = threadContexts.size();
|
||||
threadContexts.push_back(tc);
|
||||
|
||||
int port = getRemoteGDBPort();
|
||||
if (port) {
|
||||
RemoteGDB *rgdb = new RemoteGDB(system, tc);
|
||||
GDBListener *gdbl = new GDBListener(rgdb, port + myIndex);
|
||||
gdbl->listen();
|
||||
|
||||
remoteGDB.push_back(rgdb);
|
||||
int size = contextIds.size();
|
||||
ThreadContext *tc;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
tc = system->getThreadContext(contextIds[i]);
|
||||
if (tc->status() == ThreadContext::Unallocated) {
|
||||
// inactive context, free to use
|
||||
return tc;
|
||||
}
|
||||
}
|
||||
|
||||
// return CPU number to caller
|
||||
return myIndex;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
Process::startup()
|
||||
{
|
||||
if (threadContexts.empty())
|
||||
fatal("Process %s is not associated with any CPUs!\n", name());
|
||||
if (contextIds.empty())
|
||||
fatal("Process %s is not associated with any HW contexts!\n", name());
|
||||
|
||||
// first thread context for this process... initialize & enable
|
||||
ThreadContext *tc = threadContexts[0];
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
|
||||
// mark this context as active so it will start ticking.
|
||||
tc->activate(0);
|
||||
@@ -245,17 +239,6 @@ Process::startup()
|
||||
initVirtMem->setPeer(mem_port);
|
||||
}
|
||||
|
||||
void
|
||||
Process::replaceThreadContext(ThreadContext *tc, int tcIndex)
|
||||
{
|
||||
if (tcIndex >= threadContexts.size()) {
|
||||
panic("replaceThreadContext: bad tcIndex, %d >= %d\n",
|
||||
tcIndex, threadContexts.size());
|
||||
}
|
||||
|
||||
threadContexts[tcIndex] = tc;
|
||||
}
|
||||
|
||||
// map simulator fd sim_fd to target fd tgt_fd
|
||||
void
|
||||
Process::dup_fd(int sim_fd, int tgt_fd)
|
||||
@@ -624,16 +607,19 @@ LiveProcess::argsInit(int intSize, int pageSize)
|
||||
copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
|
||||
|
||||
assert(NumArgumentRegs >= 2);
|
||||
threadContexts[0]->setIntReg(ArgumentReg[0], argc);
|
||||
threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
|
||||
threadContexts[0]->setIntReg(StackPointerReg, stack_min);
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
|
||||
tc->setIntReg(ArgumentReg[0], argc);
|
||||
tc->setIntReg(ArgumentReg[1], argv_array_base);
|
||||
tc->setIntReg(StackPointerReg, stack_min);
|
||||
|
||||
Addr prog_entry = objFile->entryPoint();
|
||||
threadContexts[0]->setPC(prog_entry);
|
||||
threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
|
||||
tc->setPC(prog_entry);
|
||||
tc->setNextPC(prog_entry + sizeof(MachInst));
|
||||
|
||||
#if THE_ISA != ALPHA_ISA //e.g. MIPS or Sparc
|
||||
threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
|
||||
tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
|
||||
#endif
|
||||
|
||||
num_processes++;
|
||||
|
||||
@@ -77,7 +77,7 @@ class Process : public SimObject
|
||||
bool checkpointRestored;
|
||||
|
||||
// thread contexts associated with this process
|
||||
std::vector<ThreadContext *> threadContexts;
|
||||
std::vector<int> contextIds;
|
||||
|
||||
// remote gdb objects
|
||||
std::vector<TheISA::RemoteGDB *> remoteGDB;
|
||||
@@ -85,7 +85,7 @@ class Process : public SimObject
|
||||
bool breakpoint();
|
||||
|
||||
// number of CPUs (esxec contexts, really) assigned to this process.
|
||||
unsigned int numCpus() { return threadContexts.size(); }
|
||||
unsigned int numCpus() { return contextIds.size(); }
|
||||
|
||||
// record of blocked context
|
||||
struct WaitRec
|
||||
@@ -187,12 +187,15 @@ class Process : public SimObject
|
||||
// override of virtual SimObject method: register statistics
|
||||
virtual void regStats();
|
||||
|
||||
// register a thread context for this process.
|
||||
// returns tc's cpu number (index into threadContexts[])
|
||||
int registerThreadContext(ThreadContext *tc);
|
||||
// After getting registered with system object, tell process which
|
||||
// system-wide context id it is assigned.
|
||||
void assignThreadContext(int context_id)
|
||||
{
|
||||
contextIds.push_back(context_id);
|
||||
}
|
||||
|
||||
|
||||
void replaceThreadContext(ThreadContext *tc, int tcIndex);
|
||||
// Find a free context to use
|
||||
ThreadContext * findFreeContext();
|
||||
|
||||
// map simulator fd sim_fd to target fd tgt_fd
|
||||
void dup_fd(int sim_fd, int tgt_fd);
|
||||
|
||||
@@ -208,22 +208,24 @@ System::registerThreadContext(ThreadContext *tc)
|
||||
void
|
||||
System::startup()
|
||||
{
|
||||
#if FULL_SYSTEM
|
||||
int i;
|
||||
for (i = 0; i < threadContexts.size(); i++)
|
||||
TheISA::startupCPU(threadContexts[i], i);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
System::replaceThreadContext(ThreadContext *tc, int id)
|
||||
System::replaceThreadContext(ThreadContext *tc, int context_id)
|
||||
{
|
||||
if (id >= threadContexts.size()) {
|
||||
if (context_id >= threadContexts.size()) {
|
||||
panic("replaceThreadContext: bad id, %d >= %d\n",
|
||||
id, threadContexts.size());
|
||||
context_id, threadContexts.size());
|
||||
}
|
||||
|
||||
threadContexts[id] = tc;
|
||||
if (id < remoteGDB.size())
|
||||
remoteGDB[id]->replaceThreadContext(tc);
|
||||
threadContexts[context_id] = tc;
|
||||
if (context_id < remoteGDB.size())
|
||||
remoteGDB[context_id]->replaceThreadContext(tc);
|
||||
}
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
|
||||
@@ -89,6 +89,11 @@ class System : public SimObject
|
||||
std::vector<ThreadContext *> threadContexts;
|
||||
int numcpus;
|
||||
|
||||
ThreadContext * getThreadContext(int tid)
|
||||
{
|
||||
return threadContexts[tid];
|
||||
}
|
||||
|
||||
int getNumCPUs()
|
||||
{
|
||||
if (numcpus != threadContexts.size())
|
||||
@@ -220,7 +225,7 @@ class System : public SimObject
|
||||
#endif // FULL_SYSTEM
|
||||
|
||||
int registerThreadContext(ThreadContext *tc);
|
||||
void replaceThreadContext(ThreadContext *tc, int tcIndex);
|
||||
void replaceThreadContext(ThreadContext *tc, int context_id);
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
Reference in New Issue
Block a user