inorder: treat SE mode syscalls as a trapping instruction

define a syscallContext to schedule the syscall and then use syscall() to actually perform the action
This commit is contained in:
Korey Sewell 2011-06-19 21:43:38 -04:00
parent c95fe261ab
commit db8b1e4b78
5 changed files with 40 additions and 17 deletions

View file

@ -105,7 +105,7 @@ std::string InOrderCPU::eventNames[NumCPUEvents] =
"HaltThread", "HaltThread",
"SuspendThread", "SuspendThread",
"Trap", "Trap",
"InstGraduated", "Syscall",
"SquashFromMemStall", "SquashFromMemStall",
"UpdatePCs" "UpdatePCs"
}; };
@ -151,6 +151,11 @@ InOrderCPU::CPUEvent::process()
cpu->resPool->trap(fault, tid, inst); cpu->resPool->trap(fault, tid, inst);
break; break;
case Syscall:
cpu->syscall(inst->syscallNum, tid);
cpu->resPool->trap(fault, tid, inst);
break;
default: default:
fatal("Unrecognized Event Type %s", eventNames[cpuEventType]); fatal("Unrecognized Event Type %s", eventNames[cpuEventType]);
} }
@ -1068,9 +1073,6 @@ InOrderCPU::activateNextReadyContext(int delay)
{ {
DPRINTF(InOrderCPU,"Activating next ready thread\n"); DPRINTF(InOrderCPU,"Activating next ready thread\n");
// NOTE: Add 5 to the event priority so that we always activate
// threads after we've finished deactivating, squashing,etc.
// other threads
scheduleCpuEvent(ActivateNextReadyThread, NoFault, 0/*tid*/, dummyInst[0], scheduleCpuEvent(ActivateNextReadyThread, NoFault, 0/*tid*/, dummyInst[0],
delay, ActivateNextReadyThread_Pri); delay, ActivateNextReadyThread_Pri);
@ -1382,11 +1384,6 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
// Check for instruction-count-based events. // Check for instruction-count-based events.
comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
// Broadcast to other resources an instruction
// has been completed
resPool->scheduleEvent((CPUEventType)ResourcePool::InstGraduated, inst,
0, 0, tid);
// Finally, remove instruction from CPU // Finally, remove instruction from CPU
removeInst(inst); removeInst(inst);
} }
@ -1600,6 +1597,12 @@ InOrderCPU::wakeup()
#endif #endif
#if !FULL_SYSTEM #if !FULL_SYSTEM
void
InOrderCPU::syscallContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay)
{
scheduleCpuEvent(Syscall, fault, tid, inst, delay, Syscall_Pri);
}
void void
InOrderCPU::syscall(int64_t callnum, ThreadID tid) InOrderCPU::syscall(int64_t callnum, ThreadID tid)
{ {

View file

@ -182,7 +182,7 @@ class InOrderCPU : public BaseCPU
HaltThread, HaltThread,
SuspendThread, SuspendThread,
Trap, Trap,
InstGraduated, Syscall,
SquashFromMemStall, SquashFromMemStall,
UpdatePCs, UpdatePCs,
NumCPUEvents NumCPUEvents
@ -192,6 +192,7 @@ class InOrderCPU : public BaseCPU
enum CPUEventPri { enum CPUEventPri {
InOrderCPU_Pri = Event::CPU_Tick_Pri, InOrderCPU_Pri = Event::CPU_Tick_Pri,
Syscall_Pri = Event::CPU_Tick_Pri + 9,
ActivateNextReadyThread_Pri = Event::CPU_Tick_Pri + 10 ActivateNextReadyThread_Pri = Event::CPU_Tick_Pri + 10
}; };
@ -207,6 +208,7 @@ class InOrderCPU : public BaseCPU
DynInstPtr inst; DynInstPtr inst;
Fault fault; Fault fault;
unsigned vpe; unsigned vpe;
short syscall_num;
public: public:
/** Constructs a CPU event. */ /** Constructs a CPU event. */
@ -436,6 +438,13 @@ class InOrderCPU : public BaseCPU
/** Check if this address is a valid data address. */ /** Check if this address is a valid data address. */
bool validDataAddr(Addr addr) { return true; } bool validDataAddr(Addr addr) { return true; }
#else
/** Schedule a syscall on the CPU */
void syscallContext(Fault fault, ThreadID tid, DynInstPtr inst,
int delay = 0);
/** Executes a syscall.*/
void syscall(int64_t callnum, ThreadID tid);
#endif #endif
/** Schedule a trap on the CPU */ /** Schedule a trap on the CPU */
@ -650,9 +659,6 @@ class InOrderCPU : public BaseCPU
Fault write(DynInstPtr inst, uint8_t *data, unsigned size, Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
Addr addr, unsigned flags, uint64_t *write_res = NULL); Addr addr, unsigned flags, uint64_t *write_res = NULL);
/** Executes a syscall.*/
void syscall(int64_t callnum, ThreadID tid);
public: public:
/** Per-Thread List of all the instructions in flight. */ /** Per-Thread List of all the instructions in flight. */
std::list<DynInstPtr> instList[ThePipeline::MaxThreads]; std::list<DynInstPtr> instList[ThePipeline::MaxThreads];

View file

@ -296,7 +296,8 @@ InOrderDynInst::simPalCheck(int palFunc)
void void
InOrderDynInst::syscall(int64_t callnum) InOrderDynInst::syscall(int64_t callnum)
{ {
cpu->syscall(callnum, this->threadNumber); syscallNum = callnum;
cpu->syscallContext(NoFault, this->threadNumber, this);
} }
#endif #endif

View file

@ -385,6 +385,9 @@ class InOrderDynInst : public FastAlloc, public RefCounted
bool isQuiesce() const { return staticInst->isQuiesce(); } bool isQuiesce() const { return staticInst->isQuiesce(); }
bool isIprAccess() const { return staticInst->isIprAccess(); } bool isIprAccess() const { return staticInst->isIprAccess(); }
bool isUnverifiable() const { return staticInst->isUnverifiable(); } bool isUnverifiable() const { return staticInst->isUnverifiable(); }
bool isSyscall() const
{ return staticInst->isSyscall(); }
///////////////////////////////////////////// /////////////////////////////////////////////
// //
@ -509,6 +512,8 @@ class InOrderDynInst : public FastAlloc, public RefCounted
void trap(Fault fault); void trap(Fault fault);
bool simPalCheck(int palFunc); bool simPalCheck(int palFunc);
#else #else
short syscallNum;
/** Calls a syscall. */ /** Calls a syscall. */
void syscall(int64_t callnum); void syscall(int64_t callnum);
#endif #endif

View file

@ -89,6 +89,8 @@ ExecutionUnit::execute(int slot_num)
DynInstPtr inst = reqs[slot_num]->inst; DynInstPtr inst = reqs[slot_num]->inst;
Fault fault = NoFault; Fault fault = NoFault;
Tick cur_tick = curTick(); Tick cur_tick = curTick();
unsigned stage_num = exec_req->getStageNum();
ThreadID tid = inst->readTid();
#if TRACING_ON #if TRACING_ON
InstSeqNum seq_num = inst->seqNum; InstSeqNum seq_num = inst->seqNum;
#endif #endif
@ -149,13 +151,10 @@ ExecutionUnit::execute(int slot_num)
assert(inst->isControl()); assert(inst->isControl());
// Set up Squash Generated By this Misprediction // Set up Squash Generated By this Misprediction
unsigned stage_num = exec_req->getStageNum();
ThreadID tid = inst->readTid();
TheISA::PCState pc = inst->pcState(); TheISA::PCState pc = inst->pcState();
TheISA::advancePC(pc, inst->staticInst); TheISA::advancePC(pc, inst->staticInst);
inst->setPredTarg(pc); inst->setPredTarg(pc);
inst->setSquashInfo(stage_num); inst->setSquashInfo(stage_num);
setupSquash(inst, stage_num, tid); setupSquash(inst, stage_num, tid);
DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i] Squashing from " DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i] Squashing from "
@ -210,6 +209,15 @@ ExecutionUnit::execute(int slot_num)
seq_num, seq_num,
(inst->resultType(0) == InOrderDynInst::Float) ? (inst->resultType(0) == InOrderDynInst::Float) ?
inst->readFloatResult(0) : inst->readIntResult(0)); inst->readFloatResult(0) : inst->readIntResult(0));
#if !FULL_SYSTEM
// The Syscall might change the PC, so conservatively
// squash everything behing it
if (inst->isSyscall()) {
inst->setSquashInfo(stage_num);
setupSquash(inst, stage_num, tid);
}
#endif
} else { } else {
DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: had a %s " DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: had a %s "
"fault.\n", inst->readTid(), seq_num, fault->name()); "fault.\n", inst->readTid(), seq_num, fault->name());