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:
Lisa Hsu
2008-11-02 21:57:06 -05:00
parent c55a467a06
commit 67fda02dda
9 changed files with 100 additions and 107 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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