arch-arm: GenericTimer arch regs, perms/trapping

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>
This commit is contained in:
Adrian Herrera
2019-11-07 12:59:27 +00:00
committed by Giacomo Travaglini
parent 81fc073768
commit 6e06d231ec
8 changed files with 829 additions and 194 deletions

View 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;
}

View 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:

View 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

View 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);
.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_CNTV_CTL)
.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);

View 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,

View 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)

View 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, CPSR cpsr, SCR scr, HSTR hstr,
HCR hcr, uint32_t iss);
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
isGenericTimerSystemAccessTrapEL3(const MiscRegIndex miscReg,
ThreadContext *tc);
bool SPAlignmentCheckEnabled(ThreadContext* tc);

View 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__