summaryrefslogtreecommitdiff
path: root/src/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm')
-rw-r--r--src/arch/arm/faults.cc80
-rw-r--r--src/arch/arm/faults.hh12
2 files changed, 56 insertions, 36 deletions
diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc
index 1d6d01592..310545bc3 100644
--- a/src/arch/arm/faults.cc
+++ b/src/arch/arm/faults.cc
@@ -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 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 source exception level and mode
+ fromMode = (OperatingMode) (uint8_t) cpsr.mode;
+ fromEL = opModeToEL(fromMode);
+ if (opModeIs64(fromMode))
+ from64 = true;
+
+ // 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);
diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh
index 537405cf2..f663b5cfc 100644
--- a/src/arch/arm/faults.hh
+++ b/src/arch/arm/faults.hh
@@ -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;