summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/insts/static_inst.cc6
-rw-r--r--src/arch/arm/insts/static_inst.hh2
-rw-r--r--src/arch/arm/isa/formats/mem.isa7
-rw-r--r--src/arch/arm/isa/formats/uncond.isa7
-rw-r--r--src/arch/arm/isa/insts/str.isa6
-rw-r--r--src/arch/arm/types.hh5
-rw-r--r--src/arch/arm/utility.cc12
-rw-r--r--src/arch/arm/utility.hh20
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)
{