arch-arm: Add FaultCB callbacks to the MiscRegLUTEntry class
This patch is adding per-EL read/write callbacks to the MiscRegLUTEntry class. The goal is to merge access permission and trapping logic into these unified callbacks As of now the default callbacks are simply reimplementing the access permission code, checking for MiscRegLUTEntry flags. This is the default behaviour for all registers. Trapping code (from MiscRegOp64::trap) will be moved with a later patch Change-Id: Ib4bb1b5d95319548de5e77e00258fd65c11d88d7 Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/61675 Maintainer: Andreas Sandberg <andreas.sandberg@arm.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Richard Cooper <richard.cooper@arm.com> Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
@@ -39,6 +39,7 @@
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "arch/arm/insts/misc64.hh"
|
||||
#include "arch/arm/isa.hh"
|
||||
#include "base/logging.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
@@ -1332,6 +1333,92 @@ encodeAArch64SysReg(MiscRegIndex misc_reg)
|
||||
}
|
||||
}
|
||||
|
||||
Fault
|
||||
MiscRegLUTEntry::checkFault(ThreadContext *tc,
|
||||
const MiscRegOp64 &inst, ExceptionLevel el)
|
||||
{
|
||||
return !inst.miscRead() ? faultWrite[el](*this, tc, inst) :
|
||||
faultRead[el](*this, tc, inst);
|
||||
}
|
||||
|
||||
template <MiscRegInfo Sec, MiscRegInfo NonSec>
|
||||
Fault
|
||||
MiscRegLUTEntry::defaultFault(const MiscRegLUTEntry &entry,
|
||||
ThreadContext *tc, const MiscRegOp64 &inst)
|
||||
{
|
||||
if (isSecureBelowEL3(tc) ? entry.info[Sec] : entry.info[NonSec]) {
|
||||
return NoFault;
|
||||
} else {
|
||||
return inst.undefined();
|
||||
}
|
||||
}
|
||||
|
||||
Fault
|
||||
MiscRegLUTEntry::defaultReadFaultEL2(const MiscRegLUTEntry &entry,
|
||||
ThreadContext *tc, const MiscRegOp64 &inst)
|
||||
{
|
||||
const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
|
||||
const bool el2_host = EL2Enabled(tc) && hcr.e2h;
|
||||
if (el2_host) {
|
||||
return defaultFault<MISCREG_HYP_E2H_S_RD, MISCREG_HYP_E2H_NS_RD>(
|
||||
entry, tc, inst);
|
||||
} else {
|
||||
return defaultFault<MISCREG_HYP_S_RD, MISCREG_HYP_NS_RD>(
|
||||
entry, tc, inst);
|
||||
}
|
||||
}
|
||||
|
||||
Fault
|
||||
MiscRegLUTEntry::defaultWriteFaultEL2(const MiscRegLUTEntry &entry,
|
||||
ThreadContext *tc, const MiscRegOp64 &inst)
|
||||
{
|
||||
const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
|
||||
const bool el2_host = EL2Enabled(tc) && hcr.e2h;
|
||||
if (el2_host) {
|
||||
return defaultFault<MISCREG_HYP_E2H_S_WR, MISCREG_HYP_E2H_NS_WR>(
|
||||
entry, tc, inst);
|
||||
} else {
|
||||
return defaultFault<MISCREG_HYP_S_WR, MISCREG_HYP_NS_WR>(
|
||||
entry, tc, inst);
|
||||
}
|
||||
}
|
||||
|
||||
Fault
|
||||
MiscRegLUTEntry::defaultReadFaultEL3(const MiscRegLUTEntry &entry,
|
||||
ThreadContext *tc, const MiscRegOp64 &inst)
|
||||
{
|
||||
const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
|
||||
const bool el2_host = EL2Enabled(tc) && hcr.e2h;
|
||||
if (el2_host) {
|
||||
if (entry.info[MISCREG_MON_E2H_RD]) {
|
||||
return NoFault;
|
||||
} else {
|
||||
return inst.undefined();
|
||||
}
|
||||
} else {
|
||||
return defaultFault<MISCREG_MON_NS0_RD, MISCREG_MON_NS1_RD>(
|
||||
entry, tc, inst);
|
||||
}
|
||||
}
|
||||
|
||||
Fault
|
||||
MiscRegLUTEntry::defaultWriteFaultEL3(const MiscRegLUTEntry &entry,
|
||||
ThreadContext *tc, const MiscRegOp64 &inst)
|
||||
{
|
||||
const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
|
||||
const bool el2_host = EL2Enabled(tc) && hcr.e2h;
|
||||
if (el2_host) {
|
||||
if (entry.info[MISCREG_MON_E2H_WR]) {
|
||||
return NoFault;
|
||||
} else {
|
||||
return inst.undefined();
|
||||
}
|
||||
} else {
|
||||
return defaultFault<MISCREG_MON_NS0_WR, MISCREG_MON_NS1_WR>(
|
||||
entry, tc, inst);
|
||||
}
|
||||
}
|
||||
|
||||
MiscRegLUTEntryInitializer::chain
|
||||
MiscRegLUTEntryInitializer::highest(ArmSystem *const sys) const
|
||||
{
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <tuple>
|
||||
|
||||
#include "arch/arm/regs/misc_types.hh"
|
||||
#include "arch/arm/types.hh"
|
||||
#include "base/compiler.hh"
|
||||
#include "cpu/reg_class.hh"
|
||||
#include "debug/MiscRegs.hh"
|
||||
@@ -55,6 +56,7 @@ namespace gem5
|
||||
|
||||
class ArmSystem;
|
||||
class ThreadContext;
|
||||
class MiscRegOp64;
|
||||
|
||||
namespace ArmISA
|
||||
{
|
||||
@@ -1163,10 +1165,43 @@ namespace ArmISA
|
||||
uint64_t _raz; // read as zero (fixed at 0)
|
||||
uint64_t _rao; // read as one (fixed at 1)
|
||||
std::bitset<NUM_MISCREG_INFOS> info;
|
||||
|
||||
using FaultCB = std::function<
|
||||
Fault(const MiscRegLUTEntry &entry, ThreadContext *tc,
|
||||
const MiscRegOp64 &inst)
|
||||
>;
|
||||
|
||||
std::array<FaultCB, EL3 + 1> faultRead;
|
||||
std::array<FaultCB, EL3 + 1> faultWrite;
|
||||
|
||||
Fault checkFault(ThreadContext *tc, const MiscRegOp64 &inst,
|
||||
ExceptionLevel el);
|
||||
|
||||
protected:
|
||||
template <MiscRegInfo Sec, MiscRegInfo NonSec>
|
||||
static Fault defaultFault(const MiscRegLUTEntry &entry,
|
||||
ThreadContext *tc, const MiscRegOp64 &inst);
|
||||
static Fault defaultReadFaultEL2(const MiscRegLUTEntry &entry,
|
||||
ThreadContext *tc, const MiscRegOp64 &inst);
|
||||
static Fault defaultWriteFaultEL2(const MiscRegLUTEntry &entry,
|
||||
ThreadContext *tc, const MiscRegOp64 &inst);
|
||||
static Fault defaultReadFaultEL3(const MiscRegLUTEntry &entry,
|
||||
ThreadContext *tc, const MiscRegOp64 &inst);
|
||||
static Fault defaultWriteFaultEL3(const MiscRegLUTEntry &entry,
|
||||
ThreadContext *tc, const MiscRegOp64 &inst);
|
||||
|
||||
public:
|
||||
MiscRegLUTEntry() :
|
||||
lower(0), upper(0),
|
||||
_reset(0), _res0(0), _res1(0), _raz(0), _rao(0), info(0)
|
||||
_reset(0), _res0(0), _res1(0), _raz(0), _rao(0), info(0),
|
||||
faultRead({ defaultFault<MISCREG_USR_S_RD, MISCREG_USR_NS_RD>,
|
||||
defaultFault<MISCREG_PRI_S_RD, MISCREG_PRI_NS_RD>,
|
||||
defaultReadFaultEL2,
|
||||
defaultReadFaultEL3 }),
|
||||
faultWrite({ defaultFault<MISCREG_USR_S_WR, MISCREG_USR_NS_WR>,
|
||||
defaultFault<MISCREG_PRI_S_WR, MISCREG_PRI_NS_WR>,
|
||||
defaultWriteFaultEL2,
|
||||
defaultWriteFaultEL3 })
|
||||
{}
|
||||
uint64_t reset() const { return _reset; }
|
||||
uint64_t res0() const { return _res0; }
|
||||
@@ -1591,6 +1626,33 @@ namespace ArmISA
|
||||
return *this;
|
||||
}
|
||||
chain highest(ArmSystem *const sys) const;
|
||||
|
||||
chain
|
||||
faultRead(ExceptionLevel el, MiscRegLUTEntry::FaultCB cb) const
|
||||
{
|
||||
entry.faultRead[el] = cb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
chain
|
||||
faultWrite(ExceptionLevel el, MiscRegLUTEntry::FaultCB cb) const
|
||||
{
|
||||
entry.faultWrite[el] = cb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
chain
|
||||
fault(ExceptionLevel el, MiscRegLUTEntry::FaultCB cb) const
|
||||
{
|
||||
return faultRead(el, cb).faultWrite(el, cb);
|
||||
}
|
||||
|
||||
chain
|
||||
fault(MiscRegLUTEntry::FaultCB cb) const
|
||||
{
|
||||
return fault(EL0, cb).fault(EL1, cb).fault(EL2, cb).fault(EL3, cb);
|
||||
}
|
||||
|
||||
MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e)
|
||||
: entry(e)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user