arch-arm: Implementing SecureEL2 feature for Armv8
authorJordi Vaquero <jordi.vaquero@metempsy.com>
Tue, 14 Jul 2020 09:54:30 +0000 (11:54 +0200)
committerJordi Vaquero <jordi.vaquero@metempsy.com>
Fri, 31 Jul 2020 13:13:57 +0000 (13:13 +0000)
This patch adds Secure EL2 feature. This allows stage1
EL2/EL&0 and stage2 secure translation.
The changes are organized as follow:

  + insts/static_inst.cc: Modify checks for illegalInstruction on eret
  + isa.cc/hh: Enabling contorl bits
  + isa/insts/misc.hh/64.hh: Smc fault trigger.
  + miscregs.cc/hh: Declaration and initialization of new registers
  + self_debug.cc/hh: Add secureEL2 types for breakpoints
  + stage2_lookup.cc/hh: Allow stage2 in secure state.
  + tlb.cc/table_walker.cc: Allow secure state for stage2 and stage 1 EL2&0
                     translation regime
  + utility.cc/hh: New function InSecure and refactor of other helpers
                   to enable secure state

JIRA: https://gem5.atlassian.net/browse/GEM5-686

Change-Id: Ie59438b1828508e944334420da1d8f4745649056
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31394
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
27 files changed:
src/arch/arm/ArmSystem.py
src/arch/arm/fastmodel/CortexA76/thread_context.cc
src/arch/arm/faults.cc
src/arch/arm/insts/static_inst.cc
src/arch/arm/insts/static_inst.hh
src/arch/arm/interrupts.cc
src/arch/arm/interrupts.hh
src/arch/arm/isa.cc
src/arch/arm/isa.hh
src/arch/arm/isa/insts/branch.isa
src/arch/arm/isa/insts/fp.isa
src/arch/arm/isa/insts/misc.isa
src/arch/arm/isa/insts/misc64.isa
src/arch/arm/miscregs.cc
src/arch/arm/miscregs.hh
src/arch/arm/self_debug.cc
src/arch/arm/self_debug.hh
src/arch/arm/semihosting.cc
src/arch/arm/stage2_lookup.cc
src/arch/arm/stage2_lookup.hh
src/arch/arm/system.cc
src/arch/arm/system.hh
src/arch/arm/table_walker.cc
src/arch/arm/tlb.cc
src/arch/arm/tracers/tarmac_record.cc
src/arch/arm/utility.cc
src/arch/arm/utility.hh

index c4cc51fbf17569819964b744cb2b36a7ae32949d..333ae5f31f702dff571abe5754e9bb04f546b872 100644 (file)
@@ -75,6 +75,8 @@ class ArmSystem(System):
         "True if LSE is implemented (ARMv8.1)")
     have_pan = Param.Bool(True,
         "True if Priviledge Access Never is implemented (ARMv8.1)")
+    have_secel2 = Param.Bool(True,
+        "True if Secure EL2 is implemented (ARMv8)")
 
     semihosting = Param.ArmSemihosting(NULL,
         "Enable support for the Arm semihosting by settings this parameter")
index 4016d2bf128be6121730b39f3ae57126171b2358..4e2bfd22acb34b5a97173e1feb24222eb9d93800 100644 (file)
@@ -59,7 +59,7 @@ CortexA76TC::translateAddress(Addr &paddr, Addr vaddr)
         break;
     }
 
-    Iris::CanonicalMsn out_msn = inSecureState(this) ?
+    Iris::CanonicalMsn out_msn = isSecure(this) ?
         Iris::PhysicalMemorySecureMsn : Iris::PhysicalMemoryNonSecureMsn;
 
     // Figure out what memory spaces match the canonical numbers we need.
index 40cf6341c1c5f848d13a302de252955cef42f1e7..300c82c2fe3a5094f0670be3db65d213ca8b2844 100644 (file)
@@ -977,10 +977,12 @@ ArmFaultVals<T>::offset64(ThreadContext *tc)
     } else {
         bool lower_32 = false;
         if (toEL == EL3) {
-            if (!inSecureState(tc) && ArmSystem::haveEL(tc, EL2))
+            if (EL2Enabled(tc))
                 lower_32 = ELIs32(tc, EL2);
             else
                 lower_32 = ELIs32(tc, EL1);
+        } else if (ELIsInHost(tc, fromEL) && fromEL == EL0 && toEL == EL2) {
+            lower_32 = ELIs32(tc, EL0);
         } else {
             lower_32 = ELIs32(tc, static_cast<ExceptionLevel>(toEL - 1));
         }
@@ -1310,7 +1312,7 @@ PrefetchAbort::routeToHyp(ThreadContext *tc) const
     HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
 
     toHyp = fromEL == EL2;
-    toHyp |=  ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) &&
+    toHyp |=  ArmSystem::haveEL(tc, EL2) && !isSecure(tc) &&
         currEL(tc) <= EL1 && (hcr.tge || stage2 ||
                               (source == DebugEvent && hdcr.tde));
      return toHyp;
index 0cbd77645589bd324df8e04dc9b50e490b71defa..12586c7562d1019645ea926920e6d3fa76e6febc 100644 (file)
@@ -634,9 +634,8 @@ ArmStaticInst::softwareBreakpoint32(ExecContext *xc, uint16_t imm) const
     const auto tc = xc->tcBase();
     const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
     const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
