/*
- * 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
immediate = 0x1E00000;
}
break;
+ // Generic Timer
+ case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
+ trap_to_sup = el == EL0 &&
+ isGenericTimerSystemAccessTrapEL1(misc_reg, tc);
+ break;
default:
break;
}
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;
}
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;
}
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:
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:
// -*- 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
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);
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);
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;
'''
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;
'''
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);
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;
'''
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
}
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;
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;
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)
{
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:
.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();
.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();
.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);
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)
.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);
#include "arch/arm/miscregs_types.hh"
#include "base/compiler.hh"
+#include "dev/arm/generic_timer_miscregs_types.hh"
class ThreadContext;
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,
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,
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,
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,
// Introduced in ARMv8.1
MISCREG_TTBR1_EL2,
- MISCREG_CNTHV_CTL_EL2,
- MISCREG_CNTHV_CVAL_EL2,
- MISCREG_CNTHV_TVAL_EL2,
MISCREG_ID_AA64MMFR2_EL1,
"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",
"cbar",
"httbr",
"vttbr",
- "cntpct",
- "cntvct",
- "cntp_cval",
- "cntp_cval_ns",
- "cntp_cval_s",
- "cntv_cval",
- "cntvoff",
- "cnthp_cval",
"cpumerrsr",
"l2merrsr",
"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",
"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",
"contextidr_el2",
"ttbr1_el2",
- "cnthv_ctl_el2",
- "cnthv_cval_el2",
- "cnthv_tval_el2",
"id_aa64mmfr2_el1",
"apdakeyhi_el1",
* @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.
* @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,
/*
- * 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
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;
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;
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;
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
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;
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 ®Idx,
CPSR cpsr, SCR scr, NSACR nsacr, bool checkSecurity)
/*
- * 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
(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);
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;
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;
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__