From 0ca254aa8381ba2fae61a4a056301e35da9ffab3 Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Thu, 28 Feb 2019 17:07:16 +0800 Subject: invisispec-1.0 source --- src/cpu/base_dyn_inst.hh | 188 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 187 insertions(+), 1 deletion(-) (limited to 'src/cpu/base_dyn_inst.hh') diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 93cafd694..0e81073cc 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -120,6 +120,28 @@ class BaseDynInst : public ExecContext, public RefCounted /// instructions ahead of it SerializeAfter, /// Needs to serialize instructions behind it SerializeHandled, /// Serialization has been handled + + SpecCompleted, + // [mengjia] indicates whether received specReadResp + ValidationCompleted, + // indicates whether validation finishes + ExposeCompleted, + ExposeSent, + // indicates whether expose finishes + // (should set when expose is sent out) + PrevInstsCompleted, + // indicate whether previous instructions completed + PrevBrsResolved, + // [mengjia] indicate whether previous branches are resolved + PrevInstsCommitted, + // indicate whether previous instructions committed + PrevBrsCommitted, + // [mengjia] indicate whether previous branches are committed + L1HitHigh, + L1HitLow, + SpecBuffObsoleteHigh, + SpecBuffObsoleteLow, + // [InvisiSpec] it hits in L1 and is open to invalidations NumStatus }; @@ -136,6 +158,22 @@ class BaseDynInst : public ExecContext, public RefCounted IsStrictlyOrdered, ReqMade, MemOpDone, + // [mengjia] indicates need validation or expose + NeedPostFetch, + NeedDeletePostReq, + // [mengjia] indicates only need to expose, do not need to validate + NeedExposeOnly, + // [InvisiSpec] indicate the instruction needs to be delayed + // due to virtual fences before to defend against speculative attacks + FenceDelay, + // [InvisiSpec] indicate the load is legal to be visible + ReadyToExpose, + HitInvalidation, + HitExternalEviction, + ValidationFail, + OnlyWaitForFence, + OnlyWaitForExpose, + SpecTLBMiss, MaxFlags }; @@ -222,6 +260,9 @@ class BaseDynInst : public ExecContext, public RefCounted /** Pointer to the data for the memory access. */ uint8_t *memData; + /** Pointer to the data for the validation result. */ + uint8_t *vldData; + /** Load queue index. */ int16_t lqIdx; @@ -238,6 +279,12 @@ class BaseDynInst : public ExecContext, public RefCounted RequestPtr savedSreqLow; RequestPtr savedSreqHigh; + /** [InvisiSpec] + * Saved memory requests (needed for post-fetch validation/expose). + */ + RequestPtr postReq; + RequestPtr postSreqLow; + RequestPtr postSreqHigh; /////////////////////// Checker ////////////////////// // Need a copy of main request pointer to verify on writes. RequestPtr reqToVerify; @@ -275,6 +322,43 @@ class BaseDynInst : public ExecContext, public RefCounted bool memOpDone() const { return instFlags[MemOpDone]; } void memOpDone(bool f) { instFlags[MemOpDone] = f; } + /** [mengjia] Whether or not need pseudo-validation. + * whether speculative laod finishes, + * whether validation completes or not (success) */ + bool needExposeOnly() const { return instFlags[NeedExposeOnly]; } + void needExposeOnly(bool f) { instFlags[NeedExposeOnly] = f; } + + bool needPostFetch() const { return instFlags[NeedPostFetch]; } + void needPostFetch(bool f) { instFlags[NeedPostFetch] = f; } + + bool needDeletePostReq() const { return instFlags[NeedDeletePostReq]; } + void needDeletePostReq(bool f) { instFlags[NeedDeletePostReq] = f; } + + bool fenceDelay() const { return instFlags[ReadyToExpose]; } + void fenceDelay(bool f) { instFlags[ReadyToExpose] = f; } + + bool readyToExpose() const { return instFlags[FenceDelay]; } + void readyToExpose(bool f) { instFlags[FenceDelay] = f; } + + bool hitInvalidation() const { return instFlags[HitInvalidation]; } + void hitInvalidation(bool f) { instFlags[HitInvalidation] = f; } + + bool hitExternalEviction() const { return instFlags[HitExternalEviction]; } + void hitExternalEviction(bool f) { instFlags[HitExternalEviction] = f; } + + bool validationFail() const { return instFlags[ValidationFail]; } + void validationFail(bool f) { instFlags[ValidationFail] = f; } + + bool onlyWaitForFence() const { return instFlags[OnlyWaitForFence]; } + void onlyWaitForFence(bool f) { instFlags[OnlyWaitForFence] = f; } + + bool onlyWaitForExpose() const { return instFlags[OnlyWaitForExpose]; } + void onlyWaitForExpose(bool f) { instFlags[OnlyWaitForExpose] = f; } + + bool specTLBMiss() const { return instFlags[SpecTLBMiss]; } + void specTLBMiss(bool f) { instFlags[SpecTLBMiss] = f; } + /*[mengjia] added 2 new flags and corresponding functions*/ + bool notAnInst() const { return instFlags[NotAnInst]; } void setNotAnInst() { instFlags[NotAnInst] = true; } @@ -704,6 +788,49 @@ class BaseDynInst : public ExecContext, public RefCounted /** Returns whether or not this instruction is completed. */ bool isCompleted() const { return status[Completed]; } + /* [mengjia] new status for load operations */ + //void setSpecSent() { status.set(SpecSent); } + //bool isSpecSent() const { return status[SpecSent]; } + + void setSpecCompleted() { status.set(SpecCompleted); } + bool isSpecCompleted() const { return status[SpecCompleted]; } + + void setValidationCompleted() { status.set(ValidationCompleted); } + bool isValidationCompleted() const { return status[ValidationCompleted]; } + + void setExposeCompleted() { status.set(ExposeCompleted); } + bool isExposeCompleted() const { return status[ExposeCompleted]; } + + void setExposeSent() { status.set(ExposeSent); } + bool isExposeSent() const { return status[ExposeSent]; } + + void setL1HitHigh() { status.set(L1HitHigh); } + void clearL1HitHigh() { status.reset(L1HitHigh); } + bool isL1HitHigh() const { return status[L1HitHigh]; } + + void setL1HitLow() { status.set(L1HitLow); } + void clearL1HitLow() { status.reset(L1HitLow); } + bool isL1HitLow() const { return status[L1HitLow]; } + + void setPrevInstsCompleted() { status.set(PrevInstsCompleted); } + bool isPrevInstsCompleted() const { return status[PrevInstsCompleted]; } + + void setSpecBuffObsoleteHigh() { status.set(SpecBuffObsoleteHigh); } + bool isSpecBuffObsoleteHigh() const { return status[SpecBuffObsoleteHigh]; } + + void setSpecBuffObsoleteLow() { status.set(SpecBuffObsoleteLow); } + bool isSpecBuffObsoleteLow() const { return status[SpecBuffObsoleteLow]; } + + void setPrevBrsResolved() { status.set(PrevBrsResolved); } + bool isPrevBrsResolved() const { return status[PrevBrsResolved]; } + + void setPrevInstsCommitted() { status.set(PrevInstsCommitted); } + bool isPrevInstsCommitted() const { return status[PrevInstsCommitted]; } + + void setPrevBrsCommitted() { status.set(PrevBrsCommitted); } + bool isPrevBrsCommitted() const { return status[PrevBrsCommitted]; } + /* Configure load related status */ + /** Marks the result as ready. */ void setResultReady() { status.set(ResultReady); } @@ -893,7 +1020,25 @@ Fault BaseDynInst::initiateMemRead(Addr addr, unsigned size, Request::Flags flags) { + // [InvisiSpec] do not start translation if + // there is a virtual fence ahead + assert(!fenceDelay()); + + if ( (flags.isSet(Request::ATOMIC_RETURN_OP) + || flags.isSet(Request::ATOMIC_NO_RETURN_OP) + || flags.isSet(Request::UNCACHEABLE) + || flags.isSet(Request::LLSC) + || flags.isSet(Request::STRICT_ORDER)) + && !readyToExpose()){ + onlyWaitForExpose(true); + // FIXME: reschedule due to LLSC + // reuse TLBMiss for now + specTLBMiss(true); + return NoFault; + } + instFlags[ReqMade] = true; + instFlags[SpecTLBMiss] = false; RequestPtr req = NULL; RequestPtr sreqLow = NULL; RequestPtr sreqHigh = NULL; @@ -908,16 +1053,36 @@ BaseDynInst::initiateMemRead(Addr addr, unsigned size, this->pc.instAddr(), thread->contextId()); req->taskId(cpu->taskId()); - + if(!readyToExpose()){ + req->setFlags(Request::SPEC); + } // Only split the request if the ISA supports unaligned accesses. if (TheISA::HasUnalignedMemAcc) { splitRequest(req, sreqLow, sreqHigh); } + initiateTranslation(req, sreqLow, sreqHigh, NULL, BaseTLB::Read); + } if (translationCompleted()) { + // [InvisiSpec] to fix the memory leakage problem + // in the case the read is squashed and the request + // is never sent out due to a virtual fence ahead if (fault == NoFault) { + /* + if (fenceDelay()){ + translationStarted(false); + translationCompleted(false); + onlyWaitForFence(true); + delete req; + if (sreqLow){ + delete sreqLow; + delete sreqHigh; + } + return NoFault; + } + */ effAddr = req->getVaddr(); effSize = size; instFlags[EffAddrValid] = true; @@ -925,10 +1090,30 @@ BaseDynInst::initiateMemRead(Addr addr, unsigned size, if (cpu->checker) { reqToVerify = std::make_shared(*req); } + + // issue load request [mengjia] fault = cpu->read(req, sreqLow, sreqHigh, lqIdx); } else { // Commit will have to clean up whatever happened. Set this // instruction as executed. + + // [InvisiSpec] If it is a fault on translating a spec load + // Deffer it and retry when it is ready to expose + if (!readyToExpose()){ + translationStarted(false); + translationCompleted(false); + onlyWaitForExpose(true); + specTLBMiss(true); + //delete req; + //if (sreqLow){ + // delete sreqLow; + // delete sreqHigh; + //} + return NoFault; + } + // set it as executed and fault flag. + // when it enters ROB and try to commit, + // the commit stage will squash this inst [mengjia] this->setExecuted(); } } @@ -939,6 +1124,7 @@ BaseDynInst::initiateMemRead(Addr addr, unsigned size, return fault; } + template Fault BaseDynInst::writeMem(uint8_t *data, unsigned size, Addr addr, -- cgit v1.2.3