summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiacomo Travaglini <giacomo.travaglini@arm.com>2018-02-09 10:01:39 +0000
committerGiacomo Travaglini <giacomo.travaglini@arm.com>2018-03-08 10:11:36 +0000
commit72ecef7a759f10b4816ecf13a1289fc6d9443c92 (patch)
tree998f6efce665e127846b89d5d55aa41a9ee0c489
parentdbf7b0adc53b2ab78ae327653870fdcf8b63b572 (diff)
downloadgem5-72ecef7a759f10b4816ecf13a1289fc6d9443c92.tar.xz
arch-arm: Fix FSC generation in AbortFault
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>
-rw-r--r--src/arch/arm/faults.cc65
-rw-r--r--src/arch/arm/faults.hh6
-rw-r--r--src/arch/arm/isa.cc2
3 files changed, 54 insertions, 19 deletions
diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc
index 310545bc3..a1952d664 100644
--- a/src/arch/arm/faults.cc
+++ b/src/arch/arm/faults.cc
@@ -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;
}
diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh
index f663b5cfc..132c07cae 100644
--- a/src/arch/arm/faults.hh
+++ b/src/arch/arm/faults.hh
@@ -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;
};
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index f6677323e..d6992dc44 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -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);