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:
Gabe Black
2020-08-23 01:33:22 -07:00
parent 3293926413
commit 0ad5d1edc5
21 changed files with 21 additions and 88 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -479,7 +479,7 @@ void
m5Syscall(ThreadContext *tc)
{
DPRINTF(PseudoInst, "PseudoInst::m5Syscall()\n");
tc->syscall();
tc->getSystemPtr()->workload->syscall(tc);
}
void

View File

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

View File

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

View File

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