diff --git a/src/arch/arm/regs/misc.cc b/src/arch/arm/regs/misc.cc index de46a98f21..69d1fc9132 100644 --- a/src/arch/arm/regs/misc.cc +++ b/src/arch/arm/regs/misc.cc @@ -39,6 +39,7 @@ #include +#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 +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( + entry, tc, inst); + } else { + return defaultFault( + 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( + entry, tc, inst); + } else { + return defaultFault( + 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( + 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( + entry, tc, inst); + } +} + MiscRegLUTEntryInitializer::chain MiscRegLUTEntryInitializer::highest(ArmSystem *const sys) const { diff --git a/src/arch/arm/regs/misc.hh b/src/arch/arm/regs/misc.hh index 6a8b9b05d0..4ecbb34fbf 100644 --- a/src/arch/arm/regs/misc.hh +++ b/src/arch/arm/regs/misc.hh @@ -45,6 +45,7 @@ #include #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 info; + + using FaultCB = std::function< + Fault(const MiscRegLUTEntry &entry, ThreadContext *tc, + const MiscRegOp64 &inst) + >; + + std::array faultRead; + std::array faultWrite; + + Fault checkFault(ThreadContext *tc, const MiscRegOp64 &inst, + ExceptionLevel el); + + protected: + template + 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, + defaultFault, + defaultReadFaultEL2, + defaultReadFaultEL3 }), + faultWrite({ defaultFault, + defaultFault, + 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) {