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>
This commit is contained in:
Giacomo Travaglini
2018-06-07 17:17:16 +01:00
parent 3ed0c3c0be
commit fc278fffb7
8 changed files with 56 additions and 9 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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,

View File

@@ -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:

View File

@@ -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);

View File

@@ -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:

View File

@@ -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)

View File

@@ -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)
{