From: Adrian Herrera Date: Thu, 7 Nov 2019 12:59:27 +0000 (+0000) Subject: arch-arm: GenericTimer arch regs, perms/trapping X-Git-Tag: v20.0.0.0~402 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6e06d231ecf621d580449127f96fdb20154c4f66;p=gem5.git 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 Maintainer: Giacomo Travaglini Tested-by: kokoro --- diff --git a/src/arch/arm/insts/misc64.cc b/src/arch/arm/insts/misc64.cc index 0c4663664..7342527ad 100644 --- a/src/arch/arm/insts/misc64.cc +++ b/src/arch/arm/insts/misc64.cc @@ -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; } diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index 8bd811314..b2175cb49 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -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: diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa index f0394be32..0c6fdc31a 100644 --- a/src/arch/arm/isa/insts/misc.isa +++ b/src/arch/arm/isa/insts/misc.isa @@ -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(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(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(machInst, false, mnemonic); } - if (hypTrap) { - return std::make_shared(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(machInst, false, mnemonic); } - if (hypTrap) { - return std::make_shared(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(machInst, false, mnemonic); } - if (hypTrap) { - return std::make_shared(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(machInst, false, mnemonic); } - if (hypTrap) { - return std::make_shared(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 diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc index f8a9387f1..3c80de4bf 100644 --- a/src/arch/arm/miscregs.cc +++ b/src/arch/arm/miscregs.cc @@ -984,7 +984,7 @@ decodeCP15Reg64(unsigned crm, unsigned opc1) } std::tuple -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 -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); diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh index f4545777c..3900a4ccd 100644 --- a/src/arch/arm/miscregs.hh +++ b/src/arch/arm/miscregs.hh @@ -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 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 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, diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index e1dffafab..373508cee 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -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(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(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(machInst, imm, ec); + if (currEL(tc) <= EL2 && EL2Enabled(tc) && !ELIs32(tc, EL2) && + isAArch64AArch32SystemAccessTrapEL2(miscReg, tc)) + return std::make_shared(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) diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index 4636d1768..409ceed90 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -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); diff --git a/src/dev/arm/generic_timer_miscregs_types.hh b/src/dev/arm/generic_timer_miscregs_types.hh index 98c9f2f36..0c23b2aa7 100644 --- a/src/dev/arm/generic_timer_miscregs_types.hh +++ b/src/dev/arm/generic_timer_miscregs_types.hh @@ -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__