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>
This commit is contained in:
Giacomo Travaglini
2018-02-09 10:01:39 +00:00
parent dbf7b0adc5
commit 72ecef7a75
3 changed files with 61 additions and 26 deletions

View 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;
if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) {
// AArch32
assert(tranMethod != ArmFault::UnknownTran);
if (tranMethod == ArmFault::LpaeTran) {
srcEncoded = ArmFault::longDescFaultSources[source];
fsr.status = srcEncoded;
fsr.lpae = 1;
} else {
srcEncoded = ArmFault::shortDescFaultSources[source];
fsr.fsLow = bits(srcEncoded, 3, 0);
fsr.fsHigh = bits(srcEncoded, 4);
fsr.domain = static_cast<uint8_t>(domain);
}
fsr.wnr = (write ? 1 : 0);
fsr.ext = 0;
} else {
// AArch64
srcEncoded = ArmFault::aarch64FaultSources[source];
}
srcEncoded = getFaultStatusCode(tc);
if (srcEncoded == ArmFault::FaultSourceInvalid) {
panic("Invalid fault source\n");
}
ArmFault::setSyndrome(tc, syndrome_reg);
}
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) {
fsc = ArmFault::longDescFaultSources[source];
} else {
fsc = ArmFault::shortDescFaultSources[source];
}
} else {
// AArch64
fsc = ArmFault::aarch64FaultSources[source];
}
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;
}

View 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;
};

View 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);