diff options
Diffstat (limited to 'src/arch/arm')
-rw-r--r-- | src/arch/arm/faults.cc | 31 | ||||
-rw-r--r-- | src/arch/arm/faults.hh | 4 |
2 files changed, 27 insertions, 8 deletions
diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 8d019d58a..d143056b1 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -391,6 +391,7 @@ ArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg) uint32_t value; uint32_t exc_class = (uint32_t) ec(tc); uint32_t issVal = iss(); + assert(!from64 || ArmSystem::highestELIs64(tc)); value = exc_class << 26; @@ -438,12 +439,15 @@ ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) from64 = true; // Determine target exception level - if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) + if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) { toEL = EL3; - else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) + } else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) { toEL = EL2; - else + hypRouted = true; + } else { toEL = opModeToEL(nextMode()); + } + if (fromEL > toEL) toEL = fromEL; @@ -486,12 +490,14 @@ ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) armInst->annotateFault(this); } - if (have_security && routeToMonitor(tc)) + if (have_security && routeToMonitor(tc)) { cpsr.mode = MODE_MON; - else if (have_virtualization && routeToHyp(tc)) + } else if (have_virtualization && routeToHyp(tc)) { cpsr.mode = MODE_HYP; - else + hypRouted = true; + } else { cpsr.mode = nextMode(); + } // Ensure Secure state if initially in Monitor mode if (have_security && saved_cpsr.mode == MODE_MON) { @@ -747,6 +753,12 @@ UndefinedInstruction::routeToHyp(ThreadContext *tc) const uint32_t UndefinedInstruction::iss() const { + + // If UndefinedInstruction is routed to hypervisor, iss field is 0. + if (hypRouted) { + return 0; + } + if (overrideEc == EC_INVALID) return issRaw; @@ -836,7 +848,12 @@ SecureMonitorCall::iss() const ExceptionClass UndefinedInstruction::ec(ThreadContext *tc) const { - return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; + // If UndefinedInstruction is routed to hypervisor, + // HSR.EC field is 0. + if (hypRouted) + return EC_UNKNOWN; + else + return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; } diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh index 3191ceb88..fa6740a1a 100644 --- a/src/arch/arm/faults.hh +++ b/src/arch/arm/faults.hh @@ -73,6 +73,8 @@ class ArmFault : public FaultBase ExceptionLevel toEL; // Target exception level OperatingMode fromMode; // Source operating mode + bool hypRouted; // True if the fault has been routed to Hypervisor + Addr getVector(ThreadContext *tc); Addr getVector64(ThreadContext *tc); @@ -173,7 +175,7 @@ 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) {} + fromEL(EL0), toEL(EL0), fromMode(MODE_UNDEFINED), hypRouted(false) {} // Returns the actual syndrome register to use based on the target // exception level |