arch-arm: GenericTimer arch regs, perms/trapping
authorAdrian Herrera <adrian.herrera@arm.com>
Thu, 7 Nov 2019 12:59:27 +0000 (12:59 +0000)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 10 Mar 2020 13:53:13 +0000 (13:53 +0000)
This patch enhances the Generic Timer architected registers handling:

- Reordering of miscregs for easier switch/case ranges
- Implement _EL12 reg versions for E2H environments
- AArch32/64 EL0/EL1/EL2 arch compliant trapping for all registers
    + Rely on CNTKCTL and CNTHCTL access controls
- UNDEFINED behaviour from EL0(NS)
- EL1(S) timer traps to EL3 when SCR.ST == 0

Change-Id: I4f018e103cf8f7323060516121838f90278b1c3e
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/25307
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/arch/arm/insts/misc64.cc
src/arch/arm/isa.cc
src/arch/arm/isa/insts/misc.isa
src/arch/arm/miscregs.cc
src/arch/arm/miscregs.hh
src/arch/arm/utility.cc
src/arch/arm/utility.hh
src/dev/arm/generic_timer_miscregs_types.hh

index 0c466366425397fb86bb0756bcd58bc10e0582f8..7342527ad61bcd18b9ac8e3b1a84322b78abfd6a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2013,2017-2019 ARM Limited
+ * Copyright (c) 2011-2013,2017-2020 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -125,6 +125,11 @@ MiscRegOp64::checkEL1Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
             immediate = 0x1E00000;
         }
         break;
+      // Generic Timer
+      case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
+        trap_to_sup = el == EL0 &&
+                      isGenericTimerSystemAccessTrapEL1(misc_reg, tc);
+        break;
       default:
         break;
     }
@@ -292,6 +297,11 @@ MiscRegOp64::checkEL2Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
                     trap_to_hyp = hcr.imo && el == EL1;
             }
             break;
+          // Generic Timer
+          case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
+            trap_to_hyp = el <= EL1 &&
+                          isGenericTimerSystemAccessTrapEL2(misc_reg, tc);
+            break;
           default:
             break;
         }
@@ -340,6 +350,11 @@ MiscRegOp64::checkEL3Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
       case MISCREG_APIBKeyLo_EL1:
         trap_to_mon = (el==EL1 || el==EL2) && scr.apk==0 && ELIs64(tc, EL3);
         break;
+      // Generic Timer
+      case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
+        trap_to_mon = el == EL1 &&
+                      isGenericTimerSystemAccessTrapEL3(misc_reg, tc);
+        break;
       default:
         break;
     }
index 8bd8113147b22a340a39395afcdca70977a23e45..b2175cb493851b9a4836d66b31fd8cc528cc57f0 100644 (file)
@@ -749,13 +749,8 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
         return 0; // bits [63:0] RES0 (reserved for future use)
 
       // Generic Timer registers
-      case MISCREG_CNTHV_CTL_EL2:
-      case MISCREG_CNTHV_CVAL_EL2:
-      case MISCREG_CNTHV_TVAL_EL2:
-      case MISCREG_CNTFRQ ... MISCREG_CNTHP_CTL:
-      case MISCREG_CNTPCT ... MISCREG_CNTHP_CVAL:
-      case MISCREG_CNTKCTL_EL1 ... MISCREG_CNTV_CVAL_EL0:
-      case MISCREG_CNTVOFF_EL2 ... MISCREG_CNTPS_CVAL_EL1:
+      case MISCREG_CNTFRQ ... MISCREG_CNTVOFF:
+      case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
         return getGenericTimer(tc).readMiscReg(misc_reg);
 
       case MISCREG_ICC_AP0R0 ... MISCREG_ICH_LRC15:
@@ -2085,13 +2080,8 @@ ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
             break;
 
           // Generic Timer registers
-          case MISCREG_CNTHV_CTL_EL2:
-          case MISCREG_CNTHV_CVAL_EL2:
-          case MISCREG_CNTHV_TVAL_EL2:
-          case MISCREG_CNTFRQ ... MISCREG_CNTHP_CTL:
-          case MISCREG_CNTPCT ... MISCREG_CNTHP_CVAL:
-          case MISCREG_CNTKCTL_EL1 ... MISCREG_CNTV_CVAL_EL0:
-          case MISCREG_CNTVOFF_EL2 ... MISCREG_CNTPS_CVAL_EL1:
+          case MISCREG_CNTFRQ ... MISCREG_CNTVOFF:
+          case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
             getGenericTimer(tc).setMiscReg(misc_reg, newVal);
             break;
           case MISCREG_ICC_AP0R0 ... MISCREG_ICH_LRC15:
index f0394be3215e36d629e9c10f5de3b9e878d70f94..0c6fdc31a521bd5dac5e25ce3171115a902733f5 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode:c++ -*-
 
-// Copyright (c) 2010-2013,2017-2019 ARM Limited
+// Copyright (c) 2010-2013,2017-2020 ARM Limited
 // All rights reserved
 //
 // The license below extends only to copyright in the software and shall
