Files
gem5/src/sim/faults.hh
Gabe Black 7aa9591151 arch: Use a fault to trigger system calls in SE mode.
When the system call happens during the execution of the system call
instruction, it can be ambiguous what state takes precedence, the state
update from the instruction or the system call. These may be tracked
differently and found in an unpredictable order in, for example, the O3
CPU. An instruction can avoid updating any state explicitly, but
implicitly updated state (specifically the PC) will always update,
whether the instruction wants it to or not.

If the system call can be deferred by using a Fault object, then it's no
longer ambiguous. The PC update will be discarded, and the system call
can set the PC however it likes. Because there is no implicit PC update,
the PC needs to be walked forward, either to what it would have been
anyway, or to what the system call set in NPC.

In addition, because of the existing semantics around handling Faults,
the instruction no longer needs to be marked as serializing,
non-speculative, etc.

The "normal", aka architectural, aka FS version of the system call
instructions don't return a Fault artificially.

Change-Id: I72011a16a89332b1dcfb01c79f2f0d75c55ab773
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/33281
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
2020-09-03 10:07:15 +00:00

125 lines
4.2 KiB
C++

/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FAULTS_HH__
#define __FAULTS_HH__
#include "base/types.hh"
#include "cpu/static_inst.hh"
#include "sim/stats.hh"
class ThreadContext;
typedef const char *FaultName;
typedef Stats::Scalar FaultStat;
class FaultBase
{
public:
virtual FaultName name() const = 0;
virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst=
StaticInst::nullStaticInstPtr);
virtual ~FaultBase() {};
};
class UnimpFault : public FaultBase
{
private:
std::string panicStr;
public:
UnimpFault(std::string _str) : panicStr(_str) {}
FaultName
name() const override
{
return "Unimplemented simulator feature";
}
void invoke(ThreadContext *tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr) override;
};
// A fault to trigger a system call in SE mode.
class SESyscallFault : public FaultBase
{
const char *name() const override { return "syscall_fault"; }
void invoke(ThreadContext *tc, const StaticInstPtr &inst=
StaticInst::nullStaticInstPtr) override;
};
class ReExec : public FaultBase
{
public:
virtual FaultName name() const override { return "Re-execution fault"; }
void invoke(ThreadContext *tc, const StaticInstPtr &inst=
StaticInst::nullStaticInstPtr) override;
};
/*
* This class is needed to allow system call retries to occur for blocking
* system calls in SE mode. A retry fault will be generated by the system call
* emulation code if blocking conditions arise; the fault is passed up the
* function call chain into the CPU model where it is handled by retrying the
* syscall instruction on a later tick.
*/
class SyscallRetryFault : public FaultBase
{
public:
FaultName name() const override { return "System call retry fault"; }
SyscallRetryFault() {}
void invoke(ThreadContext *tc, const StaticInstPtr &inst=
StaticInst::nullStaticInstPtr) override;
};
class GenericPageTableFault : public FaultBase
{
private:
Addr vaddr;
public:
FaultName name() const override { return "Generic page table fault"; }
GenericPageTableFault(Addr va) : vaddr(va) {}
void invoke(ThreadContext *tc, const StaticInstPtr &inst=
StaticInst::nullStaticInstPtr) override;
Addr getFaultVAddr() const { return vaddr; }
};
class GenericAlignmentFault : public FaultBase
{
private:
Addr vaddr;
public:
FaultName name() const override { return "Generic alignment fault"; }
GenericAlignmentFault(Addr va) : vaddr(va) {}
void invoke(ThreadContext *tc, const StaticInstPtr &inst=
StaticInst::nullStaticInstPtr) override;
Addr getFaultVAddr() const { return vaddr; }
};
#endif // __FAULTS_HH__