diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/arm/insts/static_inst.cc | 6 | ||||
-rw-r--r-- | src/arch/arm/insts/static_inst.hh | 2 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/mem.isa | 7 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/uncond.isa | 7 | ||||
-rw-r--r-- | src/arch/arm/isa/insts/str.isa | 6 | ||||
-rw-r--r-- | src/arch/arm/types.hh | 5 | ||||
-rw-r--r-- | src/arch/arm/utility.cc | 12 | ||||
-rw-r--r-- | src/arch/arm/utility.hh | 20 |
8 files changed, 56 insertions, 9 deletions
diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index 40a1fe4b3..b7f235e98 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -961,7 +961,7 @@ static bool illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr) { const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode; - if (badMode(mode)) + if (unknownMode(mode)) return true; const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode; @@ -1000,7 +1000,7 @@ illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr) return true; } else { // aarch32 - return badMode32(mode); + return unknownMode32(mode); } return false; @@ -1029,7 +1029,7 @@ ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const } } else { new_cpsr.il = spsr.il; - if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) { + if (spsr.width && unknownMode32((OperatingMode)(uint8_t)spsr.mode)) { new_cpsr.il = 1; } else if (spsr.width) { new_cpsr.mode = spsr.mode; diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh index 69ae58e66..873dfff02 100644 --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@ -230,7 +230,7 @@ class ArmStaticInst : public StaticInst // Now check the new mode is allowed OperatingMode newMode = (OperatingMode) (val & mask(5)); OperatingMode oldMode = (OperatingMode)(uint32_t)cpsr.mode; - if (!badMode(newMode)) { + if (!badMode(tc, newMode)) { bool validModeChange = true; // Check for attempts to enter modes only permitted in // Secure state from Non-secure state. These are Monitor diff --git a/src/arch/arm/isa/formats/mem.isa b/src/arch/arm/isa/formats/mem.isa index 1a30fbb9d..50e3e358f 100644 --- a/src/arch/arm/isa/formats/mem.isa +++ b/src/arch/arm/isa/formats/mem.isa @@ -282,7 +282,12 @@ def format Thumb32SrsRfe() {{ } } else { const uint32_t mode = bits(machInst, 4, 0); - if (badMode32((OperatingMode)mode)) + // We check at decode stage if the mode exists even + // if the checking is re-done by Srs::execute. + // This is done because we will otherwise panic if + // trying to read the banked stack pointer of an + // unrecognized mode. + if (unknownMode32((OperatingMode)mode)) return new Unknown(machInst); if (!add && !wb) { return new %(srs)s(machInst, mode, diff --git a/src/arch/arm/isa/formats/uncond.isa b/src/arch/arm/isa/formats/uncond.isa index c376cd9ce..e0b07ab5a 100644 --- a/src/arch/arm/isa/formats/uncond.isa +++ b/src/arch/arm/isa/formats/uncond.isa @@ -166,7 +166,12 @@ def format ArmUnconditional() {{ const uint32_t val = ((machInst >> 20) & 0x5); if (val == 0x4) { const uint32_t mode = bits(machInst, 4, 0); - if (badMode32((OperatingMode)mode)) + // We check at decode stage if the mode exists even + // if the checking is re-done by Srs::execute. + // This is done because we will otherwise panic if + // trying to read the banked stack pointer of an + // unrecognized mode. + if (unknownMode32((OperatingMode)mode)) return new Unknown(machInst); switch (bits(machInst, 24, 21)) { case 0x2: diff --git a/src/arch/arm/isa/insts/str.isa b/src/arch/arm/isa/insts/str.isa index 1c697d3ff..c165eaf1a 100644 --- a/src/arch/arm/isa/insts/str.isa +++ b/src/arch/arm/isa/insts/str.isa @@ -112,6 +112,12 @@ let {{ if self.add: wbDiff = 8 accCode = ''' + + auto tc = xc->tcBase(); + if (badMode32(tc, static_cast<OperatingMode>(regMode))) { + return undefinedFault32(tc, opModeToEL(currOpMode(tc))); + } + CPSR cpsr = Cpsr; Mem_ud = (uint64_t)cSwap(LR_uw, cpsr.e) | ((uint64_t)cSwap(Spsr_uw, cpsr.e) << 32); diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index 07cdfadc8..9ce02524e 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -710,7 +710,7 @@ namespace ArmISA } static inline bool - badMode(OperatingMode mode) + unknownMode(OperatingMode mode) { switch (mode) { case MODE_EL0T: @@ -735,9 +735,8 @@ namespace ArmISA } } - static inline bool - badMode32(OperatingMode mode) + unknownMode32(OperatingMode mode) { switch (mode) { case MODE_USER: diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 7659e1e79..dec85ef65 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -313,6 +313,18 @@ isBigEndian64(ThreadContext *tc) } } +bool +badMode32(ThreadContext *tc, OperatingMode mode) +{ + return unknownMode32(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode)); +} + +bool +badMode(ThreadContext *tc, OperatingMode mode) +{ + return unknownMode(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode)); +} + Addr purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el, TTBCR tcr) diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index 796ded771..9d0131b49 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -181,6 +181,26 @@ bool ELIs64(ThreadContext *tc, ExceptionLevel el); bool isBigEndian64(ThreadContext *tc); +/** + * badMode is checking if the execution mode provided as an argument is + * valid and implemented for AArch32 + * + * @param tc ThreadContext + * @param mode OperatingMode to check + * @return false if mode is valid and implemented, true otherwise + */ +bool badMode32(ThreadContext *tc, OperatingMode mode); + +/** + * badMode is checking if the execution mode provided as an argument is + * valid and implemented. + * + * @param tc ThreadContext + * @param mode OperatingMode to check + * @return false if mode is valid and implemented, true otherwise + */ +bool badMode(ThreadContext *tc, OperatingMode mode); + static inline uint8_t itState(CPSR psr) { |