-    if ((ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) &&
-         !ELIs32(tc, EL2) && (hcr.tge == 1 || mdcr.tde == 1)) ||
-         !ELIs32(tc, EL1)) {
+    if ((EL2Enabled(tc) && !ELIs32(tc, EL2) &&
+         (hcr.tge || mdcr.tde)) || !ELIs32(tc, EL1)) {
         // Route to AArch64 Software Breakpoint
         return std::make_shared<SoftwareBreakpoint>(machInst, imm);
     } else {
@@ -728,7 +727,7 @@ ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc,
 {
     const bool have_virtualization = ArmSystem::haveVirtualization(tc);
     const bool have_security = ArmSystem::haveSecurity(tc);
-    const bool is_secure = inSecureState(tc);
+    const bool is_secure = isSecure(tc);
     const ExceptionLevel cur_el = currEL(tc);
 
     if (cur_el == EL0 && ELIs64(tc, EL1))
@@ -908,8 +907,7 @@ ArmStaticInst::trapWFx(ThreadContext *tc,
         fault = checkForWFxTrap32(tc, EL1, isWfe);
     }
 
-    if ((fault == NoFault) &&
-        ArmSystem::haveEL(tc, EL2) && !inSecureState(scr, cpsr) &&
+    if ((fault == NoFault) && EL2Enabled(tc) &&
         ((curr_el == EL0) || (curr_el == EL1))) {
 
         fault = checkForWFxTrap32(tc, EL2, isWfe);
@@ -945,7 +943,7 @@ ArmStaticInst::checkSETENDEnabled(ThreadContext *tc, CPSR cpsr) const
         // Get the index of the banked version of SCTLR:
         // SCTLR_s or SCTLR_ns.
         auto banked_sctlr = snsBankedIndex(
-            MISCREG_SCTLR, tc, !inSecureState(tc));
+            MISCREG_SCTLR, tc, !isSecure(tc));
 
         // SCTLR.SED bit is enabling/disabling the ue of SETEND instruction.
         setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(banked_sctlr)).sed;
@@ -1097,22 +1095,34 @@ illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
     if (unknownMode(mode))
         return true;
 
-    const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode;
-    const ExceptionLevel target_el = opModeToEL(mode);
+    SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
+    HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
 
-    HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2));
-    SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3));
-
-    if (target_el > opModeToEL(cur_mode))
-        return true;
-
-    if (!ArmSystem::haveEL(tc, target_el))
-        return true;
-
-    if (target_el == EL1 && ArmSystem::haveEL(tc, EL2) && scr.ns && hcr.tge)
+    //ELFromSPSR
+    bool valid;
+    ExceptionLevel target_el = opModeToEL(mode);
+    if (!spsr.width) {
+        if (!ArmSystem::highestELIs64(tc)) {
+            valid = false;
+        } else if (!ArmSystem::haveEL(tc, target_el)) {
+            valid = false;
+        } else if (spsr & 0x2) {
+            valid = false;
+        } else if (target_el == EL0 && spsr.sp) {
+            valid = false;
+        } else if (target_el == EL2 && ArmSystem::haveEL(tc, EL3) &&
+                   !scr.ns && !IsSecureEL2Enabled(tc)) {
+            valid = false;
+        } else {
+            valid = true;
+        }
+    } else {
+        valid = !unknownMode32(mode);
+    }
+    if (!valid)
         return true;
 
-    if (target_el == EL2 && ArmSystem::haveEL(tc, EL3) && !scr.ns)
+    if (target_el > currEL(tc))
         return true;
 
     bool spsr_mode_is_aarch32 = (spsr.width == 1);
@@ -1123,17 +1133,9 @@ illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
     if (known && (spsr_mode_is_aarch32 != target_el_is_aarch32))
         return true;
 
-    if (!spsr.width) {
-        // aarch64
-        if (!ArmSystem::highestELIs64(tc))
-            return true;
-        if (spsr & 0x2)
-            return true;
-        if (target_el == EL0 && spsr.sp)
-            return true;
-    } else {
-        // aarch32
-        return unknownMode32(mode);
+    if (target_el == EL1 && ArmSystem::haveEL(tc, EL2) && hcr.tge &&
+            (IsSecureEL2Enabled(tc) || !isSecureBelowEL3(tc))) {
+        return true;
     }
 
     return false;
@@ -1206,7 +1208,7 @@ ArmStaticInst::generalExceptionsToAArch64(ThreadContext *tc,
     // AArch64 or TGE is in force and EL2 is using AArch64.
     HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2));
     return (pstateEL == EL0 && !ELIs32(tc, EL1)) ||
-           (ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) &&
+           (ArmSystem::haveEL(tc, EL2) && !isSecure(tc) &&
                !ELIs32(tc, EL2) && hcr.tge);
 }
 
index 8610f996fd0f5e3bac9a8c457170b91d7bc30aeb..2677a105c90c9ab81a900774ed27e2c188ab750d 100644 (file)
@@ -214,8 +214,7 @@ class ArmStaticInst : public StaticInst
     {
         bool privileged   = (cpsr.mode != MODE_USER);
         bool haveVirt     = ArmSystem::haveVirtualization(tc);
-        bool haveSecurity = ArmSystem::haveSecurity(tc);
-        bool isSecure     = inSecureState(scr, cpsr) || !haveSecurity;
+        bool isSecure     = ArmISA::isSecure(tc);
 
         uint32_t bitMask = 0;
 
index ae1d4357dc8b8ab47aebdf37a3bc8eb01dabac6f..13c281e4d15ffeeaf4d5ca10276daed60c2fbb24 100644 (file)
@@ -64,7 +64,7 @@ ArmISA::Interrupts::takeInt(InterruptTypes int_type) const
     else
         scr = tc->readMiscReg(MISCREG_SCR_EL3);
 
-    bool is_secure = inSecureState(tc);
+    bool is_secure = isSecure(tc);
 
     switch(int_type) {
       case INT_FIQ:
index 99a1492640216dc1bcf958639ec012762d43e081..695fd3986b5cdca1d45fd596aa472778673cf54c 100644 (file)
@@ -145,7 +145,7 @@ class Interrupts : public BaseInterrupts
         }
 
         bool isHypMode   = currEL(tc) == EL2;
-        bool isSecure    = inSecureState(tc);
+        bool isSecure    = ArmISA::isSecure(tc);
         bool allowVIrq   = !cpsr.i && imo && !isSecure && !isHypMode;
         bool allowVFiq   = !cpsr.f && fmo && !isSecure && !isHypMode;
         bool allowVAbort = !cpsr.a && amo && !isSecure && !isHypMode;
@@ -185,7 +185,7 @@ class Interrupts : public BaseInterrupts
         virtWake  = (hcr.vi || interrupts[INT_VIRT_IRQ]) && hcr.imo;
         virtWake |= (hcr.vf || interrupts[INT_VIRT_FIQ]) && hcr.fmo;
         virtWake |=  hcr.va                              && hcr.amo;
-        virtWake &= (cpsr.mode != MODE_HYP) && !inSecureState(scr, cpsr);
+        virtWake &= (cpsr.mode != MODE_HYP) && !isSecure(tc);
         return maskedIntStatus || virtWake;
     }
 
@@ -195,7 +195,7 @@ class Interrupts : public BaseInterrupts
         bool useHcrMux;
         CPSR isr = 0; // ARM ARM states ISR reg uses same bit possitions as CPSR
 
-        useHcrMux = (cpsr.mode != MODE_HYP) && !inSecureState(scr, cpsr);
+        useHcrMux = (cpsr.mode != MODE_HYP) && !isSecure(tc);
         isr.i = (useHcrMux & hcr.imo) ? (interrupts[INT_VIRT_IRQ] || hcr.vi)
                                       :  interrupts[INT_IRQ];
         isr.f = (useHcrMux & hcr.fmo) ? (interrupts[INT_VIRT_FIQ] || hcr.vf)
