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:
parent
c95fe261ab
commit
db8b1e4b78
5 changed files with 40 additions and 17 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
Loading…
Reference in a new issue