From 9c812d5aa9d1748da42c1e90df3895bfd90e474b Mon Sep 17 00:00:00 2001 From: Jordi Vaquero Date: Tue, 29 Oct 2019 16:28:30 +0100 Subject: [PATCH] arch-arm: Implementation of SelfHosted Debug Software step This commit implements SelfHosted Debug Software step as is defined in Armv8 Reference manual chapter D2. + decoder.hh/cc/isa: Checks the software step bit in order to skip the instruction before its decode. + faults.hh/cc: implemented SoftwareStep exception and proper modification of spsr during the invoke of other exceptions + isa.cc: Set debug mask if needed during cpsr modification + tlb.cc: Checks if software step is in ACTIVE state to avoid trigger breakpoint or watchpoint exception + self_debug.hh/cc: Implementation of State change and ss bit based during eret. + types.hh: Define sofware step flags like step, load or stepped to check the different flags that triggering software step should use for the ISS code. + pseudo.hh/isa: Triggers the sofware step esception after decode. + static_inst.cc: Call debugExceptionReturnsSS durint eret routine. Change-Id: I3a64507c64842c34c76ad7f6daa5f4306bd55d2c Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/30617 Reviewed-by: Giacomo Travaglini Maintainer: Giacomo Travaglini Tested-by: kokoro --- src/arch/arm/decoder.cc | 5 +- src/arch/arm/faults.cc | 59 +++++++++++++++++++- src/arch/arm/faults.hh | 28 ++++++++-- src/arch/arm/insts/pseudo.cc | 17 ++++++ src/arch/arm/insts/pseudo.hh | 8 +++ src/arch/arm/insts/static_inst.cc | 13 +++-- src/arch/arm/isa.cc | 1 + src/arch/arm/isa/bitfields.isa | 1 + src/arch/arm/isa/decoder/decoder.isa | 20 ++++--- src/arch/arm/isa/formats/pseudo.isa | 9 +++ src/arch/arm/isa/insts/ldr.isa | 13 +++++ src/arch/arm/isa/insts/ldr64.isa | 13 ++++- src/arch/arm/self_debug.cc | 71 ++++++++++++++++++++++++ src/arch/arm/self_debug.hh | 83 ++++++++++++++++++++++++++-- src/arch/arm/tlb.cc | 12 ++-- src/arch/arm/types.hh | 47 +++++++++++++++- 16 files changed, 364 insertions(+), 36 deletions(-) diff --git a/src/arch/arm/decoder.cc b/src/arch/arm/decoder.cc index 8f37e63db..d7de6a255 100644 --- a/src/arch/arm/decoder.cc +++ b/src/arch/arm/decoder.cc @@ -53,7 +53,8 @@ namespace ArmISA GenericISA::BasicDecodeCache Decoder::defaultCache; Decoder::Decoder(ISA* isa) - : data(0), fpscrLen(0), fpscrStride(0), decoderFlavor(isa->decoderFlavor()) + : data(0), fpscrLen(0), fpscrStride(0), + decoderFlavor(isa->decoderFlavor()) { reset(); @@ -181,7 +182,7 @@ Decoder::decode(ArmISA::PCState &pc) pc.nextItstate(itBits); this_emi.itstate = pc.itstate(); this_emi.illegalExecution = pc.illegalExec() ? 1 : 0; - + this_emi.debugStep = pc.debugStep() ? 1 : 0; pc.size(inst_size); emi = 0; diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index ce9675aee..6a3ee18ee 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -289,6 +289,10 @@ template<> ArmFault::FaultVals ArmFaultVals::vals( "Watchpoint", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 0, 0, 0, 0, true, false, false, EC_WATCHPOINT ); +template<> ArmFault::FaultVals ArmFaultVals::vals( + "SoftwareStep", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, + 0, 0, 0, 0, true, false, false, EC_SOFTWARE_STEP +); template<> ArmFault::FaultVals ArmFaultVals::vals( // Some dummy values "ArmSev Flush", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC, @@ -649,6 +653,7 @@ ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst) spsr.nz = tc->readCCReg(CCREG_NZ); spsr.c = tc->readCCReg(CCREG_C); spsr.v = tc->readCCReg(CCREG_V); + spsr.ss = isResetSPSR() ? 0: cpsr.ss; if (from64) { // Force some bitfields to 0 spsr.q = 0; @@ -662,8 +667,6 @@ ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst) ITSTATE it = tc->pcState().itstate(); spsr.it2 = it.top6; spsr.it1 = it.bottom2; - // Force some bitfields to 0 - spsr.ss = 0; } tc->setMiscReg(spsr_idx, spsr); @@ -705,6 +708,7 @@ ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst) pc.aarch64(!cpsr.width); pc.nextAArch64(!cpsr.width); pc.illegalExec(false); + pc.stepped(false); tc->pcState(pc); // Save exception syndrome @@ -911,7 +915,9 @@ UndefinedInstruction::ec(ThreadContext *tc) const HypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) : ArmFaultVals(_machInst, _imm) -{} +{ + bStep = true; +} ExceptionClass HypervisorCall::ec(ThreadContext *tc) const @@ -1739,6 +1745,52 @@ Watchpoint::ec(ThreadContext *tc) const return EC_WATCHPOINT_LOWER_EL; } +SoftwareStepFault::SoftwareStepFault(ExtMachInst _mach_inst, bool is_ldx, + bool _stepped) + : ArmFaultVals(_mach_inst), isldx(is_ldx), + stepped(_stepped) +{ + bStep = true; +} + +bool +SoftwareStepFault::routeToHyp(ThreadContext *tc) const +{ + const bool have_el2 = ArmSystem::haveVirtualization(tc); + + const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2); + const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2); + + return have_el2 && !inSecureState(tc) && fromEL <= EL1 && + (hcr.tge || mdcr.tde); +} + +ExceptionClass +SoftwareStepFault::ec(ThreadContext *tc) const +{ + // AArch64 + if (toEL == fromEL) + return EC_SOFTWARE_STEP_CURR_EL; + else + return EC_SOFTWARE_STEP_LOWER_EL; +} + +uint32_t +SoftwareStepFault::iss() const +{ + uint32_t iss= 0x0022; + if (stepped) { + iss |= 0x1000000; + } + + if (isldx) { + iss |= 0x40; + } + + return iss; + +} + void ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) { DPRINTF(Faults, "Invoking ArmSev Fault\n"); @@ -1774,6 +1826,7 @@ template class ArmFaultVals; template class ArmFaultVals; template class ArmFaultVals; template class ArmFaultVals; +template class ArmFaultVals; template class ArmFaultVals; template class AbortFault; template class AbortFault; diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh index 2e1f3387b..8a127ffdb 100644 --- a/src/arch/arm/faults.hh +++ b/src/arch/arm/faults.hh @@ -64,6 +64,7 @@ class ArmFault : public FaultBase uint32_t issRaw; // Helper variables for ARMv8 exception handling + bool bStep; // True if the Arm Faul exception is a software Step exception bool from64; // True if the exception is generated from the AArch64 state bool to64; // True if the exception is taken in AArch64 state ExceptionLevel fromEL; // Source exception level @@ -207,8 +208,8 @@ class ArmFault : public FaultBase }; ArmFault(ExtMachInst _machInst = 0, uint32_t _iss = 0) : - machInst(_machInst), issRaw(_iss), from64(false), to64(false), - fromEL(EL0), toEL(EL0), fromMode(MODE_UNDEFINED), + machInst(_machInst), issRaw(_iss), bStep(false), from64(false), + to64(false), fromEL(EL0), toEL(EL0), fromMode(MODE_UNDEFINED), faultUpdated(false), hypRouted(false), span(false) {} // Returns the actual syndrome register to use based on the target @@ -223,6 +224,7 @@ class ArmFault : public FaultBase void invoke64(ThreadContext *tc, const StaticInstPtr &inst = StaticInst::nullStaticInstPtr); void update(ThreadContext *tc); + bool isResetSPSR(){ return bStep; } ArmStaticInst *instrAnnotate(const StaticInstPtr &inst); virtual void annotate(AnnotationIDs id, uint64_t val) {} @@ -332,7 +334,9 @@ class SupervisorCall : public ArmFaultVals ExceptionClass _overrideEc = EC_INVALID) : ArmFaultVals(_machInst, _iss), overrideEc(_overrideEc) - {} + { + bStep = true; + } void invoke(ThreadContext *tc, const StaticInstPtr &inst = StaticInst::nullStaticInstPtr) override; @@ -346,7 +350,9 @@ class SecureMonitorCall : public ArmFaultVals public: SecureMonitorCall(ExtMachInst _machInst) : ArmFaultVals(_machInst) - {} + { + bStep = true; + } void invoke(ThreadContext *tc, const StaticInstPtr &inst = StaticInst::nullStaticInstPtr) override; @@ -632,6 +638,19 @@ class Watchpoint : public ArmFaultVals void annotate(AnnotationIDs id, uint64_t val); }; +class SoftwareStepFault : public ArmFaultVals +{ + private: + bool isldx; + bool stepped; + + public: + SoftwareStepFault(ExtMachInst _mach_inst, bool is_ldx, bool stepped); + bool routeToHyp(ThreadContext *tc) const override; + uint32_t iss() const override; + ExceptionClass ec(ThreadContext *tc) const override; +}; + // A fault that flushes the pipe, excluding the faulting instructions class ArmSev : public ArmFaultVals { @@ -674,6 +693,7 @@ template<> ArmFault::FaultVals ArmFaultVals::vals; template<> ArmFault::FaultVals ArmFaultVals::vals; template<> ArmFault::FaultVals ArmFaultVals::vals; template<> ArmFault::FaultVals ArmFaultVals::vals; +template<> ArmFault::FaultVals ArmFaultVals::vals; template<> ArmFault::FaultVals ArmFaultVals::vals; /** diff --git a/src/arch/arm/insts/pseudo.cc b/src/arch/arm/insts/pseudo.cc index 5c2702b5b..3fe2dfa11 100644 --- a/src/arch/arm/insts/pseudo.cc +++ b/src/arch/arm/insts/pseudo.cc @@ -190,3 +190,20 @@ IllegalExecInst::execute(ExecContext *xc, Trace::InstRecord *traceData) const { return std::make_shared(); } + +DebugStep::DebugStep(ExtMachInst _machInst) + : ArmStaticInst("DebugStep", _machInst, No_OpClass) +{ } + +Fault +DebugStep::execute(ExecContext *xc, Trace::InstRecord *traceData) const +{ + PCState pc_state(xc->pcState()); + pc_state.debugStep(false); + xc->pcState(pc_state); + auto *isa = static_cast(xc->tcBase()->getIsaPtr()); + bool ldx = isa->getSelfDebug()->getSstep()->getLdx(); + return std::make_shared(machInst, ldx, + pc_state.stepped()); + +} diff --git a/src/arch/arm/insts/pseudo.hh b/src/arch/arm/insts/pseudo.hh index 76dca20b0..7b385f109 100644 --- a/src/arch/arm/insts/pseudo.hh +++ b/src/arch/arm/insts/pseudo.hh @@ -131,4 +131,12 @@ class IllegalExecInst : public ArmStaticInst Fault execute(ExecContext *xc, Trace::InstRecord *traceData) const; }; +class DebugStep : public ArmStaticInst +{ + public: + DebugStep(ExtMachInst _machInst); + + Fault execute(ExecContext *xc, Trace::InstRecord *traceData) const; +}; + #endif diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index f23cc7978..f18898790 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -43,6 +43,8 @@ #include "arch/arm/faults.hh" #include "arch/arm/isa.hh" +#include "arch/arm/self_debug.hh" +#include "arch/arm/utility.hh" #include "base/condcodes.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" @@ -1106,10 +1108,7 @@ CPSR ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const { CPSR new_cpsr = 0; - - // gem5 doesn't implement single-stepping, so force the SS bit to - // 0. - new_cpsr.ss = 0; + ExceptionLevel dest; if (illegalExceptionReturn(tc, cpsr, spsr)) { // If the SPSR specifies an illegal exception return, @@ -1123,6 +1122,7 @@ ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const new_cpsr.el = cpsr.el; new_cpsr.sp = cpsr.sp; } + dest = currEL(tc); } else { new_cpsr.il = spsr.il; if (spsr.width && unknownMode32((OperatingMode)(uint8_t)spsr.mode)) { @@ -1133,6 +1133,7 @@ ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const new_cpsr.el = spsr.el; new_cpsr.sp = spsr.sp; } + dest = (ExceptionLevel)(uint8_t) spsr.el; } new_cpsr.nz = spsr.nz; @@ -1154,6 +1155,10 @@ ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const new_cpsr.daif = spsr.daif; } + auto *isa = static_cast(tc->getIsaPtr()); + SoftwareStep * ss = (isa->getSelfDebug())->getSstep(); + new_cpsr.ss = ss->debugExceptionReturnSS(tc, spsr, dest, new_cpsr.width); + return new_cpsr; } diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index 07713be8a..82d936924 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -836,6 +836,7 @@ ISA::setMiscReg(int misc_reg, RegVal val) pc.nextThumb(cpsr.t); pc.nextJazelle(cpsr.j); pc.illegalExec(cpsr.il == 1); + selfDebug->setDebugMask(cpsr.d == 1); tc->getDecoderPtr()->setSveLen((getCurSveVecLenInBits() >> 7) - 1); diff --git a/src/arch/arm/isa/bitfields.isa b/src/arch/arm/isa/bitfields.isa index 903bb6787..e1fc8bfed 100644 --- a/src/arch/arm/isa/bitfields.isa +++ b/src/arch/arm/isa/bitfields.isa @@ -46,6 +46,7 @@ // Opcode fields def bitfield DECODERFAULT decoderFault; def bitfield ILLEGALEXEC illegalExecution; +def bitfield DEBUGSTEP debugStep; def bitfield ENCODING encoding; def bitfield OPCODE opcode; diff --git a/src/arch/arm/isa/decoder/decoder.isa b/src/arch/arm/isa/decoder/decoder.isa index 184150579..2a979ea17 100644 --- a/src/arch/arm/isa/decoder/decoder.isa +++ b/src/arch/arm/isa/decoder/decoder.isa @@ -38,17 +38,19 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -decode ILLEGALEXEC default IllegalExec::illegalExec() { - 0: decode DECODERFAULT default DecoderFault::decoderFault() { - 0: decode THUMB default Unknown::unknown() { - 0: decode AARCH64 { - 0: - ##include "arm.isa" +decode DEBUGSTEP default DebugStep::debugStep() { + 0: decode ILLEGALEXEC default IllegalExec::illegalExec() { + 0: decode DECODERFAULT default DecoderFault::decoderFault() { + 0: decode THUMB default Unknown::unknown() { + 0: decode AARCH64 { + 0: + ##include "arm.isa" + 1: + ##include "aarch64.isa" + } 1: - ##include "aarch64.isa" + ##include "thumb.isa" } - 1: - ##include "thumb.isa" } } } diff --git a/src/arch/arm/isa/formats/pseudo.isa b/src/arch/arm/isa/formats/pseudo.isa index a1ee8ecbd..d827aa400 100644 --- a/src/arch/arm/isa/formats/pseudo.isa +++ b/src/arch/arm/isa/formats/pseudo.isa @@ -59,6 +59,15 @@ def format IllegalExec() {{ decode_block = 'return new IllegalExecInst(machInst);\n' }}; +//////////////////////////////////////////////////////////////////// +// +// Debug Step handling +// + +def format DebugStep() {{ + decode_block = 'return new DebugStep(machInst);\n' +}}; + //////////////////////////////////////////////////////////////////// // // Unknown instruction handling diff --git a/src/arch/arm/isa/insts/ldr.isa b/src/arch/arm/isa/insts/ldr.isa index d828fcff0..37abb6456 100644 --- a/src/arch/arm/isa/insts/ldr.isa +++ b/src/arch/arm/isa/insts/ldr.isa @@ -209,6 +209,13 @@ let {{ accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" accCode = accCode % buildMemSuffix(self.sign, self.size) + if self.flavor in ('exclusive', 'acex'): + accCode += ''' + auto *isa = static_cast(xc->tcBase()->getIsaPtr()); + SelfDebug * sd = isa->getSelfDebug(); + sd->getSstep()->setLdx(); + ''' + self.codeBlobs["memacc_code"] = accCode # Push it out to the output files @@ -284,6 +291,12 @@ let {{ FpDest_uw = (uint32_t)swappedMem; FpDest2_uw = (uint32_t)(swappedMem >> 32); ''' + if self.flavor in ('exclusive', 'acex'): + accCode += ''' + auto *isa = static_cast(xc->tcBase()->getIsaPtr()); + SelfDebug * sd = isa->getSelfDebug(); + sd->getSstep()->setLdx(); + ''' self.codeBlobs["memacc_code"] = accCode diff --git a/src/arch/arm/isa/insts/ldr64.isa b/src/arch/arm/isa/insts/ldr64.isa index fc4f34f0c..a2c1bae86 100644 --- a/src/arch/arm/isa/insts/ldr64.isa +++ b/src/arch/arm/isa/insts/ldr64.isa @@ -236,7 +236,12 @@ let {{ accCode = "WDest = cSwap(Mem%s, isBigEndian64(xc->tcBase()));" accCode = accCode % buildMemSuffix(self.sign, self.size) - + if self.flavor in ('exclusive', 'acex'): + accCode += ''' + auto *isa = static_cast(xc->tcBase()->getIsaPtr()); + SelfDebug * sd = isa->getSelfDebug(); + sd->getSstep()->setLdx(); + ''' self.codeBlobs["memacc_code"] = accCode if accEpilogCode: self.codeBlobs["memacc_epilog_code"] = accEpilogCode @@ -332,6 +337,12 @@ let {{ XDest2 = cSwap(Mem_tud[1], isBigEndian64(xc->tcBase())); ''' + if self.flavor in ('exp', 'acexp'): + accCode += ''' + auto *isa = static_cast(xc->tcBase()->getIsaPtr()); + SelfDebug * sd = isa->getSelfDebug(); + sd->getSstep()->setLdx(); + ''' self.codeBlobs["memacc_code"] = accCode if accEpilogCode: self.codeBlobs["memacc_epilog_code"] = accEpilogCode diff --git a/src/arch/arm/self_debug.cc b/src/arch/arm/self_debug.cc index 85c6656bb..f0f420db5 100644 --- a/src/arch/arm/self_debug.cc +++ b/src/arch/arm/self_debug.cc @@ -547,3 +547,74 @@ WatchPoint::compareAddress(ThreadContext *tc, Addr in_addr, uint8_t bas, } } +bool +SoftwareStep::debugExceptionReturnSS(ThreadContext *tc, CPSR spsr, + ExceptionLevel dest, bool aarch32) +{ + bool SS_bit = false; + bool enabled_src = false; + if (bSS) { + enabled_src = conf->isDebugEnabled(tc); + + bool enabled_dst = false; + bool secure = isSecureBelowEL3(tc) || dest == EL3; + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + if (cpsr.width) { + enabled_dst = conf->isDebugEnabledForEL32(tc, dest, secure, + spsr.d == 1); + } else { + enabled_dst = conf->isDebugEnabledForEL64(tc, dest, secure, + spsr.d == 1); + } + ExceptionLevel ELd = debugTargetFrom(tc, secure); + + if (!ELIs32(tc, ELd) && !enabled_src && enabled_dst) { + SS_bit = spsr.ss; + if (SS_bit == 0x0) { + stateSS = ACTIVE_PENDING_STATE; + } else { + stateSS = ACTIVE_NOT_PENDING_STATE; + } + } + } + return SS_bit; +} + +bool +SoftwareStep::advanceSS(ThreadContext * tc) +{ + + PCState pc = tc->pcState(); + bool res = false; + switch (stateSS){ + case INACTIVE_STATE: + pc.debugStep(false); + break; + + case ACTIVE_NOT_PENDING_STATE: + pc.debugStep(false); + if (cpsrD == 1 || !bSS) { + stateSS = INACTIVE_STATE; + } else { + pc.stepped(true); + stateSS = ACTIVE_PENDING_STATE; + tc->pcState(pc); + } + break; + + case ACTIVE_PENDING_STATE: + if (!cpsrD && bSS) { + pc.debugStep(true); + res = true; + tc->pcState(pc); + } + stateSS = INACTIVE_STATE; + clearLdx(); + break; + + default: + break; + } + return res; +} + diff --git a/src/arch/arm/self_debug.hh b/src/arch/arm/self_debug.hh index c8ae711c1..48d784cd5 100644 --- a/src/arch/arm/self_debug.hh +++ b/src/arch/arm/self_debug.hh @@ -48,11 +48,9 @@ class ThreadContext; - namespace ArmISA { - class SelfDebug; class BrkPoint @@ -201,12 +199,70 @@ class WatchPoint bool atomic, unsigned size); }; +class SoftwareStep +{ + + private: + static const uint8_t INACTIVE_STATE = 0; + static const uint8_t ACTIVE_PENDING_STATE = 1; + static const uint8_t ACTIVE_NOT_PENDING_STATE = 2; + + + bool bSS; + int stateSS; + SelfDebug * conf; + bool steppedLdx; + bool prevSteppedLdx; + bool cpsrD; + + bool ctrStepped; + bool ctrActivate; + + + public: + SoftwareStep(SelfDebug* s): bSS(false), stateSS(INACTIVE_STATE), + conf(s), steppedLdx(false) { } + + ~SoftwareStep() { } + + bool debugExceptionReturnSS(ThreadContext *tc, CPSR spsr, + ExceptionLevel dest, bool aarch32); + bool advanceSS(ThreadContext * tc); + + inline void setCPSRD(bool val) + { + cpsrD = val; + } + + inline void setEnableSS(bool val) + { + bSS = val; + } + + void setLdx() + { + prevSteppedLdx = steppedLdx; + steppedLdx = true; + } + + void clearLdx() + { + prevSteppedLdx = steppedLdx; + steppedLdx = false; + } + + bool getLdx() + { + return prevSteppedLdx; + } +}; class SelfDebug { private: std::vector arBrkPoints; std::vector arWatchPoints; + SoftwareStep * softStep; bool initialized; bool enableTdeTge; // MDCR_EL2.TDE || HCR_EL2.TGE @@ -224,9 +280,14 @@ class SelfDebug public: SelfDebug(): initialized(false), enableTdeTge(false), enableFlag(false), bSDD(false), bKDE(false), oslk(false) - {} + { + softStep = new SoftwareStep(this); + } - ~SelfDebug(){} + ~SelfDebug() + { + delete softStep; + } Fault testBreakPoints(ThreadContext *tc, Addr vaddr); Fault testWatchPoints(ThreadContext *tc, Addr vaddr, bool write, @@ -294,6 +355,7 @@ class SelfDebug { enableFlag = bits(val, 15); bKDE = bits(val, 13); + softStep->setEnableSS((bool)bits(val, 0)); } inline void setMDBGen(RegVal val) @@ -321,6 +383,10 @@ class SelfDebug arWatchPoints[index].updateControl(val); } + inline void setDebugMask(bool mask) + { + softStep->setCPSRD(mask); + } inline bool isAArch32() { return aarch32; @@ -339,6 +405,11 @@ class SelfDebug aarch32 = ELIs32(tc, fromEL); return; } + SoftwareStep * getSstep() + { + return softStep; + } + bool targetAArch32(ThreadContext * tc) { @@ -358,7 +429,7 @@ class SelfDebug const AA64MMFR1 mm_fr1 = tc->readMiscReg(MISCREG_ID_AA64MMFR1_EL1); const uint8_t nCtxtAwareBp = dfr.ctx_cmps; const bool VMIDBits = mm_fr1.vmidbits; - for (int i=0; i<=dfr.brps; i++){ + for (int i=0; i<=dfr.brps; i++) { const bool isctxaw = i>=(dfr.brps-nCtxtAwareBp); BrkPoint bkp = BrkPoint((MiscRegIndex)(MISCREG_DBGBCR0_EL1+i), @@ -372,7 +443,7 @@ class SelfDebug arBrkPoints.push_back(bkp); } - for (int i=0; i<=dfr.wrps; i++){ + for (int i=0; i<=dfr.wrps; i++) { WatchPoint wtp = WatchPoint((MiscRegIndex)(MISCREG_DBGWCR0+i), (MiscRegIndex)(MISCREG_DBGWVR0+i), this, (bool)mm_fr2.varange, aarch32); diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index fc7a7545b..1a26ab5a1 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -1197,11 +1197,13 @@ TLB::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode, auto *isa = static_cast(tc->getIsaPtr()); SelfDebug * sd = isa->getSelfDebug(); if (mode == Execute) { - fault = sd->testBreakPoints(tc, req->getVaddr()); + const bool d_step = sd->getSstep()->advanceSS(tc); + if (!d_step) { + fault = sd->testBreakPoints(tc, req->getVaddr()); + } } else if (!req->isCacheMaintenance() || - (req->isCacheInvalidate() && !req->isCacheClean())) - { + (req->isCacheInvalidate() && !req->isCacheClean())) { bool md = mode == Write ? true: false; fault = sd->testWatchPoints(tc, req->getVaddr(), md, req->isAtomic(), @@ -1291,7 +1293,9 @@ TLB::translateComplete(const RequestPtr &req, ThreadContext *tc, // stage 2 translation we prevent marking the translation as delayed twice, // one when the translation starts and again when the stage 1 translation // completes. - if (translation && (callFromS2 || !stage2Req || req->hasPaddr() || fault != NoFault)) { + + if (translation && (callFromS2 || !stage2Req || req->hasPaddr() || + fault != NoFault)) { if (!delay) translation->finish(fault, req, tc, mode); else diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index 3a5e74151..0119e4e66 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -69,6 +69,7 @@ namespace ArmISA // Decoder state Bitfield<63, 62> decoderFault; // See DecoderFault Bitfield<61> illegalExecution; + Bitfield<60> debugStep; // SVE vector length, encoded in the same format as the ZCR_EL.LEN // bitfields @@ -228,9 +229,15 @@ namespace ArmISA uint8_t _nextItstate; uint8_t _size; bool _illegalExec; + + // Software Step flags + bool _debugStep; + bool _stepped; + public: PCState() : flags(0), nextFlags(0), _itstate(0), _nextItstate(0), - _size(0), _illegalExec(false) + _size(0), _illegalExec(false), _debugStep(false), + _stepped(false) {} void @@ -241,7 +248,8 @@ namespace ArmISA } PCState(Addr val) : flags(0), nextFlags(0), _itstate(0), - _nextItstate(0), _size(0), _illegalExec(false) + _nextItstate(0), _size(0), _illegalExec(false), + _debugStep(false), _stepped(false) { set(val); } bool @@ -256,6 +264,30 @@ namespace ArmISA _illegalExec = val; } + bool + debugStep() const + { + return _debugStep; + } + + void + debugStep(bool val) + { + _debugStep = val; + } + + bool + stepped() const + { + return _stepped; + } + + void + stepped(bool val) + { + _stepped = val; + } + bool thumb() const { @@ -491,7 +523,9 @@ namespace ArmISA flags == opc.flags && nextFlags == opc.nextFlags && _itstate == opc._itstate && _nextItstate == opc._nextItstate && - _illegalExec == opc._illegalExec; + _illegalExec == opc._illegalExec && + _debugStep == opc._debugStep && + _stepped == opc._stepped; } bool @@ -510,6 +544,8 @@ namespace ArmISA SERIALIZE_SCALAR(_itstate); SERIALIZE_SCALAR(_nextItstate); SERIALIZE_SCALAR(_illegalExec); + SERIALIZE_SCALAR(_debugStep); + SERIALIZE_SCALAR(_stepped); } void @@ -522,6 +558,8 @@ namespace ArmISA UNSERIALIZE_SCALAR(_itstate); UNSERIALIZE_SCALAR(_nextItstate); UNSERIALIZE_SCALAR(_illegalExec); + UNSERIALIZE_SCALAR(_debugStep); + UNSERIALIZE_SCALAR(_stepped); } }; @@ -648,6 +686,9 @@ namespace ArmISA EC_HW_BREAKPOINT = 0x30, EC_HW_BREAKPOINT_LOWER_EL = 0x30, EC_HW_BREAKPOINT_CURR_EL = 0x31, + EC_SOFTWARE_STEP = 0x32, + EC_SOFTWARE_STEP_LOWER_EL = 0x32, + EC_SOFTWARE_STEP_CURR_EL = 0x33, EC_WATCHPOINT = 0x34, EC_WATCHPOINT_LOWER_EL = 0x34, EC_WATCHPOINT_CURR_EL = 0x35, -- 2.30.2