@@ -247,7 +247,7 @@ class Interrupts : public BaseInterrupts
         // virtual interrupt, and if its allowed to happen
         // ARM ARM Issue C section B1.9.9, B1.9.11, and B1.9.13
         bool isHypMode   = currEL(tc) == EL2;
-        bool isSecure    = inSecureState(tc);
+        bool isSecure    = ArmISA::isSecure(tc);
         bool allowVIrq   = !cpsr.i && imo && !isSecure && !isHypMode;
         bool allowVFiq   = !cpsr.f && fmo && !isSecure && !isHypMode;
         bool allowVAbort = !cpsr.a && amo && !isSecure && !isHypMode;
index b71ee63841c3a56c536f4815bc60ea1f318c6689..9106b433d90b12dcbc0c2a9074e487a0144de587 100644 (file)
@@ -88,6 +88,7 @@ ISA::ISA(Params *p) : BaseISA(p), system(NULL),
         physAddrRange = system->physAddrRange();
         haveSVE = system->haveSVE();
         havePAN = system->havePAN();
+        haveSecEL2 = system->haveSecEL2();
         sveVL = system->sveVL();
         haveLSE = system->haveLSE();
     } else {
@@ -98,6 +99,7 @@ ISA::ISA(Params *p) : BaseISA(p), system(NULL),
         physAddrRange = 32;  // dummy value
         haveSVE = true;
         havePAN = false;
+        haveSecEL2 = true;
         sveVL = p->sve_vl_se;
         haveLSE = true;
     }
@@ -397,6 +399,13 @@ ISA::initID64(const ArmISAParams *p)
     miscRegs[MISCREG_ID_AA64PFR0_EL1] = insertBits(
         miscRegs[MISCREG_ID_AA64PFR0_EL1], 35, 32,
         haveSVE ? 0x1 : 0x0);
