From 73b1160bd808cc523f49db37df597e4b2f3b9877 Mon Sep 17 00:00:00 2001 From: Chuan Zhu Date: Fri, 5 Jan 2018 10:26:37 +0000 Subject: arch-arm: Fixed error in choosing vector offset The old code chose vector offset associated with exceptions taken to EL3 by incorrectly using "from64", which is associated with the exception level where the exception was taken from. However, the offset should depends on the ISA of the lower EL and not of the starting EL itself, as specified in ARM ARM. This patch corrects this by implementing the method in AArch64.TakeException in ARM ARM. Change-Id: I8f7c9aa777c5f2eef9e2d89c36e9daee23f3a822 Reviewed-by: Jack Travaglini Reviewed-on: https://gem5-review.googlesource.com/8001 Reviewed-by: Andreas Sandberg Maintainer: Andreas Sandberg --- src/arch/arm/faults.cc | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'src/arch/arm/faults.cc') diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 27894e0c1..e3488f428 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -350,7 +350,7 @@ ArmFault::getVector64(ThreadContext *tc) panic("Invalid target exception level"); break; } - return vbar + offset64(); + return vbar + offset64(tc); } MiscRegIndex @@ -654,6 +654,8 @@ ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst) ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset(); tc->setMiscReg(elr_idx, ret_addr); + Addr vec_address = getVector64(tc); + // Update process state OperatingMode64 mode = 0; mode.spX = 1; @@ -666,7 +668,7 @@ ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst) tc->setMiscReg(MISCREG_CPSR, cpsr); // Set PC to start of exception handler - Addr new_pc = purifyTaggedAddr(getVector64(tc), tc, toEL); + Addr new_pc = purifyTaggedAddr(vec_address, tc, toEL); DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x " "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc); PCState pc(new_pc); @@ -893,6 +895,31 @@ ArmFaultVals::offset(ThreadContext *tc) return isHypTrap ? 0x14 : vals.offset; } +template +FaultOffset +ArmFaultVals::offset64(ThreadContext *tc) +{ + if (toEL == fromEL) { + if (opModeIsT(fromMode)) + return vals.currELTOffset; + return vals.currELHOffset; + } else { + bool lower_32 = false; + if (toEL == EL3) { + if (!inSecureState(tc) && ArmSystem::haveEL(tc, EL2)) + lower_32 = ELIs32(tc, EL2); + else + lower_32 = ELIs32(tc, EL1); + } else { + lower_32 = ELIs32(tc, static_cast(toEL - 1)); + } + + if (lower_32) + return vals.lowerEL32Offset; + return vals.lowerEL64Offset; + } +} + // void // SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx) // { -- cgit v1.2.3