Jordi Vaquero has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/30618 )
Change subject: arch-arm: Implementation of Vector Catch debug exception
......................................................................
arch-arm: Implementation of Vector Catch debug exception
This commit implements Vector Catch exception as they are described
in Armv8 reference manual chapter G2. This exception is just for AArch32.
+ tlb.cc: Implements the entry point for vector catch in addres mode
+ faults.hh/cc: Implements the entry point for vector catch in exception
trap mode.
+ miscregs.cc: enables the use of vector catch releated registers
+ miscregs_types.hh: New bitwise type for vector catch control registers.
+ types.hh: declaration of EC for vector catch exception
+ self_debug.hh/cc: Main implementation of the vector catch functions to
match address and exceptions type.
Change-Id: Idbef26b16eff059e94ff16fac13bf5708dfe647f
---
M src/arch/arm/faults.cc
M src/arch/arm/faults.hh
M src/arch/arm/miscregs.cc
M src/arch/arm/miscregs_types.hh
M src/arch/arm/self_debug.cc
M src/arch/arm/self_debug.hh
M src/arch/arm/tlb.cc
M src/arch/arm/types.hh
8 files changed, 321 insertions(+), 7 deletions(-)
diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc
index fde28d6..422e801 100644
--- a/src/arch/arm/faults.cc
+++ b/src/arch/arm/faults.cc
@@ -42,6 +42,8 @@
#include "arch/arm/faults.hh"
#include "arch/arm/insts/static_inst.hh"
+#include "arch/arm/isa.hh"
+#include "arch/arm/self_debug.hh"
#include "arch/arm/system.hh"
#include "arch/arm/utility.hh"
#include "base/compiler.hh"
@@ -481,6 +483,16 @@
ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
+ auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
+ SelfDebug * sd = isa->getSelfDebug();
+ VectorCatch* vc = sd->getVectorCatch(tc);
+ if (!vc->isVCMatch()){
+ Fault flt = sd->testVectorCatch(tc, 0x0, this);
+ if (flt != NoFault)
+ flt->invoke(tc, inst);
+ return;
+ }
+
// Update fault state informations, like the starting mode (aarch32)
// or EL (aarch64) and the ending mode or EL.
// From the update function we are also evaluating if the fault must
@@ -1094,7 +1106,9 @@
tc->setMiscReg(T::FarIndex, faultAddr);
if (debug == ArmFault::BRKPOINT){
Rext.moe = 0x1;
- } else if (debug > ArmFault::BRKPOINT) {
+ } else if (debug == ArmFault::VECTORCATCH){
+ Rext.moe = 0x5;
+ } else if (debug > ArmFault::VECTORCATCH) {
Rext.moe = 0xa;
fsr.cm = (debug == ArmFault::WPOINT_CM)? 1 : 0;
}
diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh
index 703d6bb..a7bda4f 100644
--- a/src/arch/arm/faults.hh
+++ b/src/arch/arm/faults.hh
@@ -154,6 +154,7 @@
{
NODEBUG = 0,
BRKPOINT,
+ VECTORCATCH,
WPOINT_CM,
WPOINT_NOCM
};
@@ -246,7 +247,7 @@
virtual FSR getFsr(ThreadContext *tc) const { return 0; }
virtual void setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg);
virtual bool getFaultVAddr(Addr &va) const { return false; }
-
+ OperatingMode getToMode() const { return toMode; }
};
template<typename T>
diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc
index aae12d5..d5eb757 100644
--- a/src/arch/arm/miscregs.cc
+++ b/src/arch/arm/miscregs.cc
@@ -61,6 +61,8 @@
return MISCREG_DBGDIDR;
case 1:
return MISCREG_DBGDSCRint;
+ case 7:
+ return MISCREG_DBGVCR;
}
break;
case 2:
@@ -564,6 +566,12 @@
return MISCREG_BPIALLIS;
}
break;
+ case 2:
+ switch (opc2){
+ case 7:
+ return MISCREG_DBGDEVID0;
+ }
+ break;
case 4:
if (opc2 == 0) {
return MISCREG_PAR;
@@ -3418,8 +3426,7 @@
.unimplemented()
.allPrivileges();
InitReg(MISCREG_DBGVCR)
- .unimplemented()
- .allPrivileges();
+ .allPrivileges().exceptUserMode();
InitReg(MISCREG_DBGDTRRXext)
.unimplemented()
.allPrivileges();
@@ -3625,7 +3632,6 @@
.unimplemented()
.allPrivileges().monSecureWrite(0).monNonSecureWrite(0);
InitReg(MISCREG_DBGDEVID0)
- .unimplemented()
.allPrivileges().monSecureWrite(0).monNonSecureWrite(0);
InitReg(MISCREG_TEECR)
.unimplemented()
@@ -4532,7 +4538,7 @@
InitReg(MISCREG_MDDTRRX_EL0)
.allPrivileges();
InitReg(MISCREG_DBGVCR32_EL2)
- .allPrivileges()
+ .allPrivileges().exceptUserMode()
.mapsTo(MISCREG_DBGVCR);
InitReg(MISCREG_MDRAR_EL1)
.allPrivileges().monSecureWrite(0).monNonSecureWrite(0)
diff --git a/src/arch/arm/miscregs_types.hh b/src/arch/arm/miscregs_types.hh
index 301d6fb..d3787ff 100644
--- a/src/arch/arm/miscregs_types.hh
+++ b/src/arch/arm/miscregs_types.hh
@@ -735,6 +735,44 @@
Bitfield<5, 2> moe;
Bitfield<1, 0> res0_1;
EndBitUnion(DBGDS32)
+
+ BitUnion32(DBGVCR)
+ Bitfield<31> nsf;
+ Bitfield<30> nsi;
+ Bitfield<29> res0_5;
+ Bitfield<28> nsd;
+ Bitfield<27> nsp;
+ Bitfield<26> nss;
+ Bitfield<25> nsu;
+ Bitfield<24, 16> res0_4;
+ Bitfield<15> mf;
+ Bitfield<14> mi;
+ Bitfield<13> res0_3;
+ Bitfield<12> md;
+ Bitfield<11> mp;
+ Bitfield<10> ms;
+ Bitfield<9,8> res0_2;
+ Bitfield<7> sf;
+ Bitfield<6> si;
+ Bitfield<5> res0_1;
+ Bitfield<4> sd;
+ Bitfield<3> sp;
+ Bitfield<2> ss;
+ Bitfield<1> su;
+ Bitfield<0> res0_0;
+ EndBitUnion(DBGVCR)
+
+ BitUnion32(DEVID)
+ Bitfield<31,28> cidmask;
+ Bitfield<27,24> auxregs;
+ Bitfield<23,20> doublelock;
+ Bitfield<19,16> virtextns;
+ Bitfield<15,12> vectorcatch;
+ Bitfield<11,8> bpaddremask;
+ Bitfield<7,4> wpaddrmask;
+ Bitfield<3,0> pcsample;
+ EndBitUnion(DEVID)
+
}
#endif // __ARCH_ARM_MISCREGS_TYPES_HH__
diff --git a/src/arch/arm/self_debug.cc b/src/arch/arm/self_debug.cc
index 53cbb8e..5bc4ad4 100644
--- a/src/arch/arm/self_debug.cc
+++ b/src/arch/arm/self_debug.cc
@@ -620,3 +620,196 @@
return res;
}
+Fault
+SelfDebug::testVectorCatch(ThreadContext *tc, Addr addr,
+ ArmFault* flt)
+{
+
+ setAArch32(tc);
+ to32 = targetAArch32(tc);
+ if (!initialized)
+ init(tc);
+ if (!isDebugEnabled(tc) || !enableFlag || !aarch32)
+ return NoFault;
+
+ ExceptionLevel el = (ExceptionLevel) currEL(tc);
+ bool debug;
+ if (flt == nullptr)
+ debug = vcExcpt->VCRtest(tc, addr, el);
+ else
+ debug = vcExcpt->trapTest(tc, el, flt);
+ if (debug){
+ if (enableTdeTge) {
+ return std::make_shared<HypervisorTrap>(0, 0x22,
+ EC_PREFETCH_ABORT_TO_HYP);
+ } else {
+ return std::make_shared<PrefetchAbort>(addr,
+ ArmFault::DebugEvent, false,
+ ArmFault::UnknownTran,
+ ArmFault::VECTORCATCH);
+ }
+ //cctypd = AccType_IFETCH;
+ //iswrite = FALSE;
+ //debugmoe = DebugException_VectorCatch;
+ //return trigger Exception Vector Catch
+ }
+
+ return NoFault;
+}
+
+bool
+VectorCatch::VCRtest(ThreadContext *tc, Addr addr, ExceptionLevel el)
+{
+ // Each bit position in this string corresponds to a bit in DBGVCR
+ // and an exception vector.
+ bool enabled;
+ if (conf->isAArch32() && ELIs32(tc, EL1)
+ && (addr & 0x3) == 0 && el != EL2 ){
+
+ DBGVCR match_word = 0x0;
+
+ uint32_t vbase = getVectorBase(tc, false);
+ Addr vaddress = addr & ~ 0x1f;
+ uint32_t low_addr = bits(addr, 5, 2);
+ if (vaddress == vbase)
+ {
+ if (ArmSystem::haveEL(tc, EL3) && !inSecureState(tc)){
+ uint32_t bmask = pow(2, low_addr +24);
+ match_word = match_word | (DBGVCR) bmask;
+ // Non-secure vectors
+ }
+ else
+ {
+ uint32_t bmask = pow(2, low_addr);
+ match_word = match_word | (DBGVCR) bmask;
+ // Secure vectors (or no EL3)
+ }
+ }
+ uint32_t mvbase = getVectorBase(tc, true);
+ if (ArmSystem::haveEL(tc, EL3) && ELIs32(tc, EL3)
+ && inSecureState(tc) && (vaddress == mvbase)){
+
+ uint32_t bmask = pow(2, low_addr +8);
+ match_word = match_word | (DBGVCR) bmask;
+ // Monitor vectors
+ }
+
+ DBGVCR mask;
+
+ // Mask out bits not corresponding to vectors.
+ if (!ArmSystem::haveEL(tc, EL3)){
+ mask = (DBGVCR) 0xDE;
+ }else if (!ELIs32(tc, EL3)){
+ mask = (DBGVCR) 0xDE0000DE;
+ }else{
+ mask = (DBGVCR) 0xDE00DEDE;
+ }
+ DBGVCR dbgvcr = tc->readMiscReg(MISCREG_DBGVCR);
+ match_word = match_word & dbgvcr & mask;
+ enabled = match_word != 0x0;
+ // Check for UNPREDICTABLE case - match on Prefetch Abort and
+ // Data Abort vectors
+ ExceptionLevel ELd = debugTargetFrom(tc, inSecureState(tc));
+ if (((match_word & 0x18001818) != 0x0) && ELd == el){
+ enabled = false;
+ }
+ }else{
+ enabled = false;
+ }
+ return enabled;
+}
+
+
+uint32_t
+VectorCatch::faultTypeToFlag(ArmFault* flt)
+{
+ {
+ FastInterrupt* f = dynamic_cast<FastInterrupt*>(flt);
+ if (f != nullptr)
+ {
+ return 0x80008080;
+ }
+ }
+ {
+ Interrupt* f = dynamic_cast<Interrupt*>(flt);
+ if (f != nullptr)
+ {
+ return 0x40004040;
+ }
+ }
+ {
+ DataAbort* f = dynamic_cast<DataAbort*>(flt);
+ if (f != nullptr)
+ {
+ return 0x10001010;
+ }
+ }
+ {
+ PrefetchAbort* f = dynamic_cast<PrefetchAbort*>(flt);
+ if (f != nullptr)
+ {
+ return 0x08000808;
+ }
+ }
+ {
+ SupervisorCall* f = dynamic_cast<SupervisorCall*>(flt);
+ if (f != nullptr)
+ {
+ return 0x04000404;
+ }
+ }
+ {
+ UndefinedInstruction* f = dynamic_cast<UndefinedInstruction*>(flt);
+ if (f != nullptr)
+ {
+ return 0x02000002;
+ }
+ }
+ {
+ HypervisorTrap* f = dynamic_cast<HypervisorTrap*>(flt);
+ if (f != nullptr)
+ {
+ // HYP does not have flag, so is always accepted if EL enables
it.
+ return 0xFFFFFFFF;
+ }
+ }
+ {
+ SecureMonitorCall* f = dynamic_cast<SecureMonitorCall*>(flt);
+ if (f != nullptr)
+ {
+ return 0x00000400;
+ }
+ }
+ return 0x0;
+}
+
+bool
+VectorCatch::trapTest(ThreadContext *tc, ExceptionLevel el, ArmFault * flt)
+{
+ if (conf->isAArch32() && ELIs32(tc, EL1)
+ && el != EL2){
+ DBGVCR dbgvcr = tc->readMiscReg(MISCREG_DBGVCR);
+
+ DBGVCR match_type = faultTypeToFlag(flt);
+
+ DBGVCR mask;
+ if (!ArmSystem::haveEL(tc, EL3)){
+ mask = (DBGVCR) 0xDE;
+ }else if (ELIs32(tc, EL3) && flt->getToMode() == MODE_MON){
+ mask = (DBGVCR) 0x0000DE00;
+ } else {
+ if (inSecureState(tc))
+ mask = (DBGVCR) 0x000000DE;
+ else
+ mask = (DBGVCR) 0xDE000000;
+ }
+ match_type = match_type & mask & dbgvcr;
+
+ if (match_type != 0x0){
+ return true;
+ }
+
+ }
+ return false;
+}
+
diff --git a/src/arch/arm/self_debug.hh b/src/arch/arm/self_debug.hh
index 1404d27..8f7e0bc 100644
--- a/src/arch/arm/self_debug.hh
+++ b/src/arch/arm/self_debug.hh
@@ -263,12 +263,60 @@
}
};
+class VectorCatch
+{
+ private:
+ bool vcmatch;
+ SelfDebug * conf;
+ std::vector<Fault *> vectorTypes();
+
+
+ public:
+ VectorCatch(bool _vcmatch, SelfDebug* s) : vcmatch(_vcmatch), conf(s)
+ {
+
+
+ }
+
+ ~VectorCatch()
+ {}
+
+ bool VCRtest(ThreadContext *tc, Addr addr, ExceptionLevel el);
+ bool trapTest(ThreadContext *tc, ExceptionLevel el, ArmFault * flt);
+ bool isVCMatch()
+ {
+ return vcmatch;
+ }
+
+
+ private:
+ uint32_t faultTypeToFlag(ArmFault* flt);
+ uint32_t getVectorBase(ThreadContext *tc, bool monitor)
+ {
+ if (monitor){
+
+ return tc->readMiscReg(MISCREG_MVBAR) & ~0x1F;
+ }
+ SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1);
+ if (sctlr.v){
+ return 0xFFFF0000;
+ }
+ else
+ {
+ uint32_t vbar = tc->readMiscReg(MISCREG_VBAR) & ~0x1F;
+ return vbar;
+ }
+ }
+
+};
+
class SelfDebug
{
private:
std::vector<BrkPoint> arBrkPoints;
std::vector<WatchPoint> arWatchPoints;
SoftwareStep * softStep;
+ VectorCatch * vcExcpt;
bool initialized;
bool enableTdeTge; // MDCR_EL2.TDE || HCR_EL2.TGE
@@ -292,6 +340,7 @@
~SelfDebug(){
delete softStep;
+ delete vcExcpt;
}
Fault testBreakPoints(ThreadContext *tc, Addr vaddr);
@@ -392,6 +441,7 @@
{
softStep->setCPSR_D(mask);
}
+
inline bool isAArch32()
{
return aarch32;
@@ -414,6 +464,11 @@
return softStep;
}
+ VectorCatch* getVectorCatch(ThreadContext* tc){
+ if (!initialized)
+ init(tc);
+ return vcExcpt;
+ }
bool targetAArch32(ThreadContext * tc)
{
@@ -472,6 +527,10 @@
const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
setenableTDETGE(hcr, mdcr);
+ // Enable Vector Catch Exceptions
+ const DEVID dvid = tc->readMiscReg(MISCREG_DBGDEVID0);
+ vcExcpt = new VectorCatch(dvid.vectorcatch==0x0, this);
+
}
};
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 4fa9590..fdfc6b7 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -1201,7 +1201,9 @@
{
const bool d_step = sd->get_Sstep()->advanceSS(tc, true);
if (!d_step){
- fault = sd->testBreakPoints(tc, req->getVaddr());
+ fault = sd->testVectorCatch(tc, req->getVaddr(), nullptr);
+ if (fault == NoFault)
+ fault = sd->testBreakPoints(tc, req->getVaddr());
}
}
else if (!req->isCacheMaintenance() ||
diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh
index 6e502bb..d3fd912 100644
--- a/src/arch/arm/types.hh
+++ b/src/arch/arm/types.hh
@@ -712,6 +712,7 @@
EC_WATCHPOINT_LOWER_EL = 0x34,
EC_WATCHPOINT_CURR_EL = 0x35,
EC_SOFTWARE_BREAKPOINT = 0x38,
+ EC_VECTOR_CATCH = 0x3A,
EC_SOFTWARE_BREAKPOINT_64 = 0x3C,
};
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/30618
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Idbef26b16eff059e94ff16fac13bf5708dfe647f
Gerrit-Change-Number: 30618
Gerrit-PatchSet: 1
Gerrit-Owner: Jordi Vaquero <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s