diff options
author | Giacomo Travaglini <giacomo.travaglini@arm.com> | 2018-02-09 10:01:39 +0000 |
---|---|---|
committer | Giacomo Travaglini <giacomo.travaglini@arm.com> | 2018-03-08 10:11:36 +0000 |
commit | 72ecef7a759f10b4816ecf13a1289fc6d9443c92 (patch) | |
tree | 998f6efce665e127846b89d5d55aa41a9ee0c489 /src/arch/arm/faults.cc | |
parent | dbf7b0adc53b2ab78ae327653870fdcf8b63b572 (diff) | |
download | gem5-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>
Diffstat (limited to 'src/arch/arm/faults.cc')
-rw-r--r-- | src/arch/arm/faults.cc | 65 |
1 files changed, 48 insertions, 17 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; } |