@@ -867,7 +867,8 @@ let {{
     MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
                                RegId(MiscRegClass, op1)).index();
     bool can_read, undefined;
-    std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
+    std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr,
+                                                     xc->tcBase());
     if (!can_read || undefined) {
         return std::make_shared<UndefinedInstruction>(machInst, false,
                                                       mnemonic);
@@ -892,7 +893,8 @@ let {{
     MiscRegIndex miscReg = (MiscRegIndex) xc->tcBase()->flattenRegId(
                                RegId(MiscRegClass, dest)).index();
     bool can_write, undefined;
-    std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
+    std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr,
+                                                       xc->tcBase());
     if (undefined || !can_write) {
         return std::make_shared<UndefinedInstruction>(machInst, false,
                                                       mnemonic);
@@ -918,21 +920,21 @@ let {{
                            xc->tcBase()->flattenRegId(RegId(MiscRegClass,
                                                       preFlatOp1)).index();
 
-    bool hypTrap = mcrMrc15TrapToHyp(miscReg, xc->tcBase(), imm);
+    Fault fault = mcrMrc15Trap(miscReg, machInst, xc->tcBase(), imm);
 
     bool can_read, undefined;
-    std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
+    std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr,
+                                                     xc->tcBase());
     // if we're in non secure PL1 mode then we can trap regargless of whether
     // the register is accessable, in other modes we trap if only if the register
     // IS accessable.
-    if (undefined || (!can_read && !(hypTrap && !inUserMode(Cpsr) &&
+    if (undefined || (!can_read && !(fault != NoFault && !inUserMode(Cpsr) &&
                                     !inSecureState(Scr, Cpsr)))) {
         return std::make_shared<UndefinedInstruction>(machInst, false,
                                                       mnemonic);
     }
-    if (hypTrap) {
-        return std::make_shared<HypervisorTrap>(machInst, imm,
-                                                EC_TRAPPED_CP15_MCR_MRC);
+    if (fault != NoFault) {
+        return fault;
     }
     Dest = MiscNsBankedOp1;
     '''
@@ -951,22 +953,22 @@ let {{
                        xc->tcBase()->flattenRegId(RegId(MiscRegClass,
                                                   preFlatDest)).index();
 
-    bool hypTrap = mcrMrc15TrapToHyp(miscReg, xc->tcBase(), imm);
+    Fault fault = mcrMrc15Trap(miscReg, machInst, xc->tcBase(), imm);
 
     bool can_write, undefined;
-    std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
+    std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr,
+                                                       xc->tcBase());
 
     // if we're in non secure PL1 mode then we can trap regargless of whether
     // the register is accessable, in other modes we trap if only if the register
     // IS accessable.
-    if (undefined || (!can_write && !(hypTrap && !inUserMode(Cpsr) &&
+    if (undefined || (!can_write && !(fault != NoFault && !inUserMode(Cpsr) &&
                                       !inSecureState(Scr, Cpsr)))) {
         return std::make_shared<UndefinedInstruction>(machInst, false,
                                                       mnemonic);
     }
-    if (hypTrap) {
-        return std::make_shared<HypervisorTrap>(machInst, imm,
-                                                EC_TRAPPED_CP15_MCR_MRC);
+    if (fault != NoFault) {
+        return fault;
     }
     MiscNsBankedDest = Op1;
     '''
@@ -984,20 +986,22 @@ let {{
     MiscRegIndex miscReg = (MiscRegIndex)
                            xc->tcBase()->flattenRegId(RegId(MiscRegClass,
                                                       preFlatOp1)).index();
-    bool hypTrap = mcrrMrrc15TrapToHyp(miscReg, Cpsr, Scr, Hstr, Hcr, imm);
+
+    Fault fault = mcrrMrrc15Trap(miscReg, machInst, xc->tcBase(), imm);
+
     bool can_read, undefined;
-    std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr);
+    std::tie(can_read, undefined) = canReadCoprocReg(miscReg, Scr, Cpsr,
+                                                     xc->tcBase());
     // if we're in non secure PL1 mode then we can trap regargless of whether
     // the register is accessable, in other modes we trap if only if the register
     // IS accessable.
-    if (undefined || (!can_read && !(hypTrap && !inUserMode(Cpsr) &&
+    if (undefined || (!can_read && !(fault != NoFault && !inUserMode(Cpsr) &&
                                      !inSecureState(Scr, Cpsr)))) {
         return std::make_shared<UndefinedInstruction>(machInst, false,
                                                       mnemonic);
     }
-    if (hypTrap) {
-        return std::make_shared<HypervisorTrap>(machInst, imm,
-                                                EC_TRAPPED_CP15_MCRR_MRRC);
+    if (fault != NoFault) {
+        return fault;
     }
     Dest = bits(MiscNsBankedOp164, 63, 32);
     Dest2 = bits(MiscNsBankedOp164, 31, 0);
@@ -1015,21 +1019,23 @@ let {{
     MiscRegIndex miscReg = (MiscRegIndex)
                            xc->tcBase()->flattenRegId(RegId(MiscRegClass,
                                                       preFlatDest)).index();
-    bool hypTrap  = mcrrMrrc15TrapToHyp(miscReg, Cpsr, Scr, Hstr, Hcr, imm);
+
+    Fault fault = mcrrMrrc15Trap(miscReg, machInst, xc->tcBase(), imm);
+
     bool can_write, undefined;
-    std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
+    std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr,
+                                                       xc->tcBase());
 
     // if we're in non secure PL1 mode then we can trap regargless of whether
     // the register is accessable, in other modes we trap if only if the register
     // IS accessable.
-    if (undefined || (!can_write && !(hypTrap && !inUserMode(Cpsr) &&
+    if (undefined || (!can_write && !(fault != NoFault && !inUserMode(Cpsr) &&
                                      !inSecureState(Scr, Cpsr)))) {
         return std::make_shared<UndefinedInstruction>(machInst, false,
                                                       mnemonic);
     }
-    if (hypTrap) {
-        return std::make_shared<HypervisorTrap>(machInst, imm,
-                                                EC_TRAPPED_CP15_MCRR_MRRC);
+    if (fault != NoFault) {
+        return fault;
     }
     MiscNsBankedDest64 = ((uint64_t) Op1 << 32) | Op2;
     '''
@@ -1095,7 +1101,8 @@ let {{
         bool hypTrap = mcrMrc15TrapToHyp(miscReg, xc->tcBase(), imm);
 
         bool can_write, undefined;
-        std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr);
+        std::tie(can_write, undefined) = canWriteCoprocReg(miscReg, Scr, Cpsr,
+                                                           xc->tcBase());
 
         // if we're in non secure PL1 mode then we can trap regardless
         // of whether the register is accessible, in other modes we
index f8a9387f174251cd1c328eb03c6b66bf1ce07769..3c80de4bf60f4f5c3c8fa7751877eefff83f2bb2 100644 (file)
@@ -984,7 +984,7 @@ decodeCP15Reg64(unsigned crm, unsigned opc1)
 }
 
 std::tuple<bool, bool>
-canReadCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr)
+canReadCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr, ThreadContext *tc)
 {
     bool secure = !scr.ns;
     bool canRead = false;
@@ -1014,13 +1014,23 @@ canReadCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr)
       default:
         undefined = true;
     }
+
+    switch (reg) {
+      case MISCREG_CNTFRQ ... MISCREG_CNTVOFF:
+        if (!undefined)
+            undefined = AArch32isUndefinedGenericTimer(reg, tc);
+        break;
+      default:
+        break;
+    }
+
     // can't do permissions checkes on the root of a banked pair of regs
     assert(!miscRegInfo[reg][MISCREG_BANKED]);
     return std::make_tuple(canRead, undefined);
 }
 
 std::tuple<bool, bool>
-canWriteCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr)
+canWriteCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr, ThreadContext *tc)
 {
     bool secure = !scr.ns;
     bool canWrite = false;
@@ -1050,11 +1060,33 @@ canWriteCoprocReg(MiscRegIndex reg, SCR scr, CPSR cpsr)
       default:
         undefined = true;
     }
+
+    switch (reg) {
+      case MISCREG_CNTFRQ ... MISCREG_CNTVOFF:
+        if (!undefined)
+            undefined = AArch32isUndefinedGenericTimer(reg, tc);
+        break;
+      default:
+        break;
+    }
+
     // can't do permissions checkes on the root of a banked pair of regs
     assert(!miscRegInfo[reg][MISCREG_BANKED]);
     return std::make_tuple(canWrite, undefined);
 }
 
+bool
+AArch32isUndefinedGenericTimer(MiscRegIndex reg, ThreadContext *tc)
+{
+    if (currEL(tc) == EL0 && ELIs32(tc, EL1)) {
+        const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+        bool trap_cond = condGenericTimerSystemAccessTrapEL1(reg, tc);
+        if (trap_cond && (!EL2Enabled(tc) || !hcr.tge))
+            return true;
+    }
+    return false;
+}
+
 int
 snsBankedIndex(MiscRegIndex reg, ThreadContext *tc)
 {
@@ -2794,6 +2826,36 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
                     break;
                 }
                 break;
+              case 5:
+                switch (crm) {
+                  case 1:
+                    switch (op2) {
+                      case 0:
+                        return MISCREG_CNTKCTL_EL12;
+                    }
+                    break;
+                  case 2:
+                    switch (op2) {
+                      case 0:
+                        return MISCREG_CNTP_TVAL_EL02;
+                      case 1:
+                        return MISCREG_CNTP_CTL_EL02;
+                      case 2:
+                        return MISCREG_CNTP_CVAL_EL02;
+                    }
+                    break;
+                  case 3:
+                    switch (op2) {
+                      case 0:
+                        return MISCREG_CNTV_TVAL_EL02;
+                      case 1:
+                        return MISCREG_CNTV_CTL_EL02;
+                      case 2:
+                        return MISCREG_CNTV_CVAL_EL02;
+                    }
+                    break;
+                }
+                break;
               case 7:
                 switch (crm) {
                   case 2:
@@ -3702,42 +3764,78 @@ ISA::initializeMiscRegMetadata()
       .secure().exceptUserMode();
     InitReg(MISCREG_HTPIDR)
       .hyp().monNonSecure();
+    // BEGIN Generic Timer (AArch32)
     InitReg(MISCREG_CNTFRQ)
       .reads(1)
       .highest(system)
       .privSecureWrite(aarch32EL3);
-    InitReg(MISCREG_CNTKCTL)
-      .allPrivileges().exceptUserMode();
-    InitReg(MISCREG_CNTP_TVAL)
-      .banked();
-    InitReg(MISCREG_CNTP_TVAL_NS)
-      .bankedChild()
-      .allPrivileges()
-      .privSecure(!aarch32EL3)
-      .monSecure(0);
-    InitReg(MISCREG_CNTP_TVAL_S)
-      .bankedChild()
-      .secure().user(1);
+    InitReg(MISCREG_CNTPCT)
+      .unverifiable()
+      .reads(1);
+    InitReg(MISCREG_CNTVCT)
+      .unverifiable()
+      .reads(1);
     InitReg(MISCREG_CNTP_CTL)
       .banked();
     InitReg(MISCREG_CNTP_CTL_NS)
       .bankedChild()
-      .allPrivileges()
+      .nonSecure()
       .privSecure(!aarch32EL3)
-      .monSecure(0);
+      .res0(0xfffffff8);
     InitReg(MISCREG_CNTP_CTL_S)
       .bankedChild()
-      .secure().user(1);
-    InitReg(MISCREG_CNTV_TVAL)
-      .allPrivileges();
+      .secure()
+      .privSecure(aarch32EL3)
+      .res0(0xfffffff8);
+    InitReg(MISCREG_CNTP_CVAL)
+      .banked();
+    InitReg(MISCREG_CNTP_CVAL_NS)
+      .bankedChild()
+      .nonSecure()
+      .privSecure(!aarch32EL3);
+    InitReg(MISCREG_CNTP_CVAL_S)
+      .bankedChild()
+      .secure()
+      .privSecure(aarch32EL3);
+    InitReg(MISCREG_CNTP_TVAL)
+      .banked();
+    InitReg(MISCREG_CNTP_TVAL_NS)
+      .bankedChild()
+      .nonSecure()
+      .privSecure(!aarch32EL3);
+    InitReg(MISCREG_CNTP_TVAL_S)
+      .bankedChild()
+      .secure()
+      .privSecure(aarch32EL3);
     InitReg(MISCREG_CNTV_CTL)
+      .allPrivileges()
+      .res0(0xfffffff8);
+    InitReg(MISCREG_CNTV_CVAL)
       .allPrivileges();
+    InitReg(MISCREG_CNTV_TVAL)
+      .allPrivileges();
+    InitReg(MISCREG_CNTKCTL)
+      .allPrivileges()
+      .exceptUserMode()
+      .res0(0xfffdfc00);
     InitReg(MISCREG_CNTHCTL)
-      .hypWrite().monNonSecureRead();
-    InitReg(MISCREG_CNTHP_TVAL)
-      .hypWrite().monNonSecureRead();
+      .monNonSecure()
+      .hyp()
+      .res0(0xfffdff00);
     InitReg(MISCREG_CNTHP_CTL)
-      .hypWrite().monNonSecureRead();
+      .monNonSecure()
+      .hyp()
+      .res0(0xfffffff8);
+    InitReg(MISCREG_CNTHP_CVAL)
+      .monNonSecure()
+      .hyp();
+    InitReg(MISCREG_CNTHP_TVAL)
+      .monNonSecure()
+      .hyp();
+    InitReg(MISCREG_CNTVOFF)
+      .monNonSecure()
+      .hyp();
+    // END Generic Timer (AArch32)
     InitReg(MISCREG_IL1DATA0)
       .unimplemented()
       .allPrivileges().exceptUserMode();
@@ -3778,27 +3876,6 @@ ISA::initializeMiscRegMetadata()
       .hyp().monNonSecure();
     InitReg(MISCREG_VTTBR)
       .hyp().monNonSecure();
-    InitReg(MISCREG_CNTPCT)
-      .reads(1);
-    InitReg(MISCREG_CNTVCT)
-      .unverifiable()
-      .reads(1);
-    InitReg(MISCREG_CNTP_CVAL)
-      .banked();
-    InitReg(MISCREG_CNTP_CVAL_NS)
-      .bankedChild()
-      .allPrivileges()
-      .privSecure(!aarch32EL3)
-      .monSecure(0);
-    InitReg(MISCREG_CNTP_CVAL_S)
-      .bankedChild()
-      .secure().user(1);
-    InitReg(MISCREG_CNTV_CVAL)
-      .allPrivileges();
-    InitReg(MISCREG_CNTVOFF)
-      .hyp().monNonSecure();
-    InitReg(MISCREG_CNTHP_CVAL)
-      .hypWrite().monNonSecureRead();
     InitReg(MISCREG_CPUMERRSR)
       .unimplemented()
       .allPrivileges().exceptUserMode();
@@ -4446,39 +4523,128 @@ ISA::initializeMiscRegMetadata()
       .mapsTo(MISCREG_HTPIDR);
     InitReg(MISCREG_TPIDR_EL3)
       .mon();
-    InitReg(MISCREG_CNTKCTL_EL1)
-      .allPrivileges().exceptUserMode()
-      .mapsTo(MISCREG_CNTKCTL);
+    // BEGIN Generic Timer (AArch64)
     InitReg(MISCREG_CNTFRQ_EL0)
       .reads(1)
       .highest(system)
       .privSecureWrite(aarch32EL3)
       .mapsTo(MISCREG_CNTFRQ);
     InitReg(MISCREG_CNTPCT_EL0)
+      .unverifiable()
       .reads(1)
-      .mapsTo(MISCREG_CNTPCT); /* 64b */
+      .mapsTo(MISCREG_CNTPCT);
     InitReg(MISCREG_CNTVCT_EL0)
       .unverifiable()
       .reads(1)
-      .mapsTo(MISCREG_CNTVCT); /* 64b */
-    InitReg(MISCREG_CNTP_TVAL_EL0)
-      .allPrivileges()
-      .mapsTo(MISCREG_CNTP_TVAL_NS);
+      .mapsTo(MISCREG_CNTVCT);
     InitReg(MISCREG_CNTP_CTL_EL0)
       .allPrivileges()
+      .res0(0xfffffffffffffff8)
       .mapsTo(MISCREG_CNTP_CTL_NS);
     InitReg(MISCREG_CNTP_CVAL_EL0)
       .allPrivileges()
-      .mapsTo(MISCREG_CNTP_CVAL_NS); /* 64b */
-    InitReg(MISCREG_CNTV_TVAL_EL0)
+      .mapsTo(MISCREG_CNTP_CVAL_NS);
+    InitReg(MISCREG_CNTP_TVAL_EL0)
       .allPrivileges()
-      .mapsTo(MISCREG_CNTV_TVAL);
+      .res0(0xffffffff00000000)
+      .mapsTo(MISCREG_CNTP_TVAL_NS);
     InitReg(MISCREG_CNTV_CTL_EL0)
       .allPrivileges()
+      .res0(0xfffffffffffffff8)
       .mapsTo(MISCREG_CNTV_CTL);
     InitReg(MISCREG_CNTV_CVAL_EL0)
       .allPrivileges()
-      .mapsTo(MISCREG_CNTV_CVAL); /* 64b */
+      .mapsTo(MISCREG_CNTV_CVAL);
+    InitReg(MISCREG_CNTV_TVAL_EL0)
+      .allPrivileges()
+      .res0(0xffffffff00000000)
+      .mapsTo(MISCREG_CNTV_TVAL);
+    InitReg(MISCREG_CNTP_CTL_EL02)
+      .monE2H()
+      .hypE2H()
+      .res0(0xfffffffffffffff8)
+      .mapsTo(MISCREG_CNTP_CTL_NS);
+    InitReg(MISCREG_CNTP_CVAL_EL02)
+      .monE2H()
+      .hypE2H()
+      .mapsTo(MISCREG_CNTP_CVAL_NS);
+    InitReg(MISCREG_CNTP_TVAL_EL02)
+      .monE2H()
+      .hypE2H()
+      .res0(0xffffffff00000000)
+      .mapsTo(MISCREG_CNTP_TVAL_NS);
+    InitReg(MISCREG_CNTV_CTL_EL02)
+      .monE2H()
+      .hypE2H()
+      .res0(0xfffffffffffffff8)
+      .mapsTo(MISCREG_CNTV_CTL);
+    InitReg(MISCREG_CNTV_CVAL_EL02)
+      .monE2H()
+      .hypE2H()
+      .mapsTo(MISCREG_CNTV_CVAL);
+    InitReg(MISCREG_CNTV_TVAL_EL02)
+      .monE2H()
+      .hypE2H()
+      .res0(0xffffffff00000000)
+      .mapsTo(MISCREG_CNTV_TVAL);
+    InitReg(MISCREG_CNTKCTL_EL1)
+      .allPrivileges()
+      .exceptUserMode()
+      .res0(0xfffffffffffdfc00)
+      .mapsTo(MISCREG_CNTKCTL);
+    InitReg(MISCREG_CNTKCTL_EL12)
+      .monE2H()
+      .hypE2H()
+      .res0(0xfffffffffffdfc00)
+      .mapsTo(MISCREG_CNTKCTL);
+    InitReg(MISCREG_CNTPS_CTL_EL1)
+      .mon()
+      .privSecure()
+      .res0(0xfffffffffffffff8);
+    InitReg(MISCREG_CNTPS_CVAL_EL1)
+      .mon()
+      .privSecure();
+    InitReg(MISCREG_CNTPS_TVAL_EL1)
+      .mon()
+      .privSecure()
+      .res0(0xffffffff00000000);
+    InitReg(MISCREG_CNTHCTL_EL2)
+      .mon()
+      .hyp()
+      .res0(0xfffffffffffc0000)
+      .mapsTo(MISCREG_CNTHCTL);
+    InitReg(MISCREG_CNTHP_CTL_EL2)
+      .mon()
+      .hyp()
+      .res0(0xfffffffffffffff8)
+      .mapsTo(MISCREG_CNTHP_CTL);
+    InitReg(MISCREG_CNTHP_CVAL_EL2)
+      .mon()
+      .hyp()
+      .mapsTo(MISCREG_CNTHP_CVAL);
+    InitReg(MISCREG_CNTHP_TVAL_EL2)
+      .mon()
+      .hyp()
+      .res0(0xffffffff00000000)
+      .mapsTo(MISCREG_CNTHP_TVAL);
+    // IF Armv8.1-VHE
+    InitReg(MISCREG_CNTHV_CTL_EL2)
+      .mon()
+      .hyp()
+      .res0(0xfffffffffffffff8);
+    InitReg(MISCREG_CNTHV_CVAL_EL2)
+      .mon()
+      .hyp();
+    InitReg(MISCREG_CNTHV_TVAL_EL2)
+      .mon()
+      .hyp()
+      .res0(0xffffffff00000000);
+    // ENDIF Armv8.1-VHE
+    InitReg(MISCREG_CNTVOFF_EL2)
+      .mon()
+      .hyp()
+      .mapsTo(MISCREG_CNTVOFF);
+    // END Generic Timer (AArch64)
     InitReg(MISCREG_PMEVCNTR0_EL0)
       .allPrivileges();
 //    .mapsTo(MISCREG_PMEVCNTR0);
@@ -4515,27 +4681,6 @@ ISA::initializeMiscRegMetadata()
     InitReg(MISCREG_PMEVTYPER5_EL0)
       .allPrivileges();
 //    .mapsTo(MISCREG_PMEVTYPER5);
-    InitReg(MISCREG_CNTVOFF_EL2)
-      .hyp().mon()
-      .mapsTo(MISCREG_CNTVOFF); /* 64b */
-    InitReg(MISCREG_CNTHCTL_EL2)
-      .mon().hyp()
-      .mapsTo(MISCREG_CNTHCTL);
-    InitReg(MISCREG_CNTHP_TVAL_EL2)
-      .mon().hyp()
-      .mapsTo(MISCREG_CNTHP_TVAL);
-    InitReg(MISCREG_CNTHP_CTL_EL2)
-      .mon().hyp()
-      .mapsTo(MISCREG_CNTHP_CTL);
-    InitReg(MISCREG_CNTHP_CVAL_EL2)
-      .mon().hyp()
-      .mapsTo(MISCREG_CNTHP_CVAL); /* 64b */
-    InitReg(MISCREG_CNTPS_TVAL_EL1)
-      .mon().privSecure();
-    InitReg(MISCREG_CNTPS_CTL_EL1)
-      .mon().privSecure();
-    InitReg(MISCREG_CNTPS_CVAL_EL1)
-      .mon().privSecure();
     InitReg(MISCREG_IL1DATA0_EL1)
       .allPrivileges().exceptUserMode();
     InitReg(MISCREG_IL1DATA1_EL1)
@@ -5040,13 +5185,6 @@ ISA::initializeMiscRegMetadata()
         .mapsTo(MISCREG_ICH_LR15)
         .hyp().mon();
 
-    InitReg(MISCREG_CNTHV_CTL_EL2)
-      .mon().hyp();
-    InitReg(MISCREG_CNTHV_CVAL_EL2)
-      .mon().hyp();
-    InitReg(MISCREG_CNTHV_TVAL_EL2)
-      .mon().hyp();
-
     // SVE
     InitReg(MISCREG_ID_AA64ZFR0_EL1)
         .allPrivileges().exceptUserMode().writes(0);
index f4545777c9b2e865cc81b2952eb28e6613666966..3900a4ccd65ea6b8c40cb24a5aebf0cd95ec4eba 100644 (file)
@@ -46,6 +46,7 @@
 
 #include "arch/arm/miscregs_types.hh"
 #include "base/compiler.hh"
+#include "dev/arm/generic_timer_miscregs_types.hh"
 
 class ThreadContext;
 
@@ -343,19 +344,29 @@ namespace ArmISA
         MISCREG_TPIDRPRW_NS,
         MISCREG_TPIDRPRW_S,
         MISCREG_HTPIDR,
+        // BEGIN Generic Timer (AArch32)
         MISCREG_CNTFRQ,
-        MISCREG_CNTKCTL,
-        MISCREG_CNTP_TVAL,
-        MISCREG_CNTP_TVAL_NS,
-        MISCREG_CNTP_TVAL_S,
+        MISCREG_CNTPCT,
+        MISCREG_CNTVCT,
         MISCREG_CNTP_CTL,
         MISCREG_CNTP_CTL_NS,
         MISCREG_CNTP_CTL_S,
-        MISCREG_CNTV_TVAL,
+        MISCREG_CNTP_CVAL,
+        MISCREG_CNTP_CVAL_NS,
+        MISCREG_CNTP_CVAL_S,
+        MISCREG_CNTP_TVAL,
+        MISCREG_CNTP_TVAL_NS,
+        MISCREG_CNTP_TVAL_S,
         MISCREG_CNTV_CTL,
+        MISCREG_CNTV_CVAL,
+        MISCREG_CNTV_TVAL,
+        MISCREG_CNTKCTL,
         MISCREG_CNTHCTL,
-        MISCREG_CNTHP_TVAL,
         MISCREG_CNTHP_CTL,
+        MISCREG_CNTHP_CVAL,
+        MISCREG_CNTHP_TVAL,
+        MISCREG_CNTVOFF,
+        // END Generic Timer (AArch32)
         MISCREG_IL1DATA0,
         MISCREG_IL1DATA1,
         MISCREG_IL1DATA2,
@@ -370,14 +381,6 @@ namespace ArmISA
         MISCREG_CBAR,
         MISCREG_HTTBR,
         MISCREG_VTTBR,
-        MISCREG_CNTPCT,
-        MISCREG_CNTVCT,
-        MISCREG_CNTP_CVAL,
-        MISCREG_CNTP_CVAL_NS,
-        MISCREG_CNTP_CVAL_S,
-        MISCREG_CNTV_CVAL,
-        MISCREG_CNTVOFF,
-        MISCREG_CNTHP_CVAL,
         MISCREG_CPUMERRSR,
         MISCREG_L2MERRSR,
 
@@ -618,16 +621,38 @@ namespace ArmISA
         MISCREG_TPIDRRO_EL0,
         MISCREG_TPIDR_EL2,
         MISCREG_TPIDR_EL3,
-        MISCREG_CNTKCTL_EL1,
+        // BEGIN Generic Timer (AArch64)
         MISCREG_CNTFRQ_EL0,
         MISCREG_CNTPCT_EL0,
         MISCREG_CNTVCT_EL0,
-        MISCREG_CNTP_TVAL_EL0,
         MISCREG_CNTP_CTL_EL0,
         MISCREG_CNTP_CVAL_EL0,
-        MISCREG_CNTV_TVAL_EL0,
+        MISCREG_CNTP_TVAL_EL0,
         MISCREG_CNTV_CTL_EL0,
         MISCREG_CNTV_CVAL_EL0,
+        MISCREG_CNTV_TVAL_EL0,
+        MISCREG_CNTP_CTL_EL02,
+        MISCREG_CNTP_CVAL_EL02,
+        MISCREG_CNTP_TVAL_EL02,
+        MISCREG_CNTV_CTL_EL02,
+        MISCREG_CNTV_CVAL_EL02,
+        MISCREG_CNTV_TVAL_EL02,
+        MISCREG_CNTKCTL_EL1,
+        MISCREG_CNTKCTL_EL12,
+        MISCREG_CNTPS_CTL_EL1,
+        MISCREG_CNTPS_CVAL_EL1,
+        MISCREG_CNTPS_TVAL_EL1,
+        MISCREG_CNTHCTL_EL2,
+        MISCREG_CNTHP_CTL_EL2,
+        MISCREG_CNTHP_CVAL_EL2,
+        MISCREG_CNTHP_TVAL_EL2,
+        // IF Armv8.1-VHE
+        MISCREG_CNTHV_CTL_EL2,
+        MISCREG_CNTHV_CVAL_EL2,
+        MISCREG_CNTHV_TVAL_EL2,
+        // ENDIF Armv8.1-VHE
+        MISCREG_CNTVOFF_EL2,
+        // END Generic Timer (AArch64)
         MISCREG_PMEVCNTR0_EL0,
         MISCREG_PMEVCNTR1_EL0,
         MISCREG_PMEVCNTR2_EL0,
@@ -640,14 +665,6 @@ namespace ArmISA
         MISCREG_PMEVTYPER3_EL0,
         MISCREG_PMEVTYPER4_EL0,
         MISCREG_PMEVTYPER5_EL0,
-        MISCREG_CNTVOFF_EL2,
-        MISCREG_CNTHCTL_EL2,
-        MISCREG_CNTHP_TVAL_EL2,
-        MISCREG_CNTHP_CTL_EL2,
-        MISCREG_CNTHP_CVAL_EL2,
-        MISCREG_CNTPS_TVAL_EL1,
-        MISCREG_CNTPS_CTL_EL1,
-        MISCREG_CNTPS_CVAL_EL1,
         MISCREG_IL1DATA0_EL1,
         MISCREG_IL1DATA1_EL1,
         MISCREG_IL1DATA2_EL1,
@@ -667,9 +684,6 @@ namespace ArmISA
 
         // Introduced in ARMv8.1
         MISCREG_TTBR1_EL2,
-        MISCREG_CNTHV_CTL_EL2,
-        MISCREG_CNTHV_CVAL_EL2,
-        MISCREG_CNTHV_TVAL_EL2,
 
         MISCREG_ID_AA64MMFR2_EL1,
 
@@ -1308,18 +1322,26 @@ namespace ArmISA
         "tpidrprw_s",
         "htpidr",
         "cntfrq",
-        "cntkctl",
-        "cntp_tval",
-        "cntp_tval_ns",
-        "cntp_tval_s",
+        "cntpct",
+        "cntvct",
         "cntp_ctl",
         "cntp_ctl_ns",
         "cntp_ctl_s",
-        "cntv_tval",
+        "cntp_cval",
+        "cntp_cval_ns",
+        "cntp_cval_s",
+        "cntp_tval",
+        "cntp_tval_ns",
+        "cntp_tval_s",
         "cntv_ctl",
+        "cntv_cval",
+        "cntv_tval",
+        "cntkctl",
         "cnthctl",
-        "cnthp_tval",
         "cnthp_ctl",
+        "cnthp_cval",
+        "cnthp_tval",
+        "cntvoff",
         "il1data0",
         "il1data1",
         "il1data2",
@@ -1334,14 +1356,6 @@ namespace ArmISA
         "cbar",
         "httbr",
         "vttbr",
-        "cntpct",
-        "cntvct",
-        "cntp_cval",
-        "cntp_cval_ns",
-        "cntp_cval_s",
-        "cntv_cval",
-        "cntvoff",
-        "cnthp_cval",
         "cpumerrsr",
         "l2merrsr",
 
@@ -1582,16 +1596,34 @@ namespace ArmISA
         "tpidrro_el0",
         "tpidr_el2",
         "tpidr_el3",
-        "cntkctl_el1",
         "cntfrq_el0",
         "cntpct_el0",
         "cntvct_el0",
-        "cntp_tval_el0",
         "cntp_ctl_el0",
         "cntp_cval_el0",
-        "cntv_tval_el0",
+        "cntp_tval_el0",
         "cntv_ctl_el0",
         "cntv_cval_el0",
+        "cntv_tval_el0",
+        "cntp_ctl_el02",
+        "cntp_cval_el02",
+        "cntp_tval_el02",
+        "cntv_ctl_el02",
+        "cntv_cval_el02",
+        "cntv_tval_el02",
+        "cntkctl_el1",
+        "cntkctl_el12",
+        "cntps_ctl_el1",
+        "cntps_cval_el1",
+        "cntps_tval_el1",
+        "cnthctl_el2",
+        "cnthp_ctl_el2",
+        "cnthp_cval_el2",
+        "cnthp_tval_el2",
+        "cnthv_ctl_el2",
+        "cnthv_cval_el2",
+        "cnthv_tval_el2",
+        "cntvoff_el2",
         "pmevcntr0_el0",
         "pmevcntr1_el0",
         "pmevcntr2_el0",
@@ -1604,14 +1636,6 @@ namespace ArmISA
         "pmevtyper3_el0",
         "pmevtyper4_el0",
         "pmevtyper5_el0",
-        "cntvoff_el2",
-        "cnthctl_el2",
-        "cnthp_tval_el2",
-        "cnthp_ctl_el2",
-        "cnthp_cval_el2",
-        "cntps_tval_el1",
-        "cntps_ctl_el1",
-        "cntps_cval_el1",
         "il1data0_el1",
         "il1data1_el1",
         "il1data2_el1",
@@ -1630,9 +1654,6 @@ namespace ArmISA
         "contextidr_el2",
 
         "ttbr1_el2",
-        "cnthv_ctl_el2",
-        "cnthv_cval_el2",
-        "cnthv_tval_el2",
         "id_aa64mmfr2_el1",
 
         "apdakeyhi_el1",
@@ -1931,10 +1952,11 @@ namespace ArmISA
      * @param the misc reg indicating the coprocessor
      * @param the SCR
      * @param the CPSR
+     * @param the thread context on the core
      * @return a tuple of booleans: can_read, undefined
      */
     std::tuple<bool, bool> canReadCoprocReg(MiscRegIndex reg, SCR scr,
-                                           CPSR cpsr);
+                                            CPSR cpsr, ThreadContext *tc);
 
     /**
      * Check for permission to write coprocessor registers.
@@ -1947,10 +1969,15 @@ namespace ArmISA
      * @param the misc reg indicating the coprocessor
      * @param the SCR
      * @param the CPSR
+     * @param the thread context on the core
      * @return a tuple of booleans: can_write, undefined
      */
     std::tuple<bool, bool> canWriteCoprocReg(MiscRegIndex reg, SCR scr,
-                                             CPSR cpsr);
+                                             CPSR cpsr, ThreadContext *tc);
+
+    // Checks for UNDEFINED behaviours when accessing AArch32
+    // Generic Timer system registers
+    bool AArch32isUndefinedGenericTimer(MiscRegIndex reg, ThreadContext *tc);
 
     // Checks read access permissions to AArch64 system registers
     bool canReadAArch64SysReg(MiscRegIndex reg, HCR hcr, SCR scr, CPSR cpsr,
index e1dffafabcc73d160e1c14f19d1e2ca62173c242..373508cee394e3594b76f24e18fc9742c3342af8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2014, 2016-2019 ARM Limited
+ * Copyright (c) 2009-2014, 2016-2020 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -511,8 +511,19 @@ roundPage(Addr addr)
     return (addr + PageBytes - 1) & ~(PageBytes - 1);
 }
 
+Fault
+mcrMrc15Trap(const MiscRegIndex miscReg, ExtMachInst machInst,
+             ThreadContext *tc, uint32_t imm)
+{
+    ExceptionClass ec = EC_TRAPPED_CP15_MCR_MRC;
+    if (mcrMrc15TrapToHyp(miscReg, tc, imm, &ec))
+        return std::make_shared<HypervisorTrap>(machInst, imm, ec);
+    return AArch64AArch32SystemAccessTrap(miscReg, machInst, tc, imm, ec);
+}
+
 bool
-mcrMrc15TrapToHyp(const MiscRegIndex miscReg, ThreadContext *tc, uint32_t iss)
+mcrMrc15TrapToHyp(const MiscRegIndex miscReg, ThreadContext *tc, uint32_t iss,
+                  ExceptionClass *ec)
 {
     bool        isRead;
     uint32_t    crm;
@@ -647,6 +658,14 @@ mcrMrc15TrapToHyp(const MiscRegIndex miscReg, ThreadContext *tc, uint32_t iss)
                         trapToHype = hcr.imo;
                 }
                 break;
+              case MISCREG_CNTFRQ ... MISCREG_CNTV_TVAL:
+                // CNTFRQ may be trapped only on reads
+                // CNTPCT and CNTVCT are read-only
+                if (MISCREG_CNTFRQ <= miscReg && miscReg <= MISCREG_CNTVCT &&
+                    !isRead)
+                    break;
+                trapToHype = isGenericTimerHypTrap(miscReg, tc, ec);
+                break;
               // No default action needed
               default:
                 break;
@@ -707,9 +726,19 @@ mcrMrc14TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
     return trapToHype;
 }
 
+Fault
+mcrrMrrc15Trap(const MiscRegIndex miscReg, ExtMachInst machInst,
+               ThreadContext *tc, uint32_t imm)
+{
+    ExceptionClass ec = EC_TRAPPED_CP15_MCRR_MRRC;
+    if (mcrrMrrc15TrapToHyp(miscReg, tc, imm, &ec))
+        return std::make_shared<HypervisorTrap>(machInst, imm, ec);
+    return AArch64AArch32SystemAccessTrap(miscReg, machInst, tc, imm, ec);
+}
+
 bool
-mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr,
-                    HCR hcr, uint32_t iss)
+mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, ThreadContext *tc,
+                    uint32_t iss, ExceptionClass *ec)
 {
     uint32_t    crm;
     IntRegIndex rt;
@@ -719,6 +748,11 @@ mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr,
     bool        isRead;
     bool        trapToHype = false;
 
+    const CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+    const HCR hcr = tc->readMiscReg(MISCREG_HCR);
+    const SCR scr = tc->readMiscReg(MISCREG_SCR);
+    const HSTR hstr = tc->readMiscReg(MISCREG_HSTR);
+
     if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
         // This is technically the wrong function, but we can re-use it for
         // the moment because we only need one field, which overlaps with the
@@ -746,6 +780,14 @@ mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr,
               case MISCREG_CONTEXTIDR:
                 trapToHype = hcr.tvm & !isRead;
                 break;
+              case MISCREG_CNTFRQ ... MISCREG_CNTV_TVAL:
+                // CNTFRQ may be trapped only on reads
+                // CNTPCT and CNTVCT are read-only
+                if (MISCREG_CNTFRQ <= miscReg && miscReg <= MISCREG_CNTVCT &&
+                    !isRead)
+                    break;
+                trapToHype = isGenericTimerHypTrap(miscReg, tc, ec);
+                break;
               // No default action needed
               default:
                 break;
@@ -755,6 +797,337 @@ mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr,
     return trapToHype;
 }
 
+Fault
+AArch64AArch32SystemAccessTrap(const MiscRegIndex miscReg,
+                               ExtMachInst machInst, ThreadContext *tc,
+                               uint32_t imm, ExceptionClass ec)
+{
+    if (currEL(tc) <= EL1 && !ELIs32(tc, EL1) &&
+        isAArch64AArch32SystemAccessTrapEL1(miscReg, tc))
+        return std::make_shared<SupervisorTrap>(machInst, imm, ec);
+    if (currEL(tc) <= EL2 && EL2Enabled(tc) && !ELIs32(tc, EL2) &&
+        isAArch64AArch32SystemAccessTrapEL2(miscReg, tc))
+        return std::make_shared<HypervisorTrap>(machInst, imm, ec);
+    return NoFault;
+}
+
+bool
+isAArch64AArch32SystemAccessTrapEL1(const MiscRegIndex miscReg,
+                                    ThreadContext *tc)
+{
+    switch (miscReg) {
+      case MISCREG_CNTFRQ ... MISCREG_CNTVOFF:
+        return currEL(tc) == EL0 &&
+               isGenericTimerSystemAccessTrapEL1(miscReg, tc);
+      default:
+        break;
+    }
+    return false;
+}
+
+bool
+isGenericTimerHypTrap(const MiscRegIndex miscReg, ThreadContext *tc,
+                      ExceptionClass *ec)
+{
+    if (currEL(tc) <= EL2 && EL2Enabled(tc) && ELIs32(tc, EL2)) {
+        switch (miscReg) {
+          case MISCREG_CNTFRQ ... MISCREG_CNTV_TVAL:
+            if (currEL(tc) == EL0 &&
+                isGenericTimerCommonEL0HypTrap(miscReg, tc, ec))
+                return true;
+            switch (miscReg) {
+              case MISCREG_CNTPCT:
+              case MISCREG_CNTP_CTL ... MISCREG_CNTP_TVAL_S:
+                return currEL(tc) <= EL1 &&
+                       isGenericTimerPhysHypTrap(miscReg, tc, ec);
+              default:
+                break;
+            }
+            break;
+          default:
+            break;
+        }
+    }
+    return false;
+}
+
+bool
+isGenericTimerCommonEL0HypTrap(const MiscRegIndex miscReg, ThreadContext *tc,
+                               ExceptionClass *ec)
+{
+    const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+    bool trap_cond = condGenericTimerSystemAccessTrapEL1(miscReg, tc);
+    if (ELIs32(tc, EL1) && trap_cond && hcr.tge) {
+        // As per the architecture, this hyp trap should have uncategorized
+        // exception class
+        if (ec)
+            *ec = EC_UNKNOWN;
+        return true;
+    }
+    return false;
+}
+
+bool
+isGenericTimerPhysHypTrap(const MiscRegIndex miscReg, ThreadContext *tc,
+                          ExceptionClass *ec)
+{
+    return condGenericTimerPhysHypTrap(miscReg, tc);
+}
+
+bool
+condGenericTimerPhysHypTrap(const MiscRegIndex miscReg, ThreadContext *tc)
+{
+    const CNTHCTL cnthctl = tc->readMiscReg(MISCREG_CNTHCTL_EL2);
+    switch (miscReg) {
+      case MISCREG_CNTPCT:
+        return !cnthctl.el1pcten;
+      case MISCREG_CNTP_CTL ... MISCREG_CNTP_TVAL_S:
+        return !cnthctl.el1pcen;
+      default:
+        break;
+    }
+    return false;
+}
+
+bool
+isGenericTimerSystemAccessTrapEL1(const MiscRegIndex miscReg,
+                                  ThreadContext *tc)
+{
+    switch (miscReg) {
+      case MISCREG_CNTFRQ ... MISCREG_CNTV_TVAL:
+      case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTV_TVAL_EL0:
+      {
+        const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+        bool trap_cond = condGenericTimerSystemAccessTrapEL1(miscReg, tc);
+        return !(EL2Enabled(tc) && hcr.e2h && hcr.tge) && trap_cond &&
+               !(EL2Enabled(tc) && !ELIs32(tc, EL2) && hcr.tge);
+      }
+      default:
+        break;
+    }
+    return false;
+}
+
+bool
+condGenericTimerSystemAccessTrapEL1(const MiscRegIndex miscReg,
+                                    ThreadContext *tc)
+{
+    const CNTKCTL cntkctl = tc->readMiscReg(MISCREG_CNTKCTL_EL1);
+    switch (miscReg) {
+      case MISCREG_CNTFRQ:
+      case MISCREG_CNTFRQ_EL0:
+        return !cntkctl.el0pcten && !cntkctl.el0vcten;
+      case MISCREG_CNTPCT:
+      case MISCREG_CNTPCT_EL0:
+        return !cntkctl.el0pcten;
+      case MISCREG_CNTVCT:
+      case MISCREG_CNTVCT_EL0:
+        return !cntkctl.el0vcten;
+      case MISCREG_CNTP_CTL ... MISCREG_CNTP_TVAL_S:
+      case MISCREG_CNTP_CTL_EL0 ... MISCREG_CNTP_TVAL_EL0:
+        return !cntkctl.el0pten;
+      case MISCREG_CNTV_CTL ... MISCREG_CNTV_TVAL:
+      case MISCREG_CNTV_CTL_EL0 ... MISCREG_CNTV_TVAL_EL0:
+        return !cntkctl.el0vten;
+      default:
+        break;
+    }
+    return false;
+}
+
+bool
+isAArch64AArch32SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                    ThreadContext *tc)
+{
+    switch (miscReg) {
+      case MISCREG_CNTFRQ ... MISCREG_CNTVOFF:
+        return currEL(tc) <= EL1 &&
+               isGenericTimerSystemAccessTrapEL2(miscReg, tc);
+      default:
+        break;
+    }
+    return false;
+}
+
+bool
+isGenericTimerSystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                  ThreadContext *tc)
+{
+    switch (miscReg) {
+      case MISCREG_CNTFRQ ... MISCREG_CNTV_TVAL:
+      case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTV_TVAL_EL0:
+        if (currEL(tc) == EL0 &&
+            isGenericTimerCommonEL0SystemAccessTrapEL2(miscReg, tc))
+            return true;
+        switch (miscReg) {
+          case MISCREG_CNTPCT:
+          case MISCREG_CNTPCT_EL0:
+          case MISCREG_CNTP_CTL ... MISCREG_CNTP_TVAL_S:
+          case MISCREG_CNTP_CTL_EL0 ... MISCREG_CNTP_TVAL_EL0:
+            return (currEL(tc) == EL0 &&
+                    isGenericTimerPhysEL0SystemAccessTrapEL2(miscReg, tc)) ||
+                   (currEL(tc) == EL1 &&
+                    isGenericTimerPhysEL1SystemAccessTrapEL2(miscReg, tc));
+          case MISCREG_CNTVCT:
+          case MISCREG_CNTVCT_EL0:
+          case MISCREG_CNTV_CTL ... MISCREG_CNTV_TVAL:
+          case MISCREG_CNTV_CTL_EL0 ... MISCREG_CNTV_TVAL_EL0:
+            return isGenericTimerVirtSystemAccessTrapEL2(miscReg, tc);
+          default:
+            break;
+        }
+        break;
+      default:
+        break;
+    }
+    return false;
+}
+
+bool
+isGenericTimerCommonEL0SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                           ThreadContext *tc)
+{
+    const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+    bool trap_cond_el1 = condGenericTimerSystemAccessTrapEL1(miscReg, tc);
+    bool trap_cond_el2 = condGenericTimerCommonEL0SystemAccessTrapEL2(miscReg,
+                                                                      tc);
+    return (!ELIs32(tc, EL1) && !hcr.e2h && trap_cond_el1 && hcr.tge) ||
+           (ELIs32(tc, EL1) && trap_cond_el1 && hcr.tge) ||
+           (hcr.e2h && hcr.tge && trap_cond_el2);
+}
+
+bool
+isGenericTimerPhysEL0SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                         ThreadContext *tc)
+{
+    const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+    bool trap_cond_0 = condGenericTimerPhysEL1SystemAccessTrapEL2(miscReg, tc);
+    bool trap_cond_1 = condGenericTimerCommonEL1SystemAccessTrapEL2(miscReg,
+                                                                    tc);
+    switch (miscReg) {
+      case MISCREG_CNTPCT:
+      case MISCREG_CNTPCT_EL0:
+        return !hcr.e2h && trap_cond_1;
+      case MISCREG_CNTP_CTL ... MISCREG_CNTP_TVAL_S:
+      case MISCREG_CNTP_CTL_EL0 ... MISCREG_CNTP_TVAL_EL0:
+        return (!hcr.e2h && trap_cond_0) ||
+               (hcr.e2h && !hcr.tge && trap_cond_1);
+      default:
+        break;
+    }
+
+    return false;
+}
+
+bool
+isGenericTimerPhysEL1SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                         ThreadContext *tc)
+{
+    const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+    bool trap_cond_0 = condGenericTimerPhysEL1SystemAccessTrapEL2(miscReg, tc);
+    bool trap_cond_1 = condGenericTimerCommonEL1SystemAccessTrapEL2(miscReg,
+                                                                    tc);
+    switch (miscReg) {
+      case MISCREG_CNTPCT:
+      case MISCREG_CNTPCT_EL0:
+        return trap_cond_1;
+      case MISCREG_CNTP_CTL ... MISCREG_CNTP_TVAL_S:
+      case MISCREG_CNTP_CTL_EL0 ... MISCREG_CNTP_TVAL_EL0:
+        return (!hcr.e2h && trap_cond_0) ||
+               (hcr.e2h && trap_cond_1);
+      default:
+        break;
+    }
+    return false;
+}
+
+bool
+isGenericTimerVirtSystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                      ThreadContext *tc)
+{
+    const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+    bool trap_cond = condGenericTimerCommonEL1SystemAccessTrapEL2(miscReg, tc);
+    return !ELIs32(tc, EL1) && !(hcr.e2h && hcr.tge) && trap_cond;
+}
+
+bool
+condGenericTimerCommonEL0SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                             ThreadContext *tc)
+{
+    const CNTHCTL_E2H cnthctl = tc->readMiscReg(MISCREG_CNTHCTL_EL2);
+    switch (miscReg) {
+      case MISCREG_CNTFRQ:
+      case MISCREG_CNTFRQ_EL0:
+        return !cnthctl.el0pcten && !cnthctl.el0vcten;
+      case MISCREG_CNTPCT:
+      case MISCREG_CNTPCT_EL0:
+        return !cnthctl.el0pcten;
+      case MISCREG_CNTVCT:
+      case MISCREG_CNTVCT_EL0:
+        return !cnthctl.el0vcten;
+      case MISCREG_CNTP_CTL ... MISCREG_CNTP_TVAL_S:
+      case MISCREG_CNTP_CTL_EL0 ... MISCREG_CNTP_TVAL_EL0:
+        return !cnthctl.el0pten;
+      case MISCREG_CNTV_CTL ... MISCREG_CNTV_TVAL:
+      case MISCREG_CNTV_CTL_EL0 ... MISCREG_CNTV_TVAL_EL0:
+        return !cnthctl.el0vten;
+      default:
+        break;
+    }
+    return false;
+}
+
+bool
+condGenericTimerCommonEL1SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                             ThreadContext *tc)
+{
+    const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
+    const RegVal cnthctl_val = tc->readMiscReg(MISCREG_CNTHCTL_EL2);
+    const CNTHCTL cnthctl = cnthctl_val;
+    const CNTHCTL_E2H cnthctl_e2h = cnthctl_val;
+    switch (miscReg) {
+      case MISCREG_CNTPCT:
+      case MISCREG_CNTPCT_EL0:
+        return hcr.e2h ? !cnthctl_e2h.el1pcten : !cnthctl.el1pcten;
+      case MISCREG_CNTVCT:
+      case MISCREG_CNTVCT_EL0:
+        return hcr.e2h ? cnthctl_e2h.el1tvct : cnthctl.el1tvct;
+      case MISCREG_CNTP_CTL ... MISCREG_CNTP_TVAL_S:
+      case MISCREG_CNTP_CTL_EL0 ... MISCREG_CNTP_TVAL_EL0:
+        return hcr.e2h ? !cnthctl_e2h.el1pten : false;
+      case MISCREG_CNTV_CTL ... MISCREG_CNTV_TVAL:
+      case MISCREG_CNTV_CTL_EL0 ... MISCREG_CNTV_TVAL_EL0:
+        return hcr.e2h ? cnthctl_e2h.el1tvt : cnthctl.el1tvt;
+      default:
+        break;
+    }
+    return false;
+}
+
+bool
+condGenericTimerPhysEL1SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                           ThreadContext *tc)
+{
+    const CNTHCTL cnthctl = tc->readMiscReg(MISCREG_CNTHCTL_EL2);
+    return !cnthctl.el1pcen;
+}
+
+bool
+isGenericTimerSystemAccessTrapEL3(const MiscRegIndex miscReg,
+                                  ThreadContext *tc)
+{
+    switch (miscReg) {
+      case MISCREG_CNTPS_CTL_EL1 ... MISCREG_CNTPS_TVAL_EL1:
+      {
+        const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
+        return currEL(tc) == EL1 && !scr.ns && !scr.st;
+      }
+      default:
+        break;
+    }
+    return false;
+}
+
 bool
 decodeMrsMsrBankedReg(uint8_t sysM, bool r, bool &isIntReg, int &regIdx,
                       CPSR cpsr, SCR scr, NSACR nsacr, bool checkSecurity)
index 4636d1768b20d4b4ee5e85870a9ec78914962c64..409ceed90d883aab402ee736a922b5705adc0e25 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012-2013, 2016-2019 ARM Limited
+ * Copyright (c) 2010, 2012-2013, 2016-2020 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -307,15 +307,80 @@ msrMrs64IssBuild(bool isRead, uint32_t op0, uint32_t op1, uint32_t crn,
         (op0 << 20);
 }
 
+Fault
+mcrMrc15Trap(const MiscRegIndex miscReg, ExtMachInst machInst,
+             ThreadContext *tc, uint32_t imm);
 bool
-mcrMrc15TrapToHyp(const MiscRegIndex miscReg, ThreadContext *tc, uint32_t iss);
+mcrMrc15TrapToHyp(const MiscRegIndex miscReg, ThreadContext *tc, uint32_t iss,
+                  ExceptionClass *ec = nullptr);
 
 bool
 mcrMrc14TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
                   HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss);
+
+Fault
+mcrrMrrc15Trap(const MiscRegIndex miscReg, ExtMachInst machInst,
+               ThreadContext *tc, uint32_t imm);
+bool
+mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, ThreadContext *tc,
+                    uint32_t iss, ExceptionClass *ec = nullptr);
+
+Fault
+AArch64AArch32SystemAccessTrap(const MiscRegIndex miscReg,
+                               ExtMachInst machInst, ThreadContext *tc,
+                               uint32_t imm, ExceptionClass ec);
+bool
+isAArch64AArch32SystemAccessTrapEL1(const MiscRegIndex miscReg,
+                                    ThreadContext *tc);
+bool
+isAArch64AArch32SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                    ThreadContext *tc);
+bool
+isGenericTimerHypTrap(const MiscRegIndex miscReg, ThreadContext *tc,
+                      ExceptionClass *ec);
+bool condGenericTimerPhysHypTrap(const MiscRegIndex miscReg,
+                                 ThreadContext *tc);
+bool
+isGenericTimerCommonEL0HypTrap(const MiscRegIndex miscReg, ThreadContext *tc,
+                               ExceptionClass *ec);
+bool
+isGenericTimerPhysHypTrap(const MiscRegIndex miscReg, ThreadContext *tc,
+                          ExceptionClass *ec);
+bool
+condGenericTimerPhysHypTrap(const MiscRegIndex miscReg, ThreadContext *tc);
+bool
+isGenericTimerSystemAccessTrapEL1(const MiscRegIndex miscReg,
+                                  ThreadContext *tc);
+bool
+condGenericTimerSystemAccessTrapEL1(const MiscRegIndex miscReg,
+                                    ThreadContext *tc);
+bool
+isGenericTimerSystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                  ThreadContext *tc);
+bool
+isGenericTimerCommonEL0SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                           ThreadContext *tc);
+bool
+isGenericTimerPhysEL0SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                         ThreadContext *tc);
+bool
+isGenericTimerPhysEL1SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                         ThreadContext *tc);
+bool
+isGenericTimerVirtSystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                      ThreadContext *tc);
+bool
+condGenericTimerCommonEL0SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                             ThreadContext *tc);
+bool
+condGenericTimerCommonEL1SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                             ThreadContext *tc);
+bool
+condGenericTimerPhysEL1SystemAccessTrapEL2(const MiscRegIndex miscReg,
+                                           ThreadContext *tc);
 bool
-mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr,
-                    HCR hcr, uint32_t iss);
+isGenericTimerSystemAccessTrapEL3(const MiscRegIndex miscReg,
+                                  ThreadContext *tc);
 
 bool SPAlignmentCheckEnabled(ThreadContext* tc);
 
index 98c9f2f36ff1e3cc9bac1be71d0d2ba257145d90..0c23b2aa759f5eb9d5a681b34c46abe1731f775c 100644 (file)
@@ -43,6 +43,9 @@
 namespace ArmISA
 {
     BitUnion64(CNTKCTL)
+        // IF Armv8.6-ECV
+        Bitfield<17> evntis;
+        // ENDIF Armv8.6-ECV
         Bitfield<9> el0pten;
         Bitfield<8> el0vten;
         Bitfield<7,4> evnti;
@@ -53,14 +56,30 @@ namespace ArmISA
     EndBitUnion(CNTKCTL)
 
     BitUnion64(CNTHCTL)
+        // IF Armv8.6-ECV
+        Bitfield<17> evntis;
+        Bitfield<16> el1nvvct;
+        Bitfield<15> el1nvpct;
+        Bitfield<14> el1tvct;
+        Bitfield<13> el1tvt;
+        Bitfield<12> ecv;
+        // ENDIF Armv8.6-ECV
         Bitfield<7,4> evnti;
         Bitfield<3> evntdir;
         Bitfield<2> evnten;
         Bitfield<1> el1pcen;
         Bitfield<0> el1pcten;
     EndBitUnion(CNTHCTL)
-    // If Armv8.1-VHE && HCR_EL2.E2H == 1
+    // IF Armv8.1-VHE && HCR_EL2.E2H == 1
     BitUnion64(CNTHCTL_E2H)
+        // IF Armv8.6-ECV
+        Bitfield<17> evntis;
+        Bitfield<16> el1nvvct;
+        Bitfield<15> el1nvpct;
+        Bitfield<14> el1tvct;
+        Bitfield<13> el1tvt;
+        Bitfield<12> ecv;
+        // ENDIF Armv8.6-ECV
         Bitfield<11> el1pten;
         Bitfield<10> el1pcten;
         Bitfield<9> el0pten;
@@ -71,6 +90,7 @@ namespace ArmISA
         Bitfield<1> el0vcten;
         Bitfield<0> el0pcten;
     EndBitUnion(CNTHCTL_E2H)
+    // ENDIF Armv8.1-VHE && HCR_EL2.E2H == 1
 }
 
 #endif // __DEV_ARM_GENERIC_TIMER_MISCREGS_TYPES_HH__