diff options
author | Giacomo Travaglini <giacomo.travaglini@arm.com> | 2017-12-14 17:38:38 +0000 |
---|---|---|
committer | Giacomo Travaglini <giacomo.travaglini@arm.com> | 2018-02-07 15:13:49 +0000 |
commit | 633fdd5841d8e7798e1b1158261612a6ad84c812 (patch) | |
tree | a572e3d8be8e82d2be24e3d1d6da54818e3e4f41 /src/arch/arm/insts/static_inst.cc | |
parent | 78024e6b026fecc780e503aa246beeb10dcc26d9 (diff) | |
download | gem5-633fdd5841d8e7798e1b1158261612a6ad84c812.tar.xz |
arch-arm: Fix AArch32 SETEND Instruction
This patch fixes AArch32 SETEND instruction, which was previously
executed unconditionally without checking (H)SCTLR.SED field. This bit
enables/disables the trapping of the instruction.
Change-Id: Ib3d2194c8d16c34ec2a9ab3e8090081900c1e42e
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/7981
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Diffstat (limited to 'src/arch/arm/insts/static_inst.cc')
-rw-r--r-- | src/arch/arm/insts/static_inst.cc | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index 61f31e5db..f7a9745ad 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -859,6 +859,77 @@ ArmStaticInst::trapWFx(ThreadContext *tc, return fault; } +Fault +ArmStaticInst::checkSETENDEnabled(ThreadContext *tc, CPSR cpsr) const +{ + bool setend_disabled(false); + ExceptionLevel pstateEL = (ExceptionLevel)(uint8_t)(cpsr.el); + + if (pstateEL == EL2) { + setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(MISCREG_HSCTLR)).sed; + } else { + // Please note: in the armarm pseudocode there is a distinction + // whether EL1 is aarch32 or aarch64: + // if ELUsingAArch32(EL1) then SCTLR.SED else SCTLR[].SED; + // Considering that SETEND is aarch32 only, ELUsingAArch32(EL1) + // will always be true (hence using SCTLR.SED) except for + // instruction executed at EL0, and with an AArch64 EL1. + // In this case SCTLR_EL1 will be used. In gem5 the register is + // mapped to SCTLR_ns. We can safely use SCTLR and choose the + // appropriate bank version. + + // Get the index of the banked version of SCTLR: + // SCTLR_s or SCTLR_ns. + auto banked_sctlr = flattenMiscRegNsBanked( + MISCREG_SCTLR, tc, !inSecureState(tc)); + + // SCTLR.SED bit is enabling/disabling the ue of SETEND instruction. + setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(banked_sctlr)).sed; + } + + return setend_disabled ? undefinedFault32(tc, pstateEL) : + NoFault; +} + +Fault +ArmStaticInst::undefinedFault32(ThreadContext *tc, + ExceptionLevel pstateEL) const +{ + // Even if we are running in aarch32, the fault might be dealt with in + // aarch64 ISA. + if (generalExceptionsToAArch64(tc, pstateEL)) { + return undefinedFault64(tc, pstateEL); + } else { + // Please note: according to the ARM ARM pseudocode we should handle + // the case when EL2 is aarch64 and HCR.TGE is 1 as well. + // However this case is already handled by the routeToHyp method in + // ArmFault class. + return std::make_shared<UndefinedInstruction>( + machInst, 0, + EC_UNKNOWN, mnemonic); + } +} + +Fault +ArmStaticInst::undefinedFault64(ThreadContext *tc, + ExceptionLevel pstateEL) const +{ + switch (pstateEL) { + case EL0: + case EL1: + return std::make_shared<SupervisorTrap>(machInst, 0, EC_UNKNOWN); + case EL2: + return std::make_shared<HypervisorTrap>(machInst, 0, EC_UNKNOWN); + case EL3: + return std::make_shared<SecureMonitorTrap>(machInst, 0, EC_UNKNOWN); + default: + panic("Unrecognized Exception Level: %d\n", pstateEL); + break; + } + + return NoFault; +} + static uint8_t getRestoredITBits(ThreadContext *tc, CPSR spsr) { @@ -981,6 +1052,18 @@ ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const return new_cpsr; } +bool +ArmStaticInst::generalExceptionsToAArch64(ThreadContext *tc, + ExceptionLevel pstateEL) const +{ + // Returns TRUE if exceptions normally routed to EL1 are being handled + // at an Exception level using AArch64, because either EL1 is using + // AArch64 or TGE is in force and EL2 is using AArch64. + HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2)); + return (pstateEL == EL0 && !ELIs32(tc, EL1)) || + (ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) && + !ELIs32(tc, EL2) && hcr.tge); +} } |