arch-arm: Fix FSC generation in AbortFault
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Fri, 9 Feb 2018 10:01:39 +0000 (10:01 +0000)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Thu, 8 Mar 2018 10:11:36 +0000 (10:11 +0000)
The fault status code generated by a Prefetch/Data Fault was containing
a wrong value when the fault was triggered in aarch32 but handled in
aarch64.  This because the encoding differs between the two ISAs and the
encoder was just checking the starting ISA rather than the the ending
one. In this case the getFsr must be called after we know which is the
ending ISA, which happens only after ArmFault::invoke gets called.  The
fsc update hence happens before writing into the Syndrome register.

Change-Id: I725f12b6dcc0178f608233bd3d15e466d1cd1ffc
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/8362
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>

src/arch/arm/faults.cc
src/arch/arm/faults.hh
src/arch/arm/isa.cc

index 310545bc33833e77ee9cc6c43d5030ee7ac751d1..a1952d664c093ae9e372a7e77b1ddb8dd68796ac 100644 (file)
@@ -1032,13 +1032,13 @@ AbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
     }
     // Get effective fault source encoding
     CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
-    FSR  fsr  = getFsr(tc);
 
     // source must be determined BEFORE invoking generic routines which will
     // try to set hsr etc. and are based upon source!
     ArmFaultVals<T>::invoke(tc, inst);
 
     if (!this->to64) {  // AArch32
+        FSR  fsr  = getFsr(tc);
         if (cpsr.mode == MODE_HYP) {
             tc->setMiscReg(T::HFarIndex, faultAddr);
         } else if (stage2) {
@@ -1068,33 +1068,64 @@ AbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
 }
 
 template<class T>
-FSR
-AbortFault<T>::getFsr(ThreadContext *tc)
+void
+AbortFault<T>::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
 {
-    FSR fsr = 0;
+    srcEncoded = getFaultStatusCode(tc);
+    if (srcEncoded == ArmFault::FaultSourceInvalid) {
+        panic("Invalid fault source\n");
+    }
+    ArmFault::setSyndrome(tc, syndrome_reg);
+}
 
-    if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) {
+template<class T>
+uint8_t
+AbortFault<T>::getFaultStatusCode(ThreadContext *tc) const
+{
+
+    panic_if(!this->faultUpdated,
+             "Trying to use un-updated ArmFault internal variables\n");
+
+    uint8_t fsc = 0;
+
+    if (!this->to64) {
         // AArch32
         assert(tranMethod != ArmFault::UnknownTran);
         if (tranMethod == ArmFault::LpaeTran) {
-            srcEncoded = ArmFault::longDescFaultSources[source];
-            fsr.status = srcEncoded;
-            fsr.lpae   = 1;
+            fsc = ArmFault::longDescFaultSources[source];
         } else {
-            srcEncoded = ArmFault::shortDescFaultSources[source];
-            fsr.fsLow  = bits(srcEncoded, 3, 0);
-            fsr.fsHigh = bits(srcEncoded, 4);
-            fsr.domain = static_cast<uint8_t>(domain);
+            fsc = ArmFault::shortDescFaultSources[source];
         }
-        fsr.wnr = (write ? 1 : 0);
-        fsr.ext = 0;
     } else {
         // AArch64
-        srcEncoded = ArmFault::aarch64FaultSources[source];
+        fsc = ArmFault::aarch64FaultSources[source];
     }
-    if (srcEncoded == ArmFault::FaultSourceInvalid) {
-        panic("Invalid fault source\n");
+
+    return fsc;
+}
+
+template<class T>
+FSR
+AbortFault<T>::getFsr(ThreadContext *tc) const
+{
+    FSR fsr = 0;
+
+    auto fsc = getFaultStatusCode(tc);
+
+    // AArch32
+    assert(tranMethod != ArmFault::UnknownTran);
+    if (tranMethod == ArmFault::LpaeTran) {
+        fsr.status = fsc;
+        fsr.lpae   = 1;
+    } else {
+        fsr.fsLow  = bits(fsc, 3, 0);
+        fsr.fsHigh = bits(fsc, 4);
+        fsr.domain = static_cast<uint8_t>(domain);
     }
+
+    fsr.wnr = (write ? 1 : 0);
+    fsr.ext = 0;
+
     return fsr;
 }
 
index f663b5cfc6b49c4c45c62fc299963313c3c79924..132c07cae7754aaa979711ef09d7262b14f9c1f3 100644 (file)
@@ -228,7 +228,7 @@ class ArmFault : public FaultBase
     virtual ExceptionClass ec(ThreadContext *tc) const = 0;
     virtual uint32_t iss() const = 0;
     virtual bool isStage2() const { return false; }
-    virtual FSR getFsr(ThreadContext *tc) { return 0; }
+    virtual FSR getFsr(ThreadContext *tc) const { return 0; }
     virtual void setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg);
 };
 
@@ -431,11 +431,13 @@ class AbortFault : public ArmFaultVals<T>
     void invoke(ThreadContext *tc, const StaticInstPtr &inst =
                 StaticInst::nullStaticInstPtr) override;
 
-    FSR getFsr(ThreadContext *tc) override;
+    FSR getFsr(ThreadContext *tc) const override;
+    uint8_t getFaultStatusCode(ThreadContext *tc) const;
     bool abortDisable(ThreadContext *tc) override;
     uint32_t iss() const override;
     bool isStage2() const override { return stage2; }
     void annotate(ArmFault::AnnotationIDs id, uint64_t val) override;
+    void setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg) override;
     bool isMMUFault() const;
 };
 
index f6677323e057147a7f1291ff2052e90b60081b58..d6992dc44e88e8e3e71ac0fca4a08aade8b63244 100644 (file)
@@ -1477,6 +1477,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
                           val, newVal);
               } else {
                   ArmFault *armFault = static_cast<ArmFault *>(fault.get());
+                  armFault->update(tc);
                   // Set fault bit and FSR
                   FSR fsr = armFault->getFsr(tc);
 
@@ -1726,6 +1727,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
                           val, newVal);
                 } else {
                     ArmFault *armFault = static_cast<ArmFault *>(fault.get());
+                    armFault->update(tc);
                     // Set fault bit and FSR
                     FSR fsr = armFault->getFsr(tc);