arch,cpu,sim: Route system calls through the workload.
System calls should now be requested from the workload directly and not routed through ExecContext or ThreadContext interfaces. That removes a major special case for SE mode from those interfaces. For now, when the SE workload gets a request for a system call, it dispatches it to the appropriate Process object. In the future, the ISA specific Workload subclasses will be responsible for handling system calls and not the Process classes. For simplicity, the Workload syscall() method is defined in the base class but will panic everywhere except when SEWorkload overrides it. In the future, this mechanism will turn into a way to request generic services from the workload which are not necessarily system calls. For instance, it could be a way to request handling of a page fault without having to have another PseudoInst just for that purpose. Change-Id: I18d36d64c54adf4f4f17a62e7e006ff2fc0b22f1 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/33282 Reviewed-by: Matthew Poremba <matthew.poremba@amd.com> Maintainer: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -865,7 +865,7 @@ SupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
||||
|
||||
// As of now, there isn't a 32 bit thumb version of this instruction.
|
||||
assert(!machInst.bigThumb);
|
||||
tc->syscall();
|
||||
tc->getSystemPtr()->workload->syscall(tc);
|
||||
|
||||
// Advance the PC since that won't happen automatically.
|
||||
PCState pc = tc->pcState();
|
||||
|
||||
@@ -194,7 +194,7 @@ BreakpointFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
|
||||
void
|
||||
SyscallFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
|
||||
{
|
||||
tc->syscall();
|
||||
tc->getSystemPtr()->workload->syscall(tc);
|
||||
}
|
||||
|
||||
} // namespace RiscvISA
|
||||
|
||||
@@ -92,7 +92,7 @@ Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc)
|
||||
{
|
||||
switch (trapNum) {
|
||||
case 0x10: //Linux 32 bit syscall trap
|
||||
tc->syscall();
|
||||
tc->getSystemPtr()->workload->syscall(tc);
|
||||
break;
|
||||
default:
|
||||
SparcProcess::handleTrap(trapNum, tc);
|
||||
@@ -129,7 +129,7 @@ Sparc64LinuxProcess::handleTrap(int trapNum, ThreadContext *tc)
|
||||
switch (trapNum) {
|
||||
// case 0x10: // Linux 32 bit syscall trap
|
||||
case 0x6d: // Linux 64 bit syscall trap
|
||||
tc->syscall();
|
||||
tc->getSystemPtr()->workload->syscall(tc);
|
||||
break;
|
||||
case 0x6e: // Linux 64 bit getcontext trap
|
||||
getContext(tc);
|
||||
|
||||
@@ -610,9 +610,6 @@ class CheckerCPU : public BaseCPU, public ExecContext
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
void wakeup(ThreadID tid) override { }
|
||||
// Assume that the normal CPU's call to syscall was successful.
|
||||
// The checker's state would have already been updated by the syscall.
|
||||
void syscall() override { }
|
||||
|
||||
void
|
||||
handleError()
|
||||
|
||||
@@ -171,9 +171,6 @@ class CheckerThreadContext : public ThreadContext
|
||||
actualTC->connectMemPorts(tc);
|
||||
}
|
||||
|
||||
/** Executes a syscall in SE mode. */
|
||||
void syscall() override { return actualTC->syscall(); }
|
||||
|
||||
Status status() const override { return actualTC->status(); }
|
||||
|
||||
void
|
||||
|
||||
@@ -300,18 +300,6 @@ class ExecContext {
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @name SysCall Emulation Interfaces
|
||||
*/
|
||||
|
||||
/**
|
||||
* Executes a syscall.
|
||||
*/
|
||||
virtual void syscall() = 0;
|
||||
|
||||
/** @} */
|
||||
|
||||
/** Returns a pointer to the ThreadContext. */
|
||||
virtual ThreadContext *tcBase() const = 0;
|
||||
|
||||
|
||||
@@ -419,8 +419,6 @@ class ExecContext : public ::ExecContext
|
||||
return thread.setMiscReg(reg.index(), val);
|
||||
}
|
||||
|
||||
void syscall() override { thread.syscall(); }
|
||||
|
||||
ThreadContext *tcBase() const override { return thread.getTC(); }
|
||||
|
||||
/* @todo, should make stCondFailures persistent somewhere */
|
||||
|
||||
@@ -912,26 +912,6 @@ FullO3CPU<Impl>::trap(const Fault &fault, ThreadID tid,
|
||||
fault->invoke(this->threadContexts[tid], inst);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::syscall(ThreadID tid)
|
||||
{
|
||||
DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
|
||||
|
||||
DPRINTF(Activity,"Activity: syscall() called.\n");
|
||||
|
||||
// Temporarily increase this by one to account for the syscall
|
||||
// instruction.
|
||||
++(this->thread[tid]->funcExeInst);
|
||||
|
||||
// Execute the actual syscall.
|
||||
this->thread[tid]->syscall();
|
||||
|
||||
// Decrease funcExeInst by one as the normal commit will handle
|
||||
// incrementing it.
|
||||
--(this->thread[tid]->funcExeInst);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::serializeThread(CheckpointOut &cp, ThreadID tid) const
|
||||
|
||||
@@ -276,11 +276,6 @@ class FullO3CPU : public BaseO3CPU
|
||||
void exitThreads();
|
||||
|
||||
public:
|
||||
/** Executes a syscall.
|
||||
* @todo: Determine if this needs to be virtual.
|
||||
*/
|
||||
void syscall(ThreadID tid);
|
||||
|
||||
/** Starts draining the CPU's pipeline of all instructions in
|
||||
* order to stop all memory accesses. */
|
||||
DrainState drain() override;
|
||||
|
||||
@@ -248,9 +248,6 @@ class BaseO3DynInst : public BaseDynInst<Impl>
|
||||
/** Traps to handle specified fault. */
|
||||
void trap(const Fault &fault);
|
||||
|
||||
/** Emulates a syscall. */
|
||||
void syscall() override;
|
||||
|
||||
public:
|
||||
|
||||
// The register accessor methods provide the index of the
|
||||
|
||||
@@ -187,19 +187,4 @@ BaseO3DynInst<Impl>::trap(const Fault &fault)
|
||||
this->cpu->trap(fault, this->threadNumber, this->staticInst);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
BaseO3DynInst<Impl>::syscall()
|
||||
{
|
||||
// HACK: check CPU's nextPC before and after syscall. If it
|
||||
// changes, update this instruction's nextPC because the syscall
|
||||
// must have changed the nextPC.
|
||||
TheISA::PCState curPC = this->cpu->pcState(this->threadNumber);
|
||||
this->cpu->syscall(this->threadNumber);
|
||||
TheISA::PCState newPC = this->cpu->pcState(this->threadNumber);
|
||||
if (!(curPC == newPC)) {
|
||||
this->pcState(newPC);
|
||||
}
|
||||
}
|
||||
|
||||
#endif//__CPU_O3_DYN_INST_IMPL_HH__
|
||||
|
||||
@@ -419,13 +419,6 @@ class O3ThreadContext : public ThreadContext
|
||||
thread->storeCondFailures = sc_failures;
|
||||
}
|
||||
|
||||
/** Executes a syscall in SE mode. */
|
||||
void
|
||||
syscall() override
|
||||
{
|
||||
return cpu->syscall(thread->threadId());
|
||||
}
|
||||
|
||||
/** Reads the funcExeInst counter. */
|
||||
Counter readFuncExeInst() const override { return thread->funcExeInst; }
|
||||
|
||||
|
||||
@@ -128,9 +128,6 @@ struct O3ThreadState : public ThreadState {
|
||||
|
||||
/** Returns a pointer to the TC of this thread. */
|
||||
ThreadContext *getTC() { return tc; }
|
||||
|
||||
/** Handles the syscall. */
|
||||
void syscall() { process->syscall(tc); }
|
||||
};
|
||||
|
||||
#endif // __CPU_O3_THREAD_STATE_HH__
|
||||
|
||||
@@ -496,11 +496,6 @@ class SimpleExecContext : public ExecContext {
|
||||
return thread->readStCondFailures();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a syscall specified by the callnum.
|
||||
*/
|
||||
void syscall() override { thread->syscall(); }
|
||||
|
||||
/** Returns a pointer to the ThreadContext. */
|
||||
ThreadContext *tcBase() const override { return thread->getTC(); }
|
||||
|
||||
|
||||
@@ -585,8 +585,6 @@ class SimpleThread : public ThreadState, public ThreadContext
|
||||
return ThreadState::readFuncExeInst();
|
||||
}
|
||||
|
||||
void syscall() override { process->syscall(this); }
|
||||
|
||||
RegVal readIntRegFlat(RegIndex idx) const override { return intRegs[idx]; }
|
||||
void
|
||||
setIntRegFlat(RegIndex idx, RegVal val) override
|
||||
|
||||
@@ -292,8 +292,6 @@ class ThreadContext : public PCEventScope
|
||||
// Same with st cond failures.
|
||||
virtual Counter readFuncExeInst() const = 0;
|
||||
|
||||
virtual void syscall() = 0;
|
||||
|
||||
// This function exits the thread context in the CPU and returns
|
||||
// 1 if the CPU has no more active threads (meaning it's OK to exit);
|
||||
// Used in syscall-emulation mode when a thread calls the exit syscall.
|
||||
|
||||
@@ -67,7 +67,7 @@ UnimpFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
||||
void
|
||||
SESyscallFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
||||
{
|
||||
tc->syscall();
|
||||
tc->getSystemPtr()->workload->syscall(tc);
|
||||
// Move the PC forward since that doesn't happen automatically.
|
||||
TheISA::PCState pc = tc->pcState();
|
||||
inst->advancePC(pc);
|
||||
|
||||
@@ -479,7 +479,7 @@ void
|
||||
m5Syscall(ThreadContext *tc)
|
||||
{
|
||||
DPRINTF(PseudoInst, "PseudoInst::m5Syscall()\n");
|
||||
tc->syscall();
|
||||
tc->getSystemPtr()->workload->syscall(tc);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -27,10 +27,17 @@
|
||||
|
||||
#include "sim/se_workload.hh"
|
||||
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "params/SEWorkload.hh"
|
||||
#include "sim/process.hh"
|
||||
|
||||
SEWorkload::SEWorkload(const Params &p) : Workload(&p), _params(p)
|
||||
{}
|
||||
|
||||
void
|
||||
SEWorkload::syscall(ThreadContext *tc)
|
||||
{
|
||||
tc->getProcessPtr()->syscall(tc);
|
||||
}
|
||||
|
||||
SEWorkload *
|
||||
|
||||
@@ -76,6 +76,8 @@ class SEWorkload : public Workload
|
||||
// within it.
|
||||
panic("No workload symbol table for syscall emulation mode.");
|
||||
}
|
||||
|
||||
void syscall(ThreadContext *tc) override;
|
||||
};
|
||||
|
||||
#endif // __SIM_SE_WORKLOAD_HH__
|
||||
|
||||
@@ -69,6 +69,12 @@ class Workload : public SimObject
|
||||
virtual const Loader::SymbolTable &symtab(ThreadContext *tc) = 0;
|
||||
virtual bool insertSymbol(const Loader::Symbol &symbol) = 0;
|
||||
|
||||
virtual void
|
||||
syscall(ThreadContext *tc)
|
||||
{
|
||||
panic("syscall() not implemented.");
|
||||
}
|
||||
|
||||
/** @{ */
|
||||
/**
|
||||
* Add a function-based event to the given function, to be looked
|
||||
|
||||
Reference in New Issue
Block a user