arch-arm: Introduce update method in ArmFault class

There is a set of internal variables in ArmFault thats get updated once
the fault is invoked (ArmFault::invoke). Sometimes we rely on those even
if the fault is generated but not invoked (e.g. when checking if a
memory access is producing a fault). This patch is moving the update
functionalities inside a public method so that a client can make use of
it even when not invoking the fault.

Change-Id: I3ac5b6835023f28ec569fe25487dffa356e1b2fd
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/8361
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
Giacomo Travaglini
2018-02-09 10:01:11 +00:00
parent 689221c651
commit dbf7b0adc5
2 changed files with 55 additions and 35 deletions

View File

@@ -426,36 +426,54 @@ ArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
}
void
ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
ArmFault::update(ThreadContext *tc)
{
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
if (ArmSystem::highestELIs64(tc)) { // ARMv8
// Determine source exception level and mode
fromMode = (OperatingMode) (uint8_t) cpsr.mode;
fromEL = opModeToEL(fromMode);
if (opModeIs64(fromMode))
from64 = true;
// Determine source exception level and mode
fromMode = (OperatingMode) (uint8_t) cpsr.mode;
fromEL = opModeToEL(fromMode);
if (opModeIs64(fromMode))
from64 = true;
// Determine target exception level
if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) {
toEL = EL3;
} else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) {
toEL = EL2;
hypRouted = true;
} else {
toEL = opModeToEL(nextMode());
}
// Determine target exception level (aarch64) or target execution
// mode (aarch32).
if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) {
toMode = MODE_MON;
toEL = EL3;
} else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) {
toMode = MODE_HYP;
toEL = EL2;
hypRouted = true;
} else {
toMode = nextMode();
toEL = opModeToEL(toMode);
}
if (fromEL > toEL)
toEL = fromEL;
if (fromEL > toEL)
toEL = fromEL;
if (toEL == ArmSystem::highestEL(tc) || ELIs64(tc, toEL)) {
// Invoke exception handler in AArch64 state
to64 = true;
invoke64(tc, inst);
return;
}
to64 = ELIs64(tc, toEL);
// The fault specific informations have been updated; it is
// now possible to use them inside the fault.
faultUpdated = true;
}
void
ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
{
// Update fault state informations, like the starting mode (aarch32)
// or EL (aarch64) and the ending mode or EL.
// From the update function we are also evaluating if the fault must
// be handled in AArch64 mode (to64).
update(tc);
if (to64) {
// Invoke exception handler in AArch64 state
invoke64(tc, inst);
return;
}
// ARMv7 (ARM ARM issue C B1.9)
@@ -489,15 +507,6 @@ ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
armInst->annotateFault(this);
}
if (have_security && routeToMonitor(tc)) {
cpsr.mode = MODE_MON;
} else if (have_virtualization && routeToHyp(tc)) {
cpsr.mode = MODE_HYP;
hypRouted = true;
} else {
cpsr.mode = nextMode();
}
// Ensure Secure state if initially in Monitor mode
if (have_security && saved_cpsr.mode == MODE_MON) {
SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
@@ -507,6 +516,9 @@ ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
}
}
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
cpsr.mode = toMode;
// some bits are set differently if we have been routed to hyp mode
if (cpsr.mode == MODE_HYP) {
SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);

View File

@@ -71,7 +71,13 @@ class ArmFault : public FaultBase
bool to64; // True if the exception is taken in AArch64 state
ExceptionLevel fromEL; // Source exception level
ExceptionLevel toEL; // Target exception level
OperatingMode fromMode; // Source operating mode
OperatingMode fromMode; // Source operating mode (aarch32)
OperatingMode toMode; // Next operating mode (aarch32)
// This variable is true if the above fault specific informations
// have been updated. This is to prevent that a client is using their
// un-updated default constructed value.
bool faultUpdated;
bool hypRouted; // True if the fault has been routed to Hypervisor
@@ -191,7 +197,8 @@ class ArmFault : public FaultBase
ArmFault(ExtMachInst _machInst = 0, uint32_t _iss = 0) :
machInst(_machInst), issRaw(_iss), from64(false), to64(false),
fromEL(EL0), toEL(EL0), fromMode(MODE_UNDEFINED), hypRouted(false) {}
fromEL(EL0), toEL(EL0), fromMode(MODE_UNDEFINED),
faultUpdated(false), hypRouted(false) {}
// Returns the actual syndrome register to use based on the target
// exception level
@@ -204,6 +211,7 @@ class ArmFault : public FaultBase
StaticInst::nullStaticInstPtr) override;
void invoke64(ThreadContext *tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr);
void update(ThreadContext *tc);
virtual void annotate(AnnotationIDs id, uint64_t val) {}
virtual FaultStat& countStat() = 0;
virtual FaultOffset offset(ThreadContext *tc) = 0;