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:
Giacomo Travaglini
2022-07-07 14:58:47 +01:00
parent 167cf86375
commit 5f67c7e54d
2 changed files with 150 additions and 1 deletions

View File

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

View File

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