+    // SecEL2
+    miscRegs[MISCREG_ID_AA64PFR0_EL1] = insertBits(
+        miscRegs[MISCREG_ID_AA64PFR0_EL1], 39, 36,
+        haveSecEL2 ? 0x1 : 0x0);
+    miscRegs[MISCREG_ID_AA64ISAR0_EL1] = insertBits(
+        miscRegs[MISCREG_ID_AA64ISAR0_EL1], 39, 36,
+        haveSecEL2 ? 0x1 : 0x0);
     // Large ASID support
     miscRegs[MISCREG_ID_AA64MMFR0_EL1] = insertBits(
         miscRegs[MISCREG_ID_AA64MMFR0_EL1], 7, 4,
@@ -554,7 +563,7 @@ ISA::readMiscReg(int misc_reg)
       case MISCREG_MIDR:
         cpsr = readMiscRegNoEffect(MISCREG_CPSR);
         scr  = readMiscRegNoEffect(MISCREG_SCR);
-        if ((cpsr.mode == MODE_HYP) || inSecureState(scr, cpsr)) {
+        if ((cpsr.mode == MODE_HYP) || isSecure(tc)) {
             return readMiscRegNoEffect(misc_reg);
         } else {
             return readMiscRegNoEffect(MISCREG_VPIDR);
@@ -731,9 +740,7 @@ ISA::readMiscReg(int misc_reg)
             val &= ~(1 << 14);
             // If a CP bit in NSACR is 0 then the corresponding bit in
             // HCPTR is RAO/WI
-            bool secure_lookup = haveSecurity &&
-                inSecureState(readMiscRegNoEffect(MISCREG_SCR),
-                              readMiscRegNoEffect(MISCREG_CPSR));
+            bool secure_lookup = haveSecurity && isSecure(tc);
             if (!secure_lookup) {
                 RegVal mask = readMiscRegNoEffect(MISCREG_NSACR);
                 val |= (mask ^ 0x7FFF) & 0xBFFF;
@@ -764,6 +771,7 @@ ISA::readMiscReg(int misc_reg)
                (haveVirtualization    ? 0x0000000000000200 : 0) | // EL2
                (haveSecurity          ? 0x0000000000002000 : 0) | // EL3
                (haveSVE               ? 0x0000000100000000 : 0) | // SVE
+               (haveSecEL2            ? 0x0000001000000000 : 0) | // SecEL2
                (gicv3CpuInterface     ? 0x0000000001000000 : 0);
       case MISCREG_ID_AA64PFR1_EL1:
         return 0; // bits [63:0] RES0 (reserved for future use)
@@ -1968,9 +1976,7 @@ ISA::setMiscReg(int misc_reg, RegVal val)
             {
                 // If a CP bit in NSACR is 0 then the corresponding bit in
                 // HCPTR is RAO/WI. Same applies to NSASEDIS
-                secure_lookup = haveSecurity &&
-                    inSecureState(readMiscRegNoEffect(MISCREG_SCR),
-                                  readMiscRegNoEffect(MISCREG_CPSR));
+                secure_lookup = haveSecurity && isSecure(tc);
                 if (!secure_lookup) {
                     RegVal oldValue = readMiscRegNoEffect(MISCREG_HCPTR);
                     RegVal mask =
@@ -2464,7 +2470,7 @@ ISA::getCurSveVecLenInBits() const
 
     if (el == EL2 || (el == EL0 && ELIsInHost(tc, el))) {
         len = static_cast<ZCR>(miscRegs[MISCREG_ZCR_EL2]).len;
-    } else if (haveVirtualization && !inSecureState(tc) &&
+    } else if (haveVirtualization && !isSecure(tc) &&
                (el == EL0 || el == EL1)) {
         len = std::min(
             len,
index 00c29bc77c963de94477c74e87c2b9a30b4b42f9..3b90de1346949b0139ac93c4a933748ec630537c 100644 (file)
@@ -95,6 +95,7 @@ namespace ArmISA
         bool haveSVE;
         bool haveLSE;
         bool havePAN;
+        bool haveSecEL2;
 
         /** SVE vector length in quadwords */
         unsigned sveVL;
@@ -695,7 +696,7 @@ namespace ArmISA
             if (hcr.e2h == 0x0 || currEL(tc) != EL2)
                 return misc_reg;
             SCR scr = readMiscRegNoEffect(MISCREG_SCR_EL3);
-            bool sec_el2 = scr.eel2 && false;
+            bool sec_el2 = scr.eel2 && haveSecEL2;
             switch(misc_reg) {
               case MISCREG_SPSR_EL1:
                   return MISCREG_SPSR_EL2;
index f61d0c56a5acf840da4ef219e34bf1416a108689..0928e66e59348693070b6697e456a5961f8e1ea6 100644 (file)
@@ -151,11 +151,10 @@ let {{
     bxjcode = '''
     HSTR hstr = Hstr;
     CPSR cpsr = Cpsr;
-    SCR  scr  = Scr;
 
     if (ArmSystem::haveVirtualization(xc->tcBase()) && hstr.tjdbx &&
-        !inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
-        fault = std::make_shared<HypervisorTrap>(machInst, op1, EC_TRAPPED_BXJ);
+        !isSecure(xc->tcBase()) && (cpsr.mode != MODE_HYP)) {
+       fault = std::make_shared<HypervisorTrap>(machInst, op1, EC_TRAPPED_BXJ);
     }
     IWNPC = Op1;
     '''
index 9e94b86d240e1517a4d7f3ea9e87d713fc4fc481..52b53158cd9e0f238d24405fefa0a6b59dede0b7 100644 (file)
@@ -210,8 +210,7 @@ let {{
 
     vmrsCode = vmrsEnabledCheckCode + '''
     CPSR cpsr = Cpsr;
-    SCR  scr  = Scr;
-    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
+    if (!isSecure(xc->tcBase()) && (cpsr.mode != MODE_HYP)) {
         HCR hcr = Hcr;
         bool hypTrap = false;
         switch(xc->tcBase()->flattenRegId(RegId(MiscRegClass, op1)).index()) {
index 64bf791d59030826dee2f905496aba384e8bc314..3ee0d618fc91f5c2a03d072f6edd90f5c2889e5c 100644 (file)
@@ -95,8 +95,7 @@ let {{
     SCR  scr  = Scr;
 
     if ((cpsr.mode != MODE_USER) && FullSystem) {
-        if (ArmSystem::haveVirtualization(xc->tcBase()) &&
-            !inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP) && hcr.tsc) {
+        if (EL2Enabled(xc->tcBase()) && (cpsr.mode != MODE_HYP) && hcr.tsc) {
             fault = std::make_shared<HypervisorTrap>(machInst, 0,
                                                      EC_SMC_TO_HYP);
         } else {
@@ -121,12 +120,11 @@ let {{
 
     hvcCode = '''
     CPSR cpsr = Cpsr;
-    SCR  scr  = Scr;
 
     // Filter out the various cases where this instruction isn't defined
     if (!FullSystem || !ArmSystem::haveVirtualization(xc->tcBase()) ||
         (cpsr.mode == MODE_USER) ||
-        (ArmSystem::haveSecurity(xc->tcBase()) && (!scr.ns || !scr.hce))) {
+        (isSecure(xc->tcBase()) && !IsSecureEL2Enabled(xc->tcBase()))) {
         fault = disabledFault();
     } else {
         fault = std::make_shared<HypervisorCall>(machInst, imm);
@@ -936,7 +934,7 @@ let {{
     // the register is accessable, in other modes we trap if only if the register
     // IS accessable.
     if (undefined || (!can_read && !(fault != NoFault && !inUserMode(Cpsr) &&
-                                    !inSecureState(Scr, Cpsr)))) {
+                                    !isSecure(xc->tcBase())))) {
         return std::make_shared<UndefinedInstruction>(machInst, false,
                                                       mnemonic);
     }
@@ -970,7 +968,7 @@ let {{
     // the register is accessable, in other modes we trap if only if the register
     // IS accessable.
     if (undefined || (!can_write && !(fault != NoFault && !inUserMode(Cpsr) &&
-                                      !inSecureState(Scr, Cpsr)))) {
+                                      !isSecure(xc->tcBase())))) {
         return std::make_shared<UndefinedInstruction>(machInst, false,
                                                       mnemonic);
     }
@@ -1003,7 +1001,7 @@ let {{
     // the register is accessable, in other modes we trap if only if the register
     // IS accessable.
     if (undefined || (!can_read && !(fault != NoFault && !inUserMode(Cpsr) &&
-                                     !inSecureState(Scr, Cpsr)))) {
+                                     !isSecure(xc->tcBase())))) {
         return std::make_shared<UndefinedInstruction>(machInst, false,
                                                       mnemonic);
     }
@@ -1037,7 +1035,7 @@ let {{
     // the register is accessable, in other modes we trap if only if the register
     // IS accessable.
     if (undefined || (!can_write && !(fault != NoFault && !inUserMode(Cpsr) &&
-                                     !inSecureState(Scr, Cpsr)))) {
+                                     !isSecure(xc->tcBase())))) {
         return std::make_shared<UndefinedInstruction>(machInst, false,
                                                       mnemonic);
     }
@@ -1115,7 +1113,7 @@ let {{
         // of whether the register is accessible, in other modes we
         // trap if only if the register IS accessible.
         if (undefined || (!can_write & !(hypTrap & !inUserMode(Cpsr) &
-                                         !inSecureState(Scr, Cpsr)))) {
+                                         !isSecure(xc->tcBase())))) {
             return std::make_shared<UndefinedInstruction>(machInst, false,
                                                           mnemonic);
         }
index 656a23445ff8b4b22093c52670bc3e70474ec4d3..a8a8be6aa6fcf92d3a66eb2d97176929c28a577c 100644 (file)
@@ -56,7 +56,8 @@ let {{
     ExceptionLevel pstate_EL = (ExceptionLevel)(uint8_t)(cpsr.el);
 
     bool unalloc_encod = !ArmSystem::haveEL(tc, EL2) || pstate_EL == EL0 ||
-                         (pstate_EL == EL1 && inSecureState(tc));
+                         (pstate_EL == EL1 && (!IsSecureEL2Enabled(tc) &&
+                         isSecure(tc)));
 
     bool hvc_enable = ArmSystem::haveEL(tc, EL3) ?
         scr.hce : !hcr.hcd;
index 5aa5adab2040e74fc1d05e2b0abd43c8f20f2a42..932abc391936b18ba744eac53526e8b6229c41ce 100644 (file)
@@ -2356,6 +2356,14 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
                         return MISCREG_VTCR_EL2;
                     }
                     break;
+                  case 6:
+                    switch (op2) {
+                      case 0:
+                        return MISCREG_VSTTBR_EL2;
+                      case 2:
+                        return MISCREG_VSTCR_EL2;
+                    }
+                    break;
                 }
                 break;
               case 5:
@@ -4880,6 +4888,10 @@ ISA::initializeMiscRegMetadata()
     InitReg(MISCREG_VTCR_EL2)
       .hyp().mon()
       .mapsTo(MISCREG_VTCR);
+    InitReg(MISCREG_VSTTBR_EL2)
+      .hyp().mon();
+    InitReg(MISCREG_VSTCR_EL2)
+      .hyp().mon();
     InitReg(MISCREG_TTBR0_EL3)
       .mon();
     InitReg(MISCREG_TCR_EL3)
index 5b09f34078565ec8185d803c958c14f550b72bb4..f683297a168556c1199e5b7de76d84de84eb51e3 100644 (file)
@@ -596,6 +596,8 @@ namespace ArmISA
         MISCREG_TCR_EL2,
         MISCREG_VTTBR_EL2,
         MISCREG_VTCR_EL2,
+        MISCREG_VSTTBR_EL2,
+        MISCREG_VSTCR_EL2,
         MISCREG_TTBR0_EL3,
         MISCREG_TCR_EL3,
         MISCREG_DACR32_EL2,
@@ -1695,6 +1697,8 @@ namespace ArmISA
         "tcr_el2",
         "vttbr_el2",
         "vtcr_el2",
+        "vsttbr_el2",
+        "vstcr_el2",
         "ttbr0_el3",
         "tcr_el3",
         "dacr32_el2",
index 790e04bf6c71cce6223e9e35c50a72cc77e46ad9..ef6ad63225a73e705a5b315defd39fe49ce7bc49 100644 (file)
@@ -165,7 +165,7 @@ SelfDebug::isDebugEnabledForEL64(ThreadContext *tc, ExceptionLevel el,
                          bool secure, bool mask)
 {
     bool route_to_el2 =  ArmSystem::haveEL(tc, EL2) &&
-        !secure && enableTdeTge;
+                         (!secure || HaveSecureEL2Ext(tc)) && enableTdeTge;
 
     ExceptionLevel target_el = route_to_el2 ? EL2 : EL1;
     if (oslk || (bSDD && secure && ArmSystem::haveEL(tc, EL3))) {
@@ -269,53 +269,53 @@ BrkPoint::test(ThreadContext *tc, Addr pc, ExceptionLevel el, DBGBCR ctr,
         break;
 
       case 0x8:
-        if (ArmSystem::haveEL(tc, EL2) && !ELIsInHost(tc, el)) {
+        if (EL2Enabled(tc) && !ELIsInHost(tc, el)) {
             v = testVMIDMatch(tc);
         }
         break;
 
       case 0x9:
-        if (from_link && ArmSystem::haveEL(tc, EL2) &&
-            !ELIsInHost(tc, el)) {
+        if (from_link && EL2Enabled(tc) && !ELIsInHost(tc, el)) {
             v = testVMIDMatch(tc);
         }
         break;
 
       case 0xa:
-        if (ArmSystem::haveEL(tc, EL2) && !ELIsInHost(tc, el)) {
+        if (EL2Enabled(tc) && !ELIsInHost(tc, el)) {
             v = testContextMatch(tc, true);
             if (v && !from_link)
                  v = v && testVMIDMatch(tc);
         }
         break;
       case 0xb:
-        if (from_link && ArmSystem::haveEL(tc, EL2) &&
-            !ELIsInHost(tc, el)) {
+        if (from_link && EL2Enabled(tc) && !ELIsInHost(tc, el)) {
             v = testContextMatch(tc, true);
             v = v && testVMIDMatch(tc);
         }
         break;
 
       case 0xc:
-        if (HaveVirtHostExt(tc) && !inSecureState(tc))
+        if (HaveVirtHostExt(tc) && (!isSecure(tc)|| HaveSecureEL2Ext(tc)))
             v = testContextMatch(tc, false);
         break;
 
       case 0xd:
-        if (HaveVirtHostExt(tc) && from_link && !inSecureState(tc))
-            v = testContextMatch(tc, false);
+        if (HaveVirtHostExt(tc) && from_link &&
+            (!isSecure(tc)|| HaveSecureEL2Ext(tc))) {
+             v = testContextMatch(tc, false);
+        }
         break;
 
       case 0xe:
-        if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el)
-                && !inSecureState(tc) ) {
+        if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el) &&
+            (!isSecure(tc)|| HaveSecureEL2Ext(tc))) {
             v = testContextMatch(tc, true); // CONTEXTIDR_EL1
             v = v && testContextMatch(tc, false); // CONTEXTIDR_EL2
         }
         break;
       case 0xf:
-        if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el) && from_link
-                && !inSecureState(tc) ) {
+        if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el) && from_link &&
+            (!isSecure(tc)|| HaveSecureEL2Ext(tc))) {
             v = testContextMatch(tc, true); // CONTEXTIDR_EL1
             v = v && testContextMatch(tc, false); // CONTEXTIDR_EL2
         }
@@ -652,8 +652,9 @@ SoftwareStep::debugExceptionReturnSS(ThreadContext *tc, CPSR spsr,
 
         bool enabled_dst = false;
         bool secure = isSecureBelowEL3(tc) || dest == EL3;
-        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
-        if (cpsr.width) {
+//        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+//        if (cpsr.width) {
+        if (ELIs32(tc, dest)) {
             enabled_dst = conf->isDebugEnabledForEL32(tc, dest, secure,
                                                       spsr.d == 1);
         } else {
@@ -760,7 +761,7 @@ VectorCatch::addressMatching(ThreadContext *tc, Addr addr, ExceptionLevel el)
         Addr vaddress = addr & ~ 0x1f;
         Addr low_addr = bits(addr, 5, 2);
         if (vaddress == vbase) {
-            if (ArmSystem::haveEL(tc, EL3) && !inSecureState(tc)) {
+            if (ArmSystem::haveEL(tc, EL3) && !isSecure(tc)) {
                 uint32_t bmask = 1UL << (low_addr + 24);
                 match_word = match_word | (DBGVCR) bmask;
                 // Non-secure vectors
@@ -772,7 +773,7 @@ VectorCatch::addressMatching(ThreadContext *tc, Addr addr, ExceptionLevel el)
         }
         uint32_t mvbase = getVectorBase(tc, true);
         if (ArmSystem::haveEL(tc, EL3) && ELIs32(tc, EL3) &&
-            inSecureState(tc) && (vaddress == mvbase)) {
+            isSecure(tc) && (vaddress == mvbase)) {
             uint32_t bmask = 1UL << (low_addr + 8);
             match_word = match_word | (DBGVCR) bmask;
             // Monitor vectors
@@ -793,7 +794,7 @@ VectorCatch::addressMatching(ThreadContext *tc, Addr addr, ExceptionLevel el)
         enabled = match_word != 0x0;
         // Check for UNPREDICTABLE case - match on Prefetch Abort and
         // Data Abort vectors
-        ExceptionLevel ELd = debugTargetFrom(tc, inSecureState(tc));
+        ExceptionLevel ELd = debugTargetFrom(tc, isSecure(tc));
         if (((match_word & 0x18001818) != 0x0) && ELd == el) {
             enabled = false;
         }
@@ -818,7 +819,7 @@ VectorCatch::exceptionTrapping(ThreadContext *tc, ExceptionLevel el,
         } else if (ELIs32(tc, EL3) && fault->getToMode() == MODE_MON) {
             mask = (DBGVCR) 0x0000DE00;
         } else {
-            if (inSecureState(tc))
+            if (isSecure(tc))
                 mask = (DBGVCR) 0x000000DE;
             else
                 mask = (DBGVCR) 0xDE000000;
index a1c03eafdffe2b6a01dc57bb5549f7d189d59d34..953a2dcda79e78d935eded1e31272bce3b90436f 100644 (file)
@@ -341,11 +341,11 @@ class SelfDebug
     {
         switch (ssc) {
             case 0x0: return true;
-            case 0x1: return !inSecureState(tc);
-            case 0x2: return inSecureState(tc);
+            case 0x1: return !isSecure(tc);
+            case 0x2: return isSecure(tc);
             case 0x3:
                 {
-                    bool b = hmc? true: inSecureState(tc);
+                    bool b = hmc? true: isSecure(tc);
                     return b;
                 }
             default: panic("Unreachable value");
@@ -372,10 +372,10 @@ class SelfDebug
         CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
         ExceptionLevel el = (ExceptionLevel) currEL(tc);
         if (aarch32) {
-            return isDebugEnabledForEL32(tc, el, inSecureState(tc),
+            return isDebugEnabledForEL32(tc, el, isSecure(tc),
                                          (bool)cpsr.d == 1);
         } else {
-            return isDebugEnabledForEL64(tc, el, inSecureState(tc),
+            return isDebugEnabledForEL64(tc, el, isSecure(tc),
                                          (bool)cpsr.d == 1 );
         }
     }
@@ -464,7 +464,7 @@ class SelfDebug
     bool
     targetAArch32(ThreadContext *tc)
     {
-        ExceptionLevel ELd = debugTargetFrom(tc, inSecureState(tc));
+        ExceptionLevel ELd = debugTargetFrom(tc, isSecure(tc));
         return ELIs32(tc, ELd) && aarch32;
     }
 
index ab21dda1f827c98cb8a2d4dfa54dafbff4db8752..bd7b617cf9f7defc6c5a9e3bfc90da0494d4e472 100644 (file)
@@ -244,7 +244,7 @@ ArmSemihosting::portProxy(ThreadContext *tc)
     static std::unique_ptr<PortProxy> port_proxy_s;
     static System *secure_sys = nullptr;
 
-    if (ArmISA::inSecureState(tc)) {
+    if (ArmISA::isSecure(tc)) {
         System *sys = tc->getSystemPtr();
         if (sys != secure_sys) {
             if (FullSystem) {
index 0fe8edd63775347d204ec8cf7832bae99395674c..93843ab4301bb99714b1fd9a4cd4a80dcba94018 100644 (file)
@@ -55,7 +55,7 @@ Stage2LookUp::getTe(ThreadContext *tc, TlbEntry *destTe)
 
 {
     fault = stage2Tlb->getTE(&stage2Te, req, tc, mode, this, timing,
-                                   functional, false, tranType);
+                                   functional, secure, tranType);
     // Call finish if we're done already
     if ((fault != NoFault) || (stage2Te != NULL)) {
         // Since we directly requested the table entry (which we need later on
@@ -180,7 +180,7 @@ Stage2LookUp::finish(const Fault &_fault, const RequestPtr &req,
     // if we haven't got the table entry get it now
     if ((fault == NoFault) && (stage2Te == NULL)) {
         fault = stage2Tlb->getTE(&stage2Te, req, tc, mode, this,
-            timing, functional, false, tranType);
+            timing, functional, secure, tranType);
     }
 
     // Now we have the stage 2 table entry we need to merge it with the stage
index a9b014a92c4edebfa7f495ef35a2ec75abf8c954..a5a984f9a71576fcb4c27249168d596ff0f53c16 100644 (file)
@@ -69,15 +69,16 @@ class Stage2LookUp : public BaseTLB::Translation
     Fault                   fault;
     bool                    complete;
     bool                    selfDelete;
+    bool                    secure;
 
   public:
     Stage2LookUp(TLB *s1Tlb, TLB *s2Tlb, TlbEntry s1Te, const RequestPtr &_req,
         TLB::Translation *_transState, BaseTLB::Mode _mode, bool _timing,
-        bool _functional, TLB::ArmTranslationType _tranType) :
+        bool _functional, bool _secure, TLB::ArmTranslationType _tranType) :
         stage1Tlb(s1Tlb), stage2Tlb(s2Tlb), stage1Te(s1Te), s1Req(_req),
         transState(_transState), mode(_mode), timing(_timing),
         functional(_functional), tranType(_tranType), stage2Te(nullptr),
-        fault(NoFault), complete(false), selfDelete(false)
+        fault(NoFault), complete(false), selfDelete(false), secure(_secure)
     {
         req = std::make_shared<Request>();
         req->setVirt(s1Te.pAddr(s1Req->getVaddr()), s1Req->getSize(),
index 8eb37b7b3a8b99efbfe7c56b7c23c6a23db59bbe..3db13d724ab3398db895d6255ed1a95c53bf49b6 100644 (file)
@@ -70,6 +70,7 @@ ArmSystem::ArmSystem(Params *p)
       _sveVL(p->sve_vl),
       _haveLSE(p->have_lse),
       _havePAN(p->have_pan),
+      _haveSecEL2(p->have_secel2),
       semihosting(p->semihosting),
       multiProc(p->multi_proc)
 {
index 203be1affebe37b705f4e8799164218831aedcb2..cffc23586af622c3851c99f209f4e8edae20d49d 100644 (file)
@@ -128,6 +128,9 @@ class ArmSystem : public System
     /** True if Priviledge Access Never is implemented */
     const unsigned _havePAN;
 
+    /** True if Secure EL2 is implemented */
+    const unsigned _haveSecEL2;
+
     /**
      * True if the Semihosting interface is enabled.
      */
@@ -223,6 +226,9 @@ class ArmSystem : public System
     /** Returns true if Priviledge Access Never is implemented */
     bool havePAN() const { return _havePAN; }
 
+    /** Returns true if Priviledge Access Never is implemented */
+    bool haveSecEL2() const { return _haveSecEL2; }
+
     /** Returns the supported physical address range in bits if the highest
      * implemented exception level is 64 bits (ARMv8) */
     uint8_t physAddrRange64() const { return _physAddrRange64; }
index aa3dbf6e22a8095aa70ac8ed1a62fbf9af3f142e..77f2800448ce7abada84d9cf332a564de0d83258 100644 (file)
@@ -267,7 +267,13 @@ TableWalker::walk(const RequestPtr &_req, ThreadContext *_tc, uint16_t _asid,
         currState->hcr = currState->tc->readMiscReg(MISCREG_HCR_EL2);
         if (isStage2) {
             currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
-            currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR_EL2);
+            if (currState->secureLookup) {
+                currState->vtcr =
+                    currState->tc->readMiscReg(MISCREG_VSTCR_EL2);
+            } else {
+                currState->vtcr =
+                    currState->tc->readMiscReg(MISCREG_VTCR_EL2);
+            }
         } else switch (currState->el) {
           case EL0:
             if (HaveVirtHostExt(currState->tc) &&
@@ -825,8 +831,13 @@ TableWalker::processWalkAArch64()
         break;
       case EL1:
         if (isStage2) {
-            DPRINTF(TLB, " - Selecting VTTBR0 (AArch64 stage 2)\n");
-            ttbr = currState->tc->readMiscReg(MISCREG_VTTBR_EL2);
+            if (currState->secureLookup) {
+                DPRINTF(TLB, " - Selecting VSTTBR_EL2 (AArch64 stage 2)\n");
+                ttbr = currState->tc->readMiscReg(MISCREG_VSTTBR_EL2);
+            } else {
+                DPRINTF(TLB, " - Selecting VTTBR_EL2 (AArch64 stage 2)\n");
+                ttbr = currState->tc->readMiscReg(MISCREG_VTTBR_EL2);
+            }
             tsz = 64 - currState->vtcr.t0sz64;
             tg = GrainMap_tg0[currState->vtcr.tg0];
             // ARM DDI 0487A.f D7-2148
index 0c001b0bc58d286a0d935bcf3bc949eea4cdbd92..a6205ced3a30c189ac26f30daeed991d818cb9d6 100644 (file)
@@ -833,6 +833,8 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode,
     bool w = is_write;
     bool x = is_fetch;
 
+    xn = ArmSystem::haveEL(tc, EL3) && isSecure && te->ns && scr.sif;
+
     // grant_read is used for faults from an atomic instruction that
     // both reads and writes from a memory location. From a ISS point
     // of view they count as read if a read to that address would have
@@ -1351,7 +1353,7 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
     cpsr = tc->readMiscReg(MISCREG_CPSR);
 
     // Dependencies: SCR/SCR_EL3, CPSR
-    isSecure = inSecureState(tc) &&
+    isSecure = ArmISA::isSecure(tc) &&
         !(tranType & HypMode) && !(tranType & S1S2NsTran);
 
     aarch64EL = tranTypeEL(cpsr, tranType);
@@ -1420,11 +1422,17 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
         scr = tc->readMiscReg(MISCREG_SCR_EL3);
         isPriv = aarch64EL != EL0;
         if (haveVirtualization) {
-            vmid  = bits(tc->readMiscReg(MISCREG_VTTBR_EL2), 55, 48);
+            uint64_t vttbr = isSecure? tc->readMiscReg(MISCREG_VSTTBR_EL2):
+                                       tc->readMiscReg(MISCREG_VTTBR_EL2);
+            vmid           = bits(vttbr, 55, 48);
             isHyp = aarch64EL == EL2;
             isHyp |= tranType & HypMode;
             isHyp &= (tranType & S1S2NsTran) == 0;
             isHyp &= (tranType & S1CTran)    == 0;
+            bool vm = hcr.vm;
+            if (HaveVirtHostExt(tc) && hcr.e2h == 1 && hcr.tge ==1) {
+                vm = 0;
+            }
 
             if (hcr.e2h == 1 && (aarch64EL == EL2
                                   || (hcr.tge ==1 && aarch64EL == EL0))) {
@@ -1436,16 +1444,12 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
             // Work out if we should skip the first stage of translation and go
             // directly to stage 2. This value is cached so we don't have to
             // compute it for every translation.
-                bool vm = hcr.vm;
-                if (HaveVirtHostExt(tc) && hcr.e2h == 1 && hcr.tge == 1) {
-                    vm = 0;
-                }
-
+                bool sec = !isSecure || (isSecure && IsSecureEL2Enabled(tc));
                 stage2Req = isStage2 ||
-                            (vm && !isHyp && !isSecure &&
+                            (vm && !isHyp && sec &&
                              !(tranType & S1CTran) && (aarch64EL < EL2) &&
                              !(tranType & S1E1Tran)); // <--- FIX THIS HACK
-                stage2DescReq = isStage2 ||  (vm && !isHyp && !isSecure &&
+                stage2DescReq = isStage2 ||  (vm && !isHyp && sec &&
                                 (aarch64EL < EL2));
                 directToStage2 = !isStage2 && stage2Req && !sctlr.m;
             }
@@ -1494,9 +1498,10 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
             // Work out if we should skip the first stage of translation and go
             // directly to stage 2. This value is cached so we don't have to
             // compute it for every translation.
-            stage2Req      = hcr.vm && !isStage2 && !isHyp && !isSecure &&
+            bool sec = !isSecure || (isSecure && IsSecureEL2Enabled(tc));
+            stage2Req      = hcr.vm && !isStage2 && !isHyp && sec &&
                              !(tranType & S1CTran);
-            stage2DescReq  = hcr.vm && !isStage2 && !isHyp && !isSecure;
+            stage2DescReq  = hcr.vm && !isStage2 && !isHyp && sec;
             directToStage2 = stage2Req && !sctlr.m;
         } else {
             vmid           = 0;
@@ -1652,7 +1657,8 @@ TLB::getResultTe(TlbEntry **te, const RequestPtr &req,
             fault = checkPermissions(s1Te, req, mode);
         if (stage2Req & (fault == NoFault)) {
             Stage2LookUp *s2Lookup = new Stage2LookUp(this, stage2Tlb, *s1Te,
-                req, translation, mode, timing, functional, curTranType);
+                req, translation, mode, timing, functional, !(s1Te->ns),
+                curTranType);
             fault = s2Lookup->getTe(tc, mergeTe);
             if (s2Lookup->isComplete()) {
                 *te = mergeTe;
index ee2e8e21d2b14e5fa58cc3224258a3188f6c7090..4b7f43d2378c968f2581e0a2b382137b87314762 100644 (file)
@@ -118,7 +118,7 @@ TarmacTracerRecord::TraceInstEntry::TraceInstEntry(
     bool predicate)
       : InstEntry(tarmCtx.thread, tarmCtx.pc, tarmCtx.staticInst, predicate)
 {
-    secureMode = inSecureState(tarmCtx.thread);
+    secureMode = isSecure(tarmCtx.thread);
 
     auto arm_inst = static_cast<const ArmStaticInst*>(
         tarmCtx.staticInst.get()
index 07740a21ce7e30e9d5ff515539ddb7157610c484..1c448343cde3da784bcc7fdd4b2c0c614cd324b1 100644 (file)
@@ -171,12 +171,15 @@ sendEvent(ThreadContext *tc)
 }
 
 bool
-inSecureState(ThreadContext *tc)
+isSecure(ThreadContext *tc)
 {
-    SCR scr = inAArch64(tc) ? tc->readMiscReg(MISCREG_SCR_EL3) :
-        tc->readMiscReg(MISCREG_SCR);
-    return ArmSystem::haveSecurity(tc) && inSecureState(
-        scr, tc->readMiscReg(MISCREG_CPSR));
+    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+    if (ArmSystem::haveEL(tc, EL3) && !cpsr.width && currEL(tc) == EL3)
+        return true;
+    if (ArmSystem::haveEL(tc, EL3) && cpsr.width  && cpsr.mode == MODE_MON)
+        return true;
+    else
+        return isSecureBelowEL3(tc);
 }
 
 bool
@@ -190,14 +193,14 @@ ExceptionLevel
 debugTargetFrom(ThreadContext *tc, bool secure)
 {
     bool route_to_el2;
-    if (ArmSystem::haveEL(tc, EL2) && !secure){
-        if (ELIs32(tc, EL2)){
+    if (ArmSystem::haveEL(tc, EL2) && (!secure || HaveSecureEL2Ext(tc))) {
+        if (ELIs32(tc, EL2)) {
             const HCR hcr = tc->readMiscReg(MISCREG_HCR);
-            const HDCR hdcr  = tc->readMiscRegNoEffect(MISCREG_HDCR);
+            const HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
             route_to_el2 = (hdcr.tde == 1 || hcr.tge == 1);
-        }else{
+        } else {
             const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
-            const HDCR mdcr  = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
+            const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
             route_to_el2 = (mdcr.tde == 1 || hcr.tge == 1);
         }
     }else{
@@ -206,10 +209,10 @@ debugTargetFrom(ThreadContext *tc, bool secure)
     ExceptionLevel target;
     if (route_to_el2) {
         target = EL2;
-    }else if (ArmSystem::haveEL(tc, EL3) && !ArmSystem::highestELIs64(tc)
-              && secure){
+    } else if (ArmSystem::haveEL(tc, EL3) && !ArmSystem::highestELIs64(tc)
+              && secure) {
         target = EL3;
-    }else{
+    } else {
         target = EL1;
     }
     return target;
@@ -344,11 +347,12 @@ bool
 IsSecureEL2Enabled(ThreadContext *tc)
 {
     SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
-    if (ArmSystem::haveEL(tc, EL2) && HaveSecureEL2Ext(tc)) {
+    if (ArmSystem::haveEL(tc, EL2) && HaveSecureEL2Ext(tc) &&
+        !ELIs32(tc, EL2)) {
         if (ArmSystem::haveEL(tc, EL3))
             return !ELIs32(tc, EL3) && scr.eel2;
         else
-            return inSecureState(tc);
+            return isSecure(tc);
     }
     return false;
 }
@@ -393,6 +397,20 @@ ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
     return ELStateUsingAArch32K(tc, el, secure);
 }
 
+bool
+haveAArch32EL(ThreadContext *tc, ExceptionLevel el)
+{
+    if (!ArmSystem::haveEL(tc, el))
+        return false;
+    else if (!ArmSystem::highestELIs64(tc))
+        return true;
+    else if (ArmSystem::highestEL(tc) == el)
+        return false;
+    else if (el == EL0)
+        return true;
+    return true;
+}
+
 std::pair<bool, bool>
 ELStateUsingAArch32K(ThreadContext *tc, ExceptionLevel el, bool secure)
 {
@@ -405,30 +423,33 @@ ELStateUsingAArch32K(ThreadContext *tc, ExceptionLevel el, bool secure)
 
     bool known, aarch32;
     known = aarch32 = false;
-    if (ArmSystem::highestELIs64(tc) && ArmSystem::highestEL(tc) == el) {
+    if (!haveAArch32EL(tc, el)) {
         // Target EL is the highest one in a system where
         // the highest is using AArch64.
         known = true; aarch32 = false;
+    } else if (secure && el == EL2) {
+        known = true; aarch32 = false;
     } else if (!ArmSystem::highestELIs64(tc)) {
         // All ELs are using AArch32:
         known = true; aarch32 = true;
+    } else if (ArmSystem::highestEL(tc) == el) {
+        known = true; aarch32 = false;
     } else {
         SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
-        bool aarch32_below_el3 = (have_el3 && scr.rw == 0);
+        bool aarch32_below_el3 = have_el3 && scr.rw == 0 &&
+                            (!secure || !HaveSecureEL2Ext(tc) || !scr.eel2);
 
         HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
-        bool secEL2 = false;
-        bool aarch32_at_el1 = (aarch32_below_el3
-                         || (have_el2
-                             && (secEL2 || !isSecureBelowEL3(tc))
-                             && hcr.rw == 0 && !(hcr.e2h && hcr.tge
-                                                && HaveVirtHostExt(tc))));
+        bool sec_el2 = HaveSecureEL2Ext(tc) && scr.eel2;
+        bool aarch32_at_el1 = (aarch32_below_el3 ||
+                               (have_el2 && (sec_el2 || !secure) &&
+                                hcr.rw == 0 && !(hcr.e2h && hcr.tge &&
+                                                 HaveVirtHostExt(tc))));
 
         // Only know if EL0 using AArch32 from PSTATE
         if (el == EL0 && !aarch32_at_el1) {
             // EL0 controlled by PSTATE
             CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
-
             known = (currEL(tc) == EL0);
             aarch32 = (cpsr.width == 1);
         } else {
index efe9e0808e1ec3ad4776dd00396873df5040bfd7..f00f606ed885082ea4e69108a556b651c72a81ae 100644 (file)
@@ -128,6 +128,8 @@ inPrivilegedMode(ThreadContext *tc)
     return !inUserMode(tc);
 }
 
+bool isSecure(ThreadContext *tc);
+
 bool inAArch64(ThreadContext *tc);
 
 static inline OperatingMode
@@ -256,8 +258,6 @@ inSecureState(SCR scr, CPSR cpsr)
     }
 }
 
-bool inSecureState(ThreadContext *tc);
-
 bool isSecureBelowEL3(ThreadContext *tc);
 
 bool longDescFormatInUse(ThreadContext *tc);