summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiacomo Travaglini <giacomo.travaglini@arm.com>2018-06-07 17:17:16 +0100
committerGiacomo Travaglini <giacomo.travaglini@arm.com>2018-06-22 10:52:55 +0000
commitfc278fffb78512ff3d62a906804d6b285edd00c7 (patch)
tree5c8f488763041f6774ebada7609b86d6a3a865bd
parent3ed0c3c0bef2eefddcf2033e6ab9d22cf45c486d (diff)
downloadgem5-fc278fffb78512ff3d62a906804d6b285edd00c7.tar.xz
arch-arm: BadMode checking if corresponding EL is implemented
The old utility function called badMode was only checking if the mode passed as an argument was a recognized mode. It was not checking if the corresponding mode/EL was implemented. That function has been renamed to unknownMode and a new badMode has been introduced. This is used by the cpsrWriteByInstruction function. In this way any try to change the execution mode won't succeed if the mode hasn't been implemented. Change-Id: Ibfe385c5465b904acc0d2eb9647710891d72c9df Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-on: https://gem5-review.googlesource.com/11196 Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
-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)
{