arch-arm: Implement ARM8.1-VHE feature
This commit implemented the VHE feature in ARMv8. This consist in 3
parts
1. Register decl/init and register redirection from el1 to el2
miscregs.cc/hh
miscregs_types.hh
isa.cc
utility.cc/hh
2. Definition of new EL2&0 translation regime.
tlb.cc/hh
table_walker.cc
pagetable.hh
tlbi_op.hh
isa.cc ( for tlb invalidation functions)
3. Self Debug adaptation for VHE
self_debug.cc
4. Effects on AMO/IMO/FMO interruptions
faults.cc
interrupts.hh
JIRA: https://gem5.atlassian.net/browse/GEM5-682
Change-Id: I478389322c295b1ec560571071626373a8c2af61
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31177
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -108,8 +108,8 @@ class ArmISA(BaseISA):
|
||||
# 4K | 64K | !16K | !BigEndEL0 | !SNSMem | !BigEnd | 8b ASID | 40b PA
|
||||
id_aa64mmfr0_el1 = Param.UInt64(0x0000000000f00002,
|
||||
"AArch64 Memory Model Feature Register 0")
|
||||
# PAN | HPDS
|
||||
id_aa64mmfr1_el1 = Param.UInt64(0x0000000000101000,
|
||||
# PAN | HPDS | VHE
|
||||
id_aa64mmfr1_el1 = Param.UInt64(0x0000000000101100,
|
||||
"AArch64 Memory Model Feature Register 1")
|
||||
id_aa64mmfr2_el1 = Param.UInt64(0x0000000000000000,
|
||||
"AArch64 Memory Model Feature Register 2")
|
||||
|
||||
@@ -179,202 +179,169 @@ MiscRegOp64::checkEL2Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
|
||||
uint32_t &immediate) const
|
||||
{
|
||||
const CPTR cptr = tc->readMiscReg(MISCREG_CPTR_EL2);
|
||||
const SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1);
|
||||
const SCTLR sctlr2 = tc->readMiscReg(MISCREG_SCTLR_EL2);
|
||||
const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
|
||||
const CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
|
||||
const HDCR mdcr = tc->readMiscReg(MISCREG_MDCR_EL3);
|
||||
|
||||
bool trap_to_hyp = false;
|
||||
|
||||
if (!inSecureState(scr, cpsr) && (el != EL2)) {
|
||||
switch (misc_reg) {
|
||||
// FP/SIMD regs
|
||||
case MISCREG_FPCR:
|
||||
case MISCREG_FPSR:
|
||||
case MISCREG_FPEXC32_EL2:
|
||||
trap_to_hyp = cptr.tfp;
|
||||
ec = EC_TRAPPED_SIMD_FP;
|
||||
immediate = 0x1E00000;
|
||||
break;
|
||||
// CPACR
|
||||
case MISCREG_CPACR_EL1:
|
||||
trap_to_hyp = cptr.tcpac && el == EL1;
|
||||
break;
|
||||
// Virtual memory control regs
|
||||
case MISCREG_SCTLR_EL1:
|
||||
case MISCREG_TTBR0_EL1:
|
||||
case MISCREG_TTBR1_EL1:
|
||||
case MISCREG_TCR_EL1:
|
||||
case MISCREG_ESR_EL1:
|
||||
case MISCREG_FAR_EL1:
|
||||
case MISCREG_AFSR0_EL1:
|
||||
case MISCREG_AFSR1_EL1:
|
||||
case MISCREG_MAIR_EL1:
|
||||
case MISCREG_AMAIR_EL1:
|
||||
case MISCREG_CONTEXTIDR_EL1:
|
||||
trap_to_hyp =
|
||||
((hcr.trvm && miscRead) || (hcr.tvm && !miscRead)) &&
|
||||
el == EL1;
|
||||
break;
|
||||
// TLB maintenance instructions
|
||||
case MISCREG_TLBI_VMALLE1:
|
||||
case MISCREG_TLBI_VAE1_Xt:
|
||||
case MISCREG_TLBI_ASIDE1_Xt:
|
||||
case MISCREG_TLBI_VAAE1_Xt:
|
||||
case MISCREG_TLBI_VALE1_Xt:
|
||||
case MISCREG_TLBI_VAALE1_Xt:
|
||||
case MISCREG_TLBI_VMALLE1IS:
|
||||
case MISCREG_TLBI_VAE1IS_Xt:
|
||||
case MISCREG_TLBI_ASIDE1IS_Xt:
|
||||
case MISCREG_TLBI_VAAE1IS_Xt:
|
||||
case MISCREG_TLBI_VALE1IS_Xt:
|
||||
case MISCREG_TLBI_VAALE1IS_Xt:
|
||||
trap_to_hyp = hcr.ttlb && el == EL1;
|
||||
break;
|
||||
// Cache maintenance instructions to the point of unification
|
||||
case MISCREG_IC_IVAU_Xt:
|
||||
case MISCREG_ICIALLU:
|
||||
case MISCREG_ICIALLUIS:
|
||||
case MISCREG_DC_CVAU_Xt:
|
||||
trap_to_hyp = hcr.tpu && el <= EL1;
|
||||
break;
|
||||
// Data/Unified cache maintenance instructions to the
|
||||
// point of coherency
|
||||
case MISCREG_DC_IVAC_Xt:
|
||||
case MISCREG_DC_CIVAC_Xt:
|
||||
case MISCREG_DC_CVAC_Xt:
|
||||
trap_to_hyp = hcr.tpc && el <= EL1;
|
||||
break;
|
||||
// Data/Unified cache maintenance instructions by set/way
|
||||
case MISCREG_DC_ISW_Xt:
|
||||
case MISCREG_DC_CSW_Xt:
|
||||
case MISCREG_DC_CISW_Xt:
|
||||
trap_to_hyp = hcr.tsw && el == EL1;
|
||||
break;
|
||||
// ACTLR
|
||||
case MISCREG_ACTLR_EL1:
|
||||
trap_to_hyp = hcr.tacr && el == EL1;
|
||||
break;
|
||||
|
||||
case MISCREG_APDAKeyHi_EL1:
|
||||
case MISCREG_APDAKeyLo_EL1:
|
||||
case MISCREG_APDBKeyHi_EL1:
|
||||
case MISCREG_APDBKeyLo_EL1:
|
||||
case MISCREG_APGAKeyHi_EL1:
|
||||
case MISCREG_APGAKeyLo_EL1:
|
||||
case MISCREG_APIAKeyHi_EL1:
|
||||
case MISCREG_APIAKeyLo_EL1:
|
||||
case MISCREG_APIBKeyHi_EL1:
|
||||
case MISCREG_APIBKeyLo_EL1:
|
||||
trap_to_hyp = el==EL1 && hcr.apk == 0;
|
||||
break;
|
||||
// @todo: Trap implementation-dependent functionality based on
|
||||
// hcr.tidcp
|
||||
|
||||
// ID regs, group 3
|
||||
case MISCREG_ID_PFR0_EL1:
|
||||
case MISCREG_ID_PFR1_EL1:
|
||||
case MISCREG_ID_DFR0_EL1:
|
||||
case MISCREG_ID_AFR0_EL1:
|
||||
case MISCREG_ID_MMFR0_EL1:
|
||||
case MISCREG_ID_MMFR1_EL1:
|
||||
case MISCREG_ID_MMFR2_EL1:
|
||||
case MISCREG_ID_MMFR3_EL1:
|
||||
case MISCREG_ID_ISAR0_EL1:
|
||||
case MISCREG_ID_ISAR1_EL1:
|
||||
case MISCREG_ID_ISAR2_EL1:
|
||||
case MISCREG_ID_ISAR3_EL1:
|
||||
case MISCREG_ID_ISAR4_EL1:
|
||||
case MISCREG_ID_ISAR5_EL1:
|
||||
case MISCREG_MVFR0_EL1:
|
||||
case MISCREG_MVFR1_EL1:
|
||||
case MISCREG_MVFR2_EL1:
|
||||
case MISCREG_ID_AA64PFR0_EL1:
|
||||
case MISCREG_ID_AA64PFR1_EL1:
|
||||
case MISCREG_ID_AA64DFR0_EL1:
|
||||
case MISCREG_ID_AA64DFR1_EL1:
|
||||
case MISCREG_ID_AA64ISAR0_EL1:
|
||||
case MISCREG_ID_AA64ISAR1_EL1:
|
||||
case MISCREG_ID_AA64MMFR0_EL1:
|
||||
case MISCREG_ID_AA64MMFR1_EL1:
|
||||
case MISCREG_ID_AA64MMFR2_EL1:
|
||||
case MISCREG_ID_AA64AFR0_EL1:
|
||||
case MISCREG_ID_AA64AFR1_EL1:
|
||||
assert(miscRead);
|
||||
trap_to_hyp = hcr.tid3 && el == EL1;
|
||||
break;
|
||||
// ID regs, group 2
|
||||
case MISCREG_CTR_EL0:
|
||||
case MISCREG_CCSIDR_EL1:
|
||||
case MISCREG_CLIDR_EL1:
|
||||
case MISCREG_CSSELR_EL1:
|
||||
trap_to_hyp = hcr.tid2 && el <= EL1;
|
||||
break;
|
||||
// ID regs, group 1
|
||||
case MISCREG_AIDR_EL1:
|
||||
case MISCREG_REVIDR_EL1:
|
||||
assert(miscRead);
|
||||
trap_to_hyp = hcr.tid1 && el == EL1;
|
||||
break;
|
||||
case MISCREG_IMPDEF_UNIMPL:
|
||||
trap_to_hyp = hcr.tidcp && el == EL1;
|
||||
break;
|
||||
// GICv3 regs
|
||||
case MISCREG_ICC_SGI0R_EL1:
|
||||
{
|
||||
auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
|
||||
if (isa->haveGICv3CpuIfc())
|
||||
trap_to_hyp = hcr.fmo && el == EL1;
|
||||
}
|
||||
break;
|
||||
case MISCREG_ICC_SGI1R_EL1:
|
||||
case MISCREG_ICC_ASGI1R_EL1:
|
||||
{
|
||||
auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
|
||||
if (isa->haveGICv3CpuIfc())
|
||||
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;
|
||||
}
|
||||
}
|
||||
return trap_to_hyp;
|
||||
}
|
||||
|
||||
bool
|
||||
MiscRegOp64::checkEL3Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
|
||||
ExceptionLevel el, ExceptionClass &ec,
|
||||
uint32_t &immediate) const
|
||||
{
|
||||
const CPTR cptr = tc->readMiscReg(MISCREG_CPTR_EL3);
|
||||
const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
|
||||
bool trap_to_mon = false;
|
||||
|
||||
switch (misc_reg) {
|
||||
// FP/SIMD regs
|
||||
case MISCREG_IMPDEF_UNIMPL:
|
||||
trap_to_hyp = EL2Enabled(tc) && hcr.tidcp && el == EL1;
|
||||
break;
|
||||
// GICv3 regs
|
||||
case MISCREG_ICC_SGI0R_EL1:
|
||||
{
|
||||
auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
|
||||
if (isa->haveGICv3CpuIfc())
|
||||
trap_to_hyp = EL2Enabled(tc) && hcr.fmo && el == EL1;
|
||||
}
|
||||
break;
|
||||
case MISCREG_ICC_SGI1R_EL1:
|
||||
case MISCREG_ICC_ASGI1R_EL1:
|
||||
{
|
||||
auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
|
||||
if (isa->haveGICv3CpuIfc())
|
||||
trap_to_hyp = EL2Enabled(tc) && hcr.imo && el == EL1;
|
||||
}
|
||||
break;
|
||||
case MISCREG_FPCR:
|
||||
case MISCREG_FPSR:
|
||||
case MISCREG_FPEXC32_EL2:
|
||||
trap_to_mon = cptr.tfp;
|
||||
ec = EC_TRAPPED_SIMD_FP;
|
||||
immediate = 0x1E00000;
|
||||
{
|
||||
bool from_el2 = (el == EL2) && (scr.ns || scr.eel2) &&
|
||||
ELIs64(tc,EL2) &&
|
||||
((!hcr.e2h && cptr.tfp) ||
|
||||
(hcr.e2h && (cptr.fpen == 0x0 ||
|
||||
cptr.fpen == 0xa)));
|
||||
bool from_el1 = (el == EL1) && hcr.nv &&
|
||||
(!hcr.e2h || (hcr.e2h && !hcr.tge));
|
||||
trap_to_hyp = from_el2 || from_el1;
|
||||
ec = EC_TRAPPED_SIMD_FP;
|
||||
immediate = 0x1E00000;
|
||||
}
|
||||
break;
|
||||
// CPACR, CPTR
|
||||
case MISCREG_CPACR_EL1:
|
||||
if (el == EL1 || el == EL2) {
|
||||
trap_to_mon = cptr.tcpac;
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && cptr.tcpac;
|
||||
break;
|
||||
case MISCREG_SCTLR_EL1:
|
||||
case MISCREG_TTBR0_EL1:
|
||||
case MISCREG_TTBR1_EL1:
|
||||
case MISCREG_TCR_EL1:
|
||||
case MISCREG_ESR_EL1:
|
||||
case MISCREG_FAR_EL1:
|
||||
case MISCREG_AFSR0_EL1:
|
||||
case MISCREG_AFSR1_EL1:
|
||||
case MISCREG_MAIR_EL1:
|
||||
case MISCREG_AMAIR_EL1:
|
||||
case MISCREG_CONTEXTIDR_EL1:
|
||||
{
|
||||
bool tvm = miscRead? hcr.trvm: hcr.tvm;
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && tvm;
|
||||
}
|
||||
break;
|
||||
case MISCREG_CPTR_EL2:
|
||||
if (el == EL2) {
|
||||
trap_to_mon = cptr.tcpac;
|
||||
case MISCREG_CPACR_EL12:
|
||||
case MISCREG_SCTLR_EL12:
|
||||
case MISCREG_TTBR0_EL12:
|
||||
case MISCREG_TTBR1_EL12:
|
||||
case MISCREG_TCR_EL12:
|
||||
case MISCREG_ESR_EL12:
|
||||
case MISCREG_FAR_EL12:
|
||||
case MISCREG_AFSR0_EL12:
|
||||
case MISCREG_AFSR1_EL12:
|
||||
case MISCREG_MAIR_EL12:
|
||||
case MISCREG_AMAIR_EL12:
|
||||
case MISCREG_CONTEXTIDR_EL12:
|
||||
case MISCREG_SPSR_EL12:
|
||||
case MISCREG_ELR_EL12:
|
||||
case MISCREG_VBAR_EL12:
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) &&
|
||||
(hcr.nv && (hcr.nv1 || !hcr.nv2));
|
||||
break;
|
||||
case MISCREG_TLBI_VMALLE1:
|
||||
case MISCREG_TLBI_VAE1_Xt:
|
||||
case MISCREG_TLBI_ASIDE1_Xt:
|
||||
case MISCREG_TLBI_VAAE1_Xt:
|
||||
case MISCREG_TLBI_VALE1_Xt:
|
||||
case MISCREG_TLBI_VAALE1_Xt:
|
||||
// case MISCREG_TLBI_RVAE1:
|
||||
// case MISCREG_TLBI_RVAAE1:
|
||||
// case MISCREG_TLBI_RVALE1:
|
||||
// case MISCREG_TLBI_RVAALE1:
|
||||
case MISCREG_TLBI_VMALLE1IS:
|
||||
case MISCREG_TLBI_VAE1IS_Xt:
|
||||
case MISCREG_TLBI_ASIDE1IS_Xt:
|
||||
case MISCREG_TLBI_VAAE1IS_Xt:
|
||||
case MISCREG_TLBI_VALE1IS_Xt:
|
||||
case MISCREG_TLBI_VAALE1IS_Xt:
|
||||
// case MISCREG_TLBI_RVAE1IS:
|
||||
// case MISCREG_TLBI_RVAAE1IS:
|
||||
// case MISCREG_TLBI_RVALE1IS:
|
||||
// case MISCREG_TLBI_RVAALE1IS:
|
||||
// case MISCREG_TLBI_VMALLE1OS:
|
||||
// case MISCREG_TLBI_VAE1OS:
|
||||
// case MISCREG_TLBI_ASIDE1OS:
|
||||
// case MISCREG_TLBI_VAAE1OS:
|
||||
// case MISCREG_TLBI_VALE1OS:
|
||||
// case MISCREG_TLBI_VAALE1OS:
|
||||
// case MISCREG_TLBI_RVAE1OS:
|
||||
// case MISCREG_TLBI_RVAAE1OS:
|
||||
// case MISCREG_TLBI_RVALE1OS:
|
||||
// case MISCREG_TLBI_RVAALE1OS:
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && hcr.ttlb;
|
||||
break;
|
||||
case MISCREG_IC_IVAU_Xt:
|
||||
case MISCREG_ICIALLU:
|
||||
case MISCREG_ICIALLUIS:
|
||||
trap_to_hyp = (el == EL1) && EL2Enabled(tc) && hcr.tpu;
|
||||
break;
|
||||
case MISCREG_DC_CVAU_Xt:
|
||||
{
|
||||
const bool el2_en = EL2Enabled(tc);
|
||||
if (el == EL0 && el2_en) {
|
||||
const bool in_host = hcr.e2h && hcr.tge;
|
||||
const bool general_trap = el2_en && !in_host && hcr.tge &&
|
||||
!sctlr.uci;
|
||||
const bool tpu_trap = el2_en && !in_host && hcr.tpu;
|
||||
const bool host_trap = el2_en && in_host && !sctlr2.uci;
|
||||
trap_to_hyp = general_trap || tpu_trap || host_trap;
|
||||
}
|
||||
else if (el == EL1 && el2_en) {
|
||||
trap_to_hyp = hcr.tpu;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MISCREG_DC_IVAC_Xt:
|
||||
trap_to_hyp = EL2Enabled(tc) && el == EL1 && hcr.tpc;
|
||||
break;
|
||||
case MISCREG_DC_CVAC_Xt:
|
||||
// case MISCREG_DC_CVAP_Xt:
|
||||
case MISCREG_DC_CIVAC_Xt:
|
||||
{
|
||||
const bool el2_en = EL2Enabled(tc);
|
||||
if (el == EL0 && el2_en) {
|
||||
|
||||
const bool in_host = hcr.e2h && hcr.tge;
|
||||
const bool general_trap = el2_en && !in_host && hcr.tge &&
|
||||
!sctlr.uci;
|
||||
const bool tpc_trap = el2_en && !in_host && hcr.tpc;
|
||||
const bool host_trap = el2_en && in_host && !sctlr2.uci;
|
||||
trap_to_hyp = general_trap || tpc_trap || host_trap;
|
||||
} else if (el == EL1 && el2_en) {
|
||||
trap_to_hyp = hcr.tpc;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MISCREG_DC_ISW_Xt:
|
||||
case MISCREG_DC_CSW_Xt:
|
||||
case MISCREG_DC_CISW_Xt:
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && hcr.tsw;
|
||||
break;
|
||||
case MISCREG_ACTLR_EL1:
|
||||
trap_to_hyp = EL2Enabled (tc) && (el == EL1) && hcr.tacr;
|
||||
break;
|
||||
case MISCREG_APDAKeyHi_EL1:
|
||||
case MISCREG_APDAKeyLo_EL1:
|
||||
case MISCREG_APDBKeyHi_EL1:
|
||||
@@ -385,13 +352,439 @@ MiscRegOp64::checkEL3Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
|
||||
case MISCREG_APIAKeyLo_EL1:
|
||||
case MISCREG_APIBKeyHi_EL1:
|
||||
case MISCREG_APIBKeyLo_EL1:
|
||||
trap_to_mon = (el==EL1 || el==EL2) && scr.apk==0 && ELIs64(tc, EL3);
|
||||
trap_to_hyp = EL2Enabled(tc) && el == EL1 && !hcr.apk;
|
||||
break;
|
||||
case MISCREG_ID_PFR0_EL1:
|
||||
case MISCREG_ID_PFR1_EL1:
|
||||
//case MISCREG_ID_PFR2_EL1:
|
||||
case MISCREG_ID_DFR0_EL1:
|
||||
case MISCREG_ID_AFR0_EL1:
|
||||
case MISCREG_ID_MMFR0_EL1:
|
||||
case MISCREG_ID_MMFR1_EL1:
|
||||
case MISCREG_ID_MMFR2_EL1:
|
||||
case MISCREG_ID_MMFR3_EL1:
|
||||
//case MISCREG_ID_MMFR4_EL1:
|
||||
case MISCREG_ID_ISAR0_EL1:
|
||||
case MISCREG_ID_ISAR1_EL1:
|
||||
case MISCREG_ID_ISAR2_EL1:
|
||||
case MISCREG_ID_ISAR3_EL1:
|
||||
case MISCREG_ID_ISAR4_EL1:
|
||||
case MISCREG_ID_ISAR5_EL1:
|
||||
case MISCREG_MVFR0_EL1:
|
||||
case MISCREG_MVFR1_EL1:
|
||||
case MISCREG_MVFR2_EL1:
|
||||
case MISCREG_ID_AA64PFR0_EL1:
|
||||
case MISCREG_ID_AA64PFR1_EL1:
|
||||
case MISCREG_ID_AA64DFR0_EL1:
|
||||
case MISCREG_ID_AA64DFR1_EL1:
|
||||
case MISCREG_ID_AA64ISAR0_EL1:
|
||||
case MISCREG_ID_AA64ISAR1_EL1:
|
||||
case MISCREG_ID_AA64MMFR0_EL1:
|
||||
case MISCREG_ID_AA64MMFR1_EL1:
|
||||
case MISCREG_ID_AA64MMFR2_EL1:
|
||||
case MISCREG_ID_AA64AFR0_EL1:
|
||||
case MISCREG_ID_AA64AFR1_EL1:
|
||||
trap_to_hyp = EL2Enabled(tc) && el == EL1 && hcr.tid3;
|
||||
break;
|
||||
case MISCREG_CTR_EL0:
|
||||
{
|
||||
const bool el2_en = EL2Enabled(tc);
|
||||
if (el == EL0 && el2_en) {
|
||||
const bool in_host = hcr.e2h && hcr.tge;
|
||||
const bool general_trap = el2_en && !in_host && hcr.tge &&
|
||||
!sctlr.uct;
|
||||
const bool tid_trap = el2_en && !in_host && hcr.tid2;
|
||||
const bool host_trap = el2_en && in_host && !sctlr2.uct;
|
||||
trap_to_hyp = general_trap || tid_trap || host_trap;
|
||||
} else if (el == EL1 && el2_en) {
|
||||
trap_to_hyp = hcr.tid2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MISCREG_CCSIDR_EL1:
|
||||
// case MISCREG_CCSIDR2_EL1:
|
||||
case MISCREG_CLIDR_EL1:
|
||||
case MISCREG_CSSELR_EL1:
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && hcr.tid2;
|
||||
break;
|
||||
case MISCREG_AIDR_EL1:
|
||||
case MISCREG_REVIDR_EL1:
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && hcr.tid1;
|
||||
break;
|
||||
// Generic Timer
|
||||
case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
|
||||
trap_to_hyp = el <= EL1 &&
|
||||
isGenericTimerSystemAccessTrapEL2(misc_reg, tc);
|
||||
break;
|
||||
case MISCREG_DAIF:
|
||||
trap_to_hyp = EL2Enabled(tc) && el == EL0 &&
|
||||
(hcr.tge && (hcr.e2h || !sctlr.uma));
|
||||
break;
|
||||
case MISCREG_SPSR_EL1:
|
||||
case MISCREG_ELR_EL1:
|
||||
case MISCREG_VBAR_EL1:
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && hcr.nv1 && !hcr.nv2;
|
||||
break;
|
||||
case MISCREG_HCR_EL2:
|
||||
case MISCREG_HSTR_EL2:
|
||||
case MISCREG_SP_EL1:
|
||||
case MISCREG_TPIDR_EL2:
|
||||
case MISCREG_VTCR_EL2:
|
||||
case MISCREG_VTTBR_EL2:
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && hcr.nv && !hcr.nv2;
|
||||
break;
|
||||
// case MISCREG_AT_S1E1WP_Xt:
|
||||
// case MISCREG_AT_S1E1RP_Xt:
|
||||
case MISCREG_AT_S1E1R_Xt:
|
||||
case MISCREG_AT_S1E1W_Xt:
|
||||
case MISCREG_AT_S1E0W_Xt:
|
||||
case MISCREG_AT_S1E0R_Xt:
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && hcr.at;
|
||||
break;
|
||||
case MISCREG_ACTLR_EL2:
|
||||
case MISCREG_AFSR0_EL2:
|
||||
case MISCREG_AFSR1_EL2:
|
||||
case MISCREG_AMAIR_EL2:
|
||||
case MISCREG_CONTEXTIDR_EL2:
|
||||
case MISCREG_CPTR_EL2:
|
||||
case MISCREG_DACR32_EL2:
|
||||
case MISCREG_ESR_EL2:
|
||||
case MISCREG_FAR_EL2:
|
||||
case MISCREG_HACR_EL2:
|
||||
case MISCREG_HPFAR_EL2:
|
||||
case MISCREG_MAIR_EL2:
|
||||
// case MISCREG_RMR_EL2:
|
||||
case MISCREG_SCTLR_EL2:
|
||||
case MISCREG_TCR_EL2:
|
||||
case MISCREG_TTBR0_EL2:
|
||||
case MISCREG_TTBR1_EL2:
|
||||
case MISCREG_VBAR_EL2:
|
||||
case MISCREG_VMPIDR_EL2:
|
||||
case MISCREG_VPIDR_EL2:
|
||||
case MISCREG_TLBI_ALLE1:
|
||||
case MISCREG_TLBI_ALLE1IS:
|
||||
// case MISCREG_TLBI_ALLE1OS:
|
||||
case MISCREG_TLBI_ALLE2:
|
||||
case MISCREG_TLBI_ALLE2IS:
|
||||
// case MISCREG_TLBI_ALLE2OS:
|
||||
case MISCREG_TLBI_IPAS2E1_Xt:
|
||||
case MISCREG_TLBI_IPAS2E1IS_Xt:
|
||||
// case MISCREG_TLBI_IPAS2E1OS:
|
||||
case MISCREG_TLBI_IPAS2LE1_Xt:
|
||||
case MISCREG_TLBI_IPAS2LE1IS_Xt:
|
||||
// case MISCREG_TLBI_IPAS2LE1OS:
|
||||
// case MISCREG_TLBI_RIPAS2E1:
|
||||
// case MISCREG_TLBI_RIPAS2E1IS:
|
||||
// case MISCREG_TLBI_RIPAS2E1OS:
|
||||
// case MISCREG_TLBI_RIPAS2LE1:
|
||||
// case MISCREG_TLBI_RIPAS2LE1IS:
|
||||
// case MISCREG_TLBI_RIPAS2LE1OS:
|
||||
// case MISCREG_TLBI_RVAE2:
|
||||
// case MISCREG_TLBI_RVAE2IS:
|
||||
// case MISCREG_TLBI_RVAE2OS:
|
||||
// case MISCREG_TLBI_RVALE2:
|
||||
// case MISCREG_TLBI_RVALE2IS:
|
||||
// case MISCREG_TLBI_RVALE2OS:
|
||||
case MISCREG_TLBI_VAE2_Xt:
|
||||
case MISCREG_TLBI_VAE2IS_Xt:
|
||||
// case MISCREG_TLBI_VAE2OS:
|
||||
case MISCREG_TLBI_VALE2_Xt:
|
||||
case MISCREG_TLBI_VALE2IS_Xt:
|
||||
// case MISCREG_TLBI_VALE2OS:
|
||||
case MISCREG_TLBI_VMALLS12E1:
|
||||
case MISCREG_TLBI_VMALLS12E1IS:
|
||||
// case MISCREG_TLBI_VMALLS12E1OS:
|
||||
case MISCREG_AT_S1E2W_Xt:
|
||||
case MISCREG_AT_S1E2R_Xt:
|
||||
case MISCREG_AT_S12E1R_Xt:
|
||||
case MISCREG_AT_S12E1W_Xt:
|
||||
case MISCREG_AT_S12E0W_Xt:
|
||||
case MISCREG_AT_S12E0R_Xt:
|
||||
case MISCREG_SPSR_UND:
|
||||
case MISCREG_SPSR_IRQ:
|
||||
case MISCREG_SPSR_FIQ:
|
||||
case MISCREG_SPSR_ABT:
|
||||
case MISCREG_SPSR_EL2:
|
||||
case MISCREG_ELR_EL2:
|
||||
case MISCREG_IFSR32_EL2:
|
||||
case MISCREG_DBGVCR32_EL2:
|
||||
case MISCREG_MDCR_EL2:
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && hcr.nv;
|
||||
break;
|
||||
// case MISCREG_VSTTBR_EL2:
|
||||
// case MISCREG_VSTCR_EL2:
|
||||
// trap_to_hyp = (el == EL1) && !scr.ns && scr.eel2 && ELIs64(tc,EL2)
|
||||
// && !hcr.nv2 && hcr.nv && (!hcr.e2h|| (hcr.e2h && !hcr.tge));
|
||||
// break;
|
||||
|
||||
//case MISCREG_LORC_EL1:
|
||||
//case MISCREG_LOREA_EL1:
|
||||
//case MISCREG_LORID_EL1:
|
||||
//case MISCREG_LORN_EL1:
|
||||
//case MISCREG_LORSA_EL1:
|
||||
// trap_to_hyp = (el == EL1) && (scr.ns || scr.eel2) && ELIs64(tc,EL2)
|
||||
// && hcr.tlor && (!hcr.e2h || (hcr.e2h && !hcr.tge));
|
||||
// break;
|
||||
|
||||
case MISCREG_DC_ZVA_Xt:
|
||||
{
|
||||
const bool el2_en = EL2Enabled(tc);
|
||||
if (el == EL0 && el2_en) {
|
||||
const bool in_host = hcr.e2h && hcr.tge;
|
||||
const bool general_trap = el2_en && !in_host && hcr.tge &&
|
||||
!sctlr.dze;
|
||||
const bool tdz_trap = el2_en && !in_host && hcr.tdz;
|
||||
const bool host_trap = el2_en && in_host && !sctlr2.dze;
|
||||
trap_to_hyp = general_trap || tdz_trap || host_trap;
|
||||
} else if (el == EL1 && el2_en) {
|
||||
trap_to_hyp = hcr.tdz;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MISCREG_DBGBVR0_EL1:
|
||||
case MISCREG_DBGBVR1_EL1:
|
||||
case MISCREG_DBGBVR2_EL1:
|
||||
case MISCREG_DBGBVR3_EL1:
|
||||
case MISCREG_DBGBVR4_EL1:
|
||||
case MISCREG_DBGBVR5_EL1:
|
||||
case MISCREG_DBGBVR6_EL1:
|
||||
case MISCREG_DBGBVR7_EL1:
|
||||
case MISCREG_DBGBVR8_EL1:
|
||||
case MISCREG_DBGBVR9_EL1:
|
||||
case MISCREG_DBGBVR10_EL1:
|
||||
case MISCREG_DBGBVR11_EL1:
|
||||
case MISCREG_DBGBVR12_EL1:
|
||||
case MISCREG_DBGBVR13_EL1:
|
||||
case MISCREG_DBGBVR14_EL1:
|
||||
case MISCREG_DBGBVR15_EL1:
|
||||
case MISCREG_DBGBCR0_EL1:
|
||||
case MISCREG_DBGBCR1_EL1:
|
||||
case MISCREG_DBGBCR2_EL1:
|
||||
case MISCREG_DBGBCR3_EL1:
|
||||
case MISCREG_DBGBCR4_EL1:
|
||||
case MISCREG_DBGBCR5_EL1:
|
||||
case MISCREG_DBGBCR6_EL1:
|
||||
case MISCREG_DBGBCR7_EL1:
|
||||
case MISCREG_DBGBCR8_EL1:
|
||||
case MISCREG_DBGBCR9_EL1:
|
||||
case MISCREG_DBGBCR10_EL1:
|
||||
case MISCREG_DBGBCR11_EL1:
|
||||
case MISCREG_DBGBCR12_EL1:
|
||||
case MISCREG_DBGBCR13_EL1:
|
||||
case MISCREG_DBGBCR14_EL1:
|
||||
case MISCREG_DBGBCR15_EL1:
|
||||
case MISCREG_DBGWVR0_EL1:
|
||||
case MISCREG_DBGWVR1_EL1:
|
||||
case MISCREG_DBGWVR2_EL1:
|
||||
case MISCREG_DBGWVR3_EL1:
|
||||
case MISCREG_DBGWVR4_EL1:
|
||||
case MISCREG_DBGWVR5_EL1:
|
||||
case MISCREG_DBGWVR6_EL1:
|
||||
case MISCREG_DBGWVR7_EL1:
|
||||
case MISCREG_DBGWVR8_EL1:
|
||||
case MISCREG_DBGWVR9_EL1:
|
||||
case MISCREG_DBGWVR10_EL1:
|
||||
case MISCREG_DBGWVR11_EL1:
|
||||
case MISCREG_DBGWVR12_EL1:
|
||||
case MISCREG_DBGWVR13_EL1:
|
||||
case MISCREG_DBGWVR14_EL1:
|
||||
case MISCREG_DBGWVR15_EL1:
|
||||
case MISCREG_DBGWCR0_EL1:
|
||||
case MISCREG_DBGWCR1_EL1:
|
||||
case MISCREG_DBGWCR2_EL1:
|
||||
case MISCREG_DBGWCR3_EL1:
|
||||
case MISCREG_DBGWCR4_EL1:
|
||||
case MISCREG_DBGWCR5_EL1:
|
||||
case MISCREG_DBGWCR6_EL1:
|
||||
case MISCREG_DBGWCR7_EL1:
|
||||
case MISCREG_DBGWCR8_EL1:
|
||||
case MISCREG_DBGWCR9_EL1:
|
||||
case MISCREG_DBGWCR10_EL1:
|
||||
case MISCREG_DBGWCR11_EL1:
|
||||
case MISCREG_DBGWCR12_EL1:
|
||||
case MISCREG_DBGWCR13_EL1:
|
||||
case MISCREG_DBGWCR14_EL1:
|
||||
case MISCREG_DBGWCR15_EL1:
|
||||
case MISCREG_MDCCINT_EL1:
|
||||
trap_to_hyp = EL2Enabled(tc) && (el == EL1) && mdcr.tda;
|
||||
break;
|
||||
case MISCREG_ZCR_EL1:
|
||||
{
|
||||
bool from_el1 = (el == EL1) && EL2Enabled(tc) &&
|
||||
ELIs64(tc, EL2) && ((!hcr.e2h && cptr.tz) ||
|
||||
(hcr.e2h && ((cptr.zen & 0x1) == 0x0)));
|
||||
bool from_el2 = (el == EL2) && ((!hcr.e2h && cptr.tz) ||
|
||||
(hcr.e2h && ((cptr.zen & 0x1) == 0x0)));
|
||||
trap_to_hyp = from_el1 || from_el2;
|
||||
}
|
||||
ec = EC_TRAPPED_SVE;
|
||||
immediate = 0;
|
||||
break;
|
||||
case MISCREG_ZCR_EL2:
|
||||
{
|
||||
bool from_el1 = (el == EL1) && EL2Enabled(tc) && hcr.nv;
|
||||
bool from_el2 = (el == EL2) && ((!hcr.e2h && cptr.tz) ||
|
||||
(hcr.e2h && ((cptr.zen & 0x1) == 0x0)));
|
||||
trap_to_hyp = from_el1 || from_el2;
|
||||
ec = from_el1 ? EC_TRAPPED_MSR_MRS_64: EC_TRAPPED_SVE;
|
||||
}
|
||||
immediate = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return trap_to_hyp;
|
||||
}
|
||||
|
||||
bool
|
||||
MiscRegOp64::checkEL3Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
|
||||
ExceptionLevel el, ExceptionClass &ec,
|
||||
uint32_t &immediate) const
|
||||
{
|
||||
const CPTR cptr = tc->readMiscReg(MISCREG_CPTR_EL3);
|
||||
const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
|
||||
const HDCR mdcr = tc->readMiscReg(MISCREG_MDCR_EL3);
|
||||
const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
bool trap_to_mon = false;
|
||||
|
||||
switch (misc_reg) {
|
||||
// FP/SIMD regs
|
||||
case MISCREG_FPCR:
|
||||
case MISCREG_FPSR:
|
||||
case MISCREG_FPEXC32_EL2:
|
||||
trap_to_mon = cptr.tfp && ELIs64(tc, EL3);
|
||||
ec = EC_TRAPPED_SIMD_FP;
|
||||
immediate = 0x1E00000;
|
||||
break;
|
||||
// CPACR, CPTR
|
||||
case MISCREG_CPACR_EL12:
|
||||
trap_to_mon = ((el == EL2 && cptr.tcpac && ELIs64(tc, EL3)) ||
|
||||
(el == EL1 && cptr.tcpac && ELIs64(tc, EL3) &&
|
||||
(!hcr.nv2 || hcr.nv1 || !hcr.nv))) ;
|
||||
break;
|
||||
case MISCREG_CPACR_EL1:
|
||||
trap_to_mon = el <= EL2 && cptr.tcpac && ELIs64(tc, EL3);
|
||||
break;
|
||||
case MISCREG_CPTR_EL2:
|
||||
if (el == EL2) {
|
||||
trap_to_mon = cptr.tcpac;
|
||||
}
|
||||
break;
|
||||
// case MISCREG_LORC_EL1:
|
||||
// case MISCREG_LOREA_EL1:
|
||||
// case MISCREG_LORID_EL1:
|
||||
// case MISCREG_LORN_EL1:
|
||||
// case MISCREG_LORSA_EL1:
|
||||
// trap_to_mon = (el <= EL2) && scr.ns && ELIs64(tc,EL3)
|
||||
// && hcr.tlor && (!hcr.e2h || (hcr.e2h && !hcr.tge));
|
||||
// break;
|
||||
case MISCREG_MDCCSR_EL0:
|
||||
trap_to_mon = (el <= EL2) && ELIs64(tc, EL3) && mdcr.tda == 0x1;
|
||||
break;
|
||||
case MISCREG_APDAKeyHi_EL1:
|
||||
case MISCREG_APDAKeyLo_EL1:
|
||||
case MISCREG_APDBKeyHi_EL1:
|
||||
case MISCREG_APDBKeyLo_EL1:
|
||||
case MISCREG_APGAKeyHi_EL1:
|
||||
case MISCREG_APGAKeyLo_EL1:
|
||||
case MISCREG_APIAKeyHi_EL1:
|
||||
case MISCREG_APIAKeyLo_EL1:
|
||||
case MISCREG_APIBKeyHi_EL1:
|
||||
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;
|
||||
case MISCREG_DBGBVR0_EL1:
|
||||
case MISCREG_DBGBVR1_EL1:
|
||||
case MISCREG_DBGBVR2_EL1:
|
||||
case MISCREG_DBGBVR3_EL1:
|
||||
case MISCREG_DBGBVR4_EL1:
|
||||
case MISCREG_DBGBVR5_EL1:
|
||||
case MISCREG_DBGBVR6_EL1:
|
||||
case MISCREG_DBGBVR7_EL1:
|
||||
case MISCREG_DBGBVR8_EL1:
|
||||
case MISCREG_DBGBVR9_EL1:
|
||||
case MISCREG_DBGBVR10_EL1:
|
||||
case MISCREG_DBGBVR11_EL1:
|
||||
case MISCREG_DBGBVR12_EL1:
|
||||
case MISCREG_DBGBVR13_EL1:
|
||||
case MISCREG_DBGBVR14_EL1:
|
||||
case MISCREG_DBGBVR15_EL1:
|
||||
case MISCREG_DBGBCR0_EL1:
|
||||
case MISCREG_DBGBCR1_EL1:
|
||||
case MISCREG_DBGBCR2_EL1:
|
||||
case MISCREG_DBGBCR3_EL1:
|
||||
case MISCREG_DBGBCR4_EL1:
|
||||
case MISCREG_DBGBCR5_EL1:
|
||||
case MISCREG_DBGBCR6_EL1:
|
||||
case MISCREG_DBGBCR7_EL1:
|
||||
case MISCREG_DBGBCR8_EL1:
|
||||
case MISCREG_DBGBCR9_EL1:
|
||||
case MISCREG_DBGBCR10_EL1:
|
||||
case MISCREG_DBGBCR11_EL1:
|
||||
case MISCREG_DBGBCR12_EL1:
|
||||
case MISCREG_DBGBCR13_EL1:
|
||||
case MISCREG_DBGBCR14_EL1:
|
||||
case MISCREG_DBGBCR15_EL1:
|
||||
case MISCREG_DBGVCR32_EL2:
|
||||
case MISCREG_DBGWVR0_EL1:
|
||||
case MISCREG_DBGWVR1_EL1:
|
||||
case MISCREG_DBGWVR2_EL1:
|
||||
case MISCREG_DBGWVR3_EL1:
|
||||
case MISCREG_DBGWVR4_EL1:
|
||||
case MISCREG_DBGWVR5_EL1:
|
||||
case MISCREG_DBGWVR6_EL1:
|
||||
case MISCREG_DBGWVR7_EL1:
|
||||
case MISCREG_DBGWVR8_EL1:
|
||||
case MISCREG_DBGWVR9_EL1:
|
||||
case MISCREG_DBGWVR10_EL1:
|
||||
case MISCREG_DBGWVR11_EL1:
|
||||
case MISCREG_DBGWVR12_EL1:
|
||||
case MISCREG_DBGWVR13_EL1:
|
||||
case MISCREG_DBGWVR14_EL1:
|
||||
case MISCREG_DBGWVR15_EL1:
|
||||
case MISCREG_DBGWCR0_EL1:
|
||||
case MISCREG_DBGWCR1_EL1:
|
||||
case MISCREG_DBGWCR2_EL1:
|
||||
case MISCREG_DBGWCR3_EL1:
|
||||
case MISCREG_DBGWCR4_EL1:
|
||||
case MISCREG_DBGWCR5_EL1:
|
||||
case MISCREG_DBGWCR6_EL1:
|
||||
case MISCREG_DBGWCR7_EL1:
|
||||
case MISCREG_DBGWCR8_EL1:
|
||||
case MISCREG_DBGWCR9_EL1:
|
||||
case MISCREG_DBGWCR10_EL1:
|
||||
case MISCREG_DBGWCR11_EL1:
|
||||
case MISCREG_DBGWCR12_EL1:
|
||||
case MISCREG_DBGWCR13_EL1:
|
||||
case MISCREG_DBGWCR14_EL1:
|
||||
case MISCREG_DBGWCR15_EL1:
|
||||
case MISCREG_MDCCINT_EL1:
|
||||
case MISCREG_MDCR_EL2:
|
||||
trap_to_mon = ELIs64(tc, EL3) && mdcr.tda && (el == EL2);
|
||||
break;
|
||||
case MISCREG_ZCR_EL1:
|
||||
trap_to_mon = !cptr.ez && ((el == EL3) ||
|
||||
((el <= EL2) && ArmSystem::haveEL(tc,EL3) && ELIs64(tc, EL3)));
|
||||
ec = EC_TRAPPED_SVE;
|
||||
immediate = 0;
|
||||
break;
|
||||
case MISCREG_ZCR_EL2:
|
||||
trap_to_mon = !cptr.ez && ((el == EL3) ||
|
||||
((el == EL2) && ArmSystem::haveEL(tc,EL3) && ELIs64(tc, EL3)));
|
||||
ec = EC_TRAPPED_SVE;
|
||||
immediate = 0;
|
||||
break;
|
||||
case MISCREG_ZCR_EL3:
|
||||
trap_to_mon = !cptr.ez && (el == EL3);
|
||||
ec = EC_TRAPPED_SVE;
|
||||
immediate = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -672,16 +672,37 @@ ArmStaticInst::advSIMDFPAccessTrap64(ExceptionLevel el) const
|
||||
Fault
|
||||
ArmStaticInst::checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const
|
||||
{
|
||||
if (ArmSystem::haveVirtualization(tc) && !inSecureState(tc)) {
|
||||
HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2);
|
||||
if (cptrEnCheck.tfp)
|
||||
if (currEL(tc) <= EL2 && EL2Enabled(tc)) {
|
||||
bool trap_el2 = false;
|
||||
CPTR cptr_en_check = tc->readMiscReg(MISCREG_CPTR_EL2);
|
||||
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
if (HaveVirtHostExt(tc) && hcr.e2h == 0x1) {
|
||||
switch (cptr_en_check.fpen) {
|
||||
case 0:
|
||||
case 2:
|
||||
trap_el2 = !(currEL(tc) == EL1 && hcr.tge == 1);
|
||||
break;
|
||||
case 1:
|
||||
trap_el2 = (currEL(tc) == EL0 && hcr.tge == 1);
|
||||
break;
|
||||
default:
|
||||
trap_el2 = false;
|
||||
break;
|
||||
}
|
||||
} else if (cptr_en_check.tfp) {
|
||||
trap_el2 = true;
|
||||
}
|
||||
|
||||
if (trap_el2) {
|
||||
return advSIMDFPAccessTrap64(EL2);
|
||||
}
|
||||
}
|
||||
|
||||
if (ArmSystem::haveSecurity(tc)) {
|
||||
HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
|
||||
if (cptrEnCheck.tfp)
|
||||
CPTR cptr_en_check = tc->readMiscReg(MISCREG_CPTR_EL3);
|
||||
if (cptr_en_check.tfp) {
|
||||
return advSIMDFPAccessTrap64(EL3);
|
||||
}
|
||||
}
|
||||
|
||||
return NoFault;
|
||||
@@ -768,8 +789,8 @@ ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc,
|
||||
}
|
||||
|
||||
if (have_security && ELIs64(tc, EL3)) {
|
||||
HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
|
||||
if (cptrEnCheck.tfp)
|
||||
HCPTR cptr_en_check = tc->readMiscReg(MISCREG_CPTR_EL3);
|
||||
if (cptr_en_check.tfp)
|
||||
return advSIMDFPAccessTrap64(EL3);
|
||||
}
|
||||
|
||||
@@ -1008,10 +1029,24 @@ ArmStaticInst::checkSveEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const
|
||||
// Check if access disabled in CPTR_EL2
|
||||
if (el <= EL2 && EL2Enabled(tc)) {
|
||||
CPTR cptr_en_check = tc->readMiscReg(MISCREG_CPTR_EL2);
|
||||
if (cptr_en_check.tz)
|
||||
return sveAccessTrap(EL2);
|
||||
if (cptr_en_check.tfp)
|
||||
return advSIMDFPAccessTrap64(EL2);
|
||||
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
if (HaveVirtHostExt(tc) && hcr.e2h) {
|
||||
if (((cptr_en_check.zen & 0x1) == 0x0) ||
|
||||
(cptr_en_check.zen == 0x1 && el == EL0 &&
|
||||
hcr.tge == 0x1)) {
|
||||
return sveAccessTrap(EL2);
|
||||
}
|
||||
if (((cptr_en_check.fpen & 0x1) == 0x0) ||
|
||||
(cptr_en_check.fpen == 0x1 && el == EL0 &&
|
||||
hcr.tge == 0x1)) {
|
||||
return advSIMDFPAccessTrap64(EL2);
|
||||
}
|
||||
} else {
|
||||
if (cptr_en_check.tz == 1)
|
||||
return sveAccessTrap(EL2);
|
||||
if (cptr_en_check.tfp == 1)
|
||||
return advSIMDFPAccessTrap64(EL2);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if access disabled in CPTR_EL3
|
||||
|
||||
@@ -132,11 +132,23 @@ class Interrupts : public BaseInterrupts
|
||||
|
||||
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
|
||||
|
||||
bool no_vhe = !HaveVirtHostExt(tc);
|
||||
bool amo, fmo, imo;
|
||||
if (hcr.tge == 1){
|
||||
amo = (no_vhe || hcr.e2h == 0);
|
||||
fmo = (no_vhe || hcr.e2h == 0);
|
||||
imo = (no_vhe || hcr.e2h == 0);
|
||||
} else {
|
||||
amo = hcr.amo;
|
||||
fmo = hcr.fmo;
|
||||
imo = hcr.imo;
|
||||
}
|
||||
|
||||
bool isHypMode = currEL(tc) == EL2;
|
||||
bool isSecure = inSecureState(tc);
|
||||
bool allowVIrq = !cpsr.i && hcr.imo && !isSecure && !isHypMode;
|
||||
bool allowVFiq = !cpsr.f && hcr.fmo && !isSecure && !isHypMode;
|
||||
bool allowVAbort = !cpsr.a && hcr.amo && !isSecure && !isHypMode;
|
||||
bool allowVIrq = !cpsr.i && imo && !isSecure && !isHypMode;
|
||||
bool allowVFiq = !cpsr.f && fmo && !isSecure && !isHypMode;
|
||||
bool allowVAbort = !cpsr.a && amo && !isSecure && !isHypMode;
|
||||
|
||||
if ( !(intStatus || (hcr.vi && allowVIrq) || (hcr.vf && allowVFiq) ||
|
||||
(hcr.va && allowVAbort)) )
|
||||
@@ -219,14 +231,26 @@ class Interrupts : public BaseInterrupts
|
||||
HCR hcr = tc->readMiscReg(MISCREG_HCR);
|
||||
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
|
||||
|
||||
bool no_vhe = !HaveVirtHostExt(tc);
|
||||
bool amo, fmo, imo;
|
||||
if (hcr.tge == 1){
|
||||
amo = (no_vhe || hcr.e2h == 0);
|
||||
fmo = (no_vhe || hcr.e2h == 0);
|
||||
imo = (no_vhe || hcr.e2h == 0);
|
||||
} else {
|
||||
amo = hcr.amo;
|
||||
fmo = hcr.fmo;
|
||||
imo = hcr.imo;
|
||||
}
|
||||
|
||||
// Calculate a few temp vars so we can work out if there's a pending
|
||||
// virtual interrupt, and if its allowed to happen
|
||||
// ARM ARM Issue C section B1.9.9, B1.9.11, and B1.9.13
|
||||
bool isHypMode = currEL(tc) == EL2;
|
||||
bool isSecure = inSecureState(tc);
|
||||
bool allowVIrq = !cpsr.i && hcr.imo && !isSecure && !isHypMode;
|
||||
bool allowVFiq = !cpsr.f && hcr.fmo && !isSecure && !isHypMode;
|
||||
bool allowVAbort = !cpsr.a && hcr.amo && !isSecure && !isHypMode;
|
||||
bool allowVIrq = !cpsr.i && imo && !isSecure && !isHypMode;
|
||||
bool allowVFiq = !cpsr.f && fmo && !isSecure && !isHypMode;
|
||||
bool allowVAbort = !cpsr.a && amo && !isSecure && !isHypMode;
|
||||
|
||||
bool take_irq = takeInt(INT_IRQ);
|
||||
bool take_fiq = takeInt(INT_FIQ);
|
||||
|
||||
@@ -507,6 +507,7 @@ ISA::readMiscReg(int misc_reg)
|
||||
miscRegName[misc_reg]);
|
||||
}
|
||||
#endif
|
||||
misc_reg = redirectRegVHE(tc, misc_reg);
|
||||
|
||||
switch (unflattenMiscReg(misc_reg)) {
|
||||
case MISCREG_HCR:
|
||||
@@ -859,6 +860,8 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
miscRegName[misc_reg], val);
|
||||
}
|
||||
#endif
|
||||
misc_reg = redirectRegVHE(tc, misc_reg);
|
||||
|
||||
switch (unflattenMiscReg(misc_reg)) {
|
||||
case MISCREG_CPACR:
|
||||
{
|
||||
@@ -1707,7 +1710,6 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
}
|
||||
// AArch64 TLB Invalidate All, EL1
|
||||
case MISCREG_TLBI_ALLE1:
|
||||
case MISCREG_TLBI_VMALLE1:
|
||||
case MISCREG_TLBI_VMALLS12E1:
|
||||
// @todo: handle VMID and stage 2 to enable Virtualization
|
||||
{
|
||||
@@ -1718,9 +1720,21 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
tlbiOp(tc);
|
||||
return;
|
||||
}
|
||||
case MISCREG_TLBI_VMALLE1:
|
||||
// @todo: handle VMID and stage 2 to enable Virtualization
|
||||
{
|
||||
assert64();
|
||||
scr = readMiscReg(MISCREG_SCR);
|
||||
|
||||
HCR hcr = readMiscReg(MISCREG_HCR_EL2);
|
||||
bool is_host = (hcr.tge && hcr.e2h);
|
||||
ExceptionLevel target_el = is_host ? EL2 : EL1;
|
||||
TLBIALL tlbiOp(target_el, haveSecurity && !scr.ns);
|
||||
tlbiOp(tc);
|
||||
return;
|
||||
}
|
||||
// AArch64 TLB Invalidate All, EL1, Inner Shareable
|
||||
case MISCREG_TLBI_ALLE1IS:
|
||||
case MISCREG_TLBI_VMALLE1IS:
|
||||
case MISCREG_TLBI_VMALLS12E1IS:
|
||||
// @todo: handle VMID and stage 2 to enable Virtualization
|
||||
{
|
||||
@@ -1731,6 +1745,19 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
tlbiOp.broadcast(tc);
|
||||
return;
|
||||
}
|
||||
case MISCREG_TLBI_VMALLE1IS:
|
||||
// @todo: handle VMID and stage 2 to enable Virtualization
|
||||
{
|
||||
assert64();
|
||||
scr = readMiscReg(MISCREG_SCR);
|
||||
|
||||
HCR hcr = readMiscReg(MISCREG_HCR_EL2);
|
||||
bool is_host = (hcr.tge && hcr.e2h);
|
||||
ExceptionLevel target_el = is_host ? EL2 : EL1;
|
||||
TLBIALL tlbiOp(target_el, haveSecurity && !scr.ns);
|
||||
tlbiOp.broadcast(tc);
|
||||
return;
|
||||
}
|
||||
// VAEx(IS) and VALEx(IS) are the same because TLBs
|
||||
// only store entries
|
||||
// from the last level of translation table walks
|
||||
@@ -1796,7 +1823,10 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
auto asid = haveLargeAsid64 ? bits(newVal, 63, 48) :
|
||||
bits(newVal, 55, 48);
|
||||
|
||||
TLBIMVA tlbiOp(EL1, haveSecurity && !scr.ns,
|
||||
HCR hcr = readMiscReg(MISCREG_HCR_EL2);
|
||||
bool is_host = (hcr.tge && hcr.e2h);
|
||||
ExceptionLevel target_el = is_host ? EL2 : EL1;
|
||||
TLBIMVA tlbiOp(target_el, haveSecurity && !scr.ns,
|
||||
static_cast<Addr>(bits(newVal, 43, 0)) << 12,
|
||||
asid);
|
||||
|
||||
@@ -1812,9 +1842,12 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
auto asid = haveLargeAsid64 ? bits(newVal, 63, 48) :
|
||||
bits(newVal, 55, 48);
|
||||
|
||||
TLBIMVA tlbiOp(EL1, haveSecurity && !scr.ns,
|
||||
static_cast<Addr>(bits(newVal, 43, 0)) << 12,
|
||||
asid);
|
||||
HCR hcr = readMiscReg(MISCREG_HCR_EL2);
|
||||
bool is_host = (hcr.tge && hcr.e2h);
|
||||
ExceptionLevel target_el = is_host ? EL2 : EL1;
|
||||
TLBIMVA tlbiOp(target_el, haveSecurity && !scr.ns,
|
||||
static_cast<Addr>(bits(newVal, 43, 0)) << 12,
|
||||
asid);
|
||||
|
||||
tlbiOp.broadcast(tc);
|
||||
return;
|
||||
@@ -1828,7 +1861,10 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
auto asid = haveLargeAsid64 ? bits(newVal, 63, 48) :
|
||||
bits(newVal, 55, 48);
|
||||
|
||||
TLBIASID tlbiOp(EL1, haveSecurity && !scr.ns, asid);
|
||||
HCR hcr = readMiscReg(MISCREG_HCR_EL2);
|
||||
bool is_host = (hcr.tge && hcr.e2h);
|
||||
ExceptionLevel target_el = is_host ? EL2 : EL1;
|
||||
TLBIASID tlbiOp(target_el, haveSecurity && !scr.ns, asid);
|
||||
tlbiOp(tc);
|
||||
return;
|
||||
}
|
||||
@@ -1840,7 +1876,10 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
auto asid = haveLargeAsid64 ? bits(newVal, 63, 48) :
|
||||
bits(newVal, 55, 48);
|
||||
|
||||
TLBIASID tlbiOp(EL1, haveSecurity && !scr.ns, asid);
|
||||
HCR hcr = readMiscReg(MISCREG_HCR_EL2);
|
||||
bool is_host = (hcr.tge && hcr.e2h);
|
||||
ExceptionLevel target_el = is_host ? EL2 : EL1;
|
||||
TLBIASID tlbiOp(target_el, haveSecurity && !scr.ns, asid);
|
||||
tlbiOp.broadcast(tc);
|
||||
return;
|
||||
}
|
||||
@@ -1853,7 +1892,10 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
assert64();
|
||||
scr = readMiscReg(MISCREG_SCR);
|
||||
|
||||
TLBIMVAA tlbiOp(EL1, haveSecurity && !scr.ns,
|
||||
HCR hcr = readMiscReg(MISCREG_HCR_EL2);
|
||||
bool is_host = (hcr.tge && hcr.e2h);
|
||||
ExceptionLevel target_el = is_host ? EL2 : EL1;
|
||||
TLBIMVAA tlbiOp(target_el, haveSecurity && !scr.ns,
|
||||
static_cast<Addr>(bits(newVal, 43, 0)) << 12);
|
||||
|
||||
tlbiOp(tc);
|
||||
@@ -1866,7 +1908,10 @@ ISA::setMiscReg(int misc_reg, RegVal val)
|
||||
assert64();
|
||||
scr = readMiscReg(MISCREG_SCR);
|
||||
|
||||
TLBIMVAA tlbiOp(EL1, haveSecurity && !scr.ns,
|
||||
HCR hcr = readMiscReg(MISCREG_HCR_EL2);
|
||||
bool is_host = (hcr.tge && hcr.e2h);
|
||||
ExceptionLevel target_el = is_host ? EL2 : EL1;
|
||||
TLBIMVAA tlbiOp(target_el, haveSecurity && !scr.ns,
|
||||
static_cast<Addr>(bits(newVal, 43, 0)) << 12);
|
||||
|
||||
tlbiOp.broadcast(tc);
|
||||
|
||||
@@ -684,6 +684,78 @@ namespace ArmISA
|
||||
return flat_idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the enconcing equivalent when VHE is implemented and
|
||||
* HCR_EL2.E2H is enabled and executing at EL2
|
||||
*/
|
||||
int
|
||||
redirectRegVHE(ThreadContext * tc, int misc_reg)
|
||||
{
|
||||
const HCR hcr = readMiscRegNoEffect(MISCREG_HCR_EL2);
|
||||
if (hcr.e2h == 0x0 || currEL(tc) != EL2)
|
||||
return misc_reg;
|
||||
SCR scr = readMiscRegNoEffect(MISCREG_SCR_EL3);
|
||||
bool sec_el2 = scr.eel2 && false;
|
||||
switch(misc_reg) {
|
||||
case MISCREG_SPSR_EL1:
|
||||
return MISCREG_SPSR_EL2;
|
||||
case MISCREG_ELR_EL1:
|
||||
return MISCREG_ELR_EL2;
|
||||
case MISCREG_SCTLR_EL1:
|
||||
return MISCREG_SCTLR_EL2;
|
||||
case MISCREG_CPACR_EL1:
|
||||
return MISCREG_CPTR_EL2;
|
||||
// case :
|
||||
// return MISCREG_TRFCR_EL2;
|
||||
case MISCREG_TTBR0_EL1:
|
||||
return MISCREG_TTBR0_EL2;
|
||||
case MISCREG_TTBR1_EL1:
|
||||
return MISCREG_TTBR1_EL2;
|
||||
case MISCREG_TCR_EL1:
|
||||
return MISCREG_TCR_EL2;
|
||||
case MISCREG_AFSR0_EL1:
|
||||
return MISCREG_AFSR0_EL2;
|
||||
case MISCREG_AFSR1_EL1:
|
||||
return MISCREG_AFSR1_EL2;
|
||||
case MISCREG_ESR_EL1:
|
||||
return MISCREG_ESR_EL2;
|
||||
case MISCREG_FAR_EL1:
|
||||
return MISCREG_FAR_EL2;
|
||||
case MISCREG_MAIR_EL1:
|
||||
return MISCREG_MAIR_EL2;
|
||||
case MISCREG_AMAIR_EL1:
|
||||
return MISCREG_AMAIR_EL2;
|
||||
case MISCREG_VBAR_EL1:
|
||||
return MISCREG_VBAR_EL2;
|
||||
case MISCREG_CONTEXTIDR_EL1:
|
||||
return MISCREG_CONTEXTIDR_EL2;
|
||||
case MISCREG_CNTKCTL_EL1:
|
||||
return MISCREG_CNTHCTL_EL2;
|
||||
case MISCREG_CNTP_TVAL_EL0:
|
||||
return sec_el2? MISCREG_CNTHPS_TVAL_EL2:
|
||||
MISCREG_CNTHP_TVAL_EL2;
|
||||
case MISCREG_CNTP_CTL_EL0:
|
||||
return sec_el2? MISCREG_CNTHPS_CTL_EL2:
|
||||
MISCREG_CNTHP_CTL_EL2;
|
||||
case MISCREG_CNTP_CVAL_EL0:
|
||||
return sec_el2? MISCREG_CNTHPS_CVAL_EL2:
|
||||
MISCREG_CNTHP_CVAL_EL2;
|
||||
case MISCREG_CNTV_TVAL_EL0:
|
||||
return sec_el2? MISCREG_CNTHVS_TVAL_EL2:
|
||||
MISCREG_CNTHV_TVAL_EL2;
|
||||
case MISCREG_CNTV_CTL_EL0:
|
||||
return sec_el2? MISCREG_CNTHVS_CTL_EL2:
|
||||
MISCREG_CNTHV_CTL_EL2;
|
||||
case MISCREG_CNTV_CVAL_EL0:
|
||||
return sec_el2? MISCREG_CNTHVS_CVAL_EL2:
|
||||
MISCREG_CNTHV_CVAL_EL2;
|
||||
default:
|
||||
return misc_reg;
|
||||
}
|
||||
/*should not be accessible */
|
||||
return misc_reg;
|
||||
}
|
||||
|
||||
int
|
||||
snsBankedIndex64(MiscRegIndex reg, bool ns) const
|
||||
{
|
||||
|
||||
@@ -64,7 +64,7 @@ let {{
|
||||
|
||||
# Add memory request flags where necessary
|
||||
if self.user:
|
||||
self.memFlags.append("ArmISA::TLB::UserMode")
|
||||
self.memFlags.append("userFlag")
|
||||
|
||||
if self.flavor == "dprefetch":
|
||||
self.memFlags.append("Request::PREFETCH")
|
||||
@@ -135,6 +135,11 @@ let {{
|
||||
eaCode += self.offset
|
||||
eaCode += ";"
|
||||
|
||||
if self.user:
|
||||
eaCode += " uint8_t userFlag = 0;\n"\
|
||||
" if(isUnpriviledgeAccess(xc->tcBase()))\n"\
|
||||
" userFlag = ArmISA::TLB::UserMode;"
|
||||
|
||||
self.codeBlobs["ea_code"] = eaCode
|
||||
|
||||
def emitHelper(self, base='Memory64', wbDecl=None):
|
||||
|
||||
@@ -62,7 +62,7 @@ let {{
|
||||
|
||||
# Add memory request flags where necessary
|
||||
if self.user:
|
||||
self.memFlags.append("ArmISA::TLB::UserMode")
|
||||
self.memFlags.append("userFlag")
|
||||
|
||||
if self.flavor in ("relexp", "exp"):
|
||||
# For exclusive pair ops alignment check is based on total size
|
||||
@@ -135,6 +135,10 @@ let {{
|
||||
eaCode += self.offset
|
||||
eaCode += ";"
|
||||
|
||||
if self.user:
|
||||
eaCode += " uint8_t userFlag = 0;\n"\
|
||||
" if(isUnpriviledgeAccess(xc->tcBase()))\n"\
|
||||
" userFlag = ArmISA::TLB::UserMode;"
|
||||
self.codeBlobs["ea_code"] = eaCode
|
||||
|
||||
|
||||
|
||||
@@ -2233,7 +2233,16 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
/* op0: 3 Crn:1 op1:5 */
|
||||
switch (crm) {
|
||||
case 0:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_SCTLR_EL12;
|
||||
case 2:
|
||||
return MISCREG_CPACR_EL12;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
@@ -2349,6 +2358,21 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
/* op0: 3 Crn:2 op1:5 */
|
||||
switch (crm) {
|
||||
case 0:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_TTBR0_EL12;
|
||||
case 1:
|
||||
return MISCREG_TTBR1_EL12;
|
||||
case 2:
|
||||
return MISCREG_TCR_EL12;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (crm) {
|
||||
case 0:
|
||||
@@ -2471,6 +2495,18 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (crm) {
|
||||
case 0:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_SPSR_EL12;
|
||||
case 1:
|
||||
return MISCREG_ELR_EL12;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (crm) {
|
||||
case 0:
|
||||
@@ -2571,6 +2607,24 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (crm) {
|
||||
case 1:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_AFSR0_EL12;
|
||||
case 1:
|
||||
return MISCREG_AFSR1_EL12;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_ESR_EL12;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (crm) {
|
||||
case 1:
|
||||
@@ -2615,6 +2669,16 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (crm) {
|
||||
case 0:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_FAR_EL12;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (crm) {
|
||||
case 0:
|
||||
@@ -2733,6 +2797,22 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (crm) {
|
||||
case 2:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_MAIR_EL12;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_AMAIR_EL12;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (crm) {
|
||||
case 2:
|
||||
@@ -2958,6 +3038,16 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (crm) {
|
||||
case 0:
|
||||
switch (op2) {
|
||||
case 0:
|
||||
return MISCREG_VBAR_EL12;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (crm) {
|
||||
case 0:
|
||||
@@ -3022,6 +3112,16 @@ decodeAArch64SysReg(unsigned op0, unsigned op1,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (crm) {
|
||||
case 0:
|
||||
switch (op2) {
|
||||
case 1:
|
||||
return MISCREG_CONTEXTIDR_EL12;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch (crm) {
|
||||
case 0:
|
||||
@@ -4512,7 +4612,8 @@ ISA::initializeMiscRegMetadata()
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_DBGWCR15);
|
||||
InitReg(MISCREG_MDCCSR_EL0)
|
||||
.allPrivileges().monSecureWrite(0).monNonSecureWrite(0)
|
||||
.allPrivileges().writes(0)
|
||||
//monSecureWrite(0).monNonSecureWrite(0)
|
||||
.mapsTo(MISCREG_DBGDSCRint);
|
||||
InitReg(MISCREG_MDDTR_EL0)
|
||||
.allPrivileges();
|
||||
@@ -4679,12 +4780,26 @@ ISA::initializeMiscRegMetadata()
|
||||
| (nTLSMD ? 0 : 0x8000000)
|
||||
| (LSMAOE ? 0 : 0x10000000))
|
||||
.mapsTo(MISCREG_SCTLR_NS);
|
||||
InitReg(MISCREG_SCTLR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.res0( 0x20440 | (EnDB ? 0 : 0x2000)
|
||||
| (IESB ? 0 : 0x200000)
|
||||
| (EnDA ? 0 : 0x8000000)
|
||||
| (EnIB ? 0 : 0x40000000)
|
||||
| (EnIA ? 0 : 0x80000000))
|
||||
.res1(0x500800 | (SPAN ? 0 : 0x800000)
|
||||
| (nTLSMD ? 0 : 0x8000000)
|
||||
| (LSMAOE ? 0 : 0x10000000))
|
||||
.mapsTo(MISCREG_SCTLR_EL1);
|
||||
InitReg(MISCREG_ACTLR_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ACTLR_NS);
|
||||
InitReg(MISCREG_CPACR_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_CPACR);
|
||||
InitReg(MISCREG_CPACR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_CPACR_EL1);
|
||||
InitReg(MISCREG_SCTLR_EL2)
|
||||
.hyp().mon()
|
||||
.res0(0x0512c7c0 | (EnDB ? 0 : 0x2000)
|
||||
@@ -4736,12 +4851,21 @@ ISA::initializeMiscRegMetadata()
|
||||
InitReg(MISCREG_TTBR0_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_TTBR0_NS);
|
||||
InitReg(MISCREG_TTBR0_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_TTBR0_EL1);
|
||||
InitReg(MISCREG_TTBR1_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_TTBR1_NS);
|
||||
InitReg(MISCREG_TTBR1_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_TTBR1_EL1);
|
||||
InitReg(MISCREG_TCR_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_TTBCR_NS);
|
||||
InitReg(MISCREG_TCR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_TTBCR_NS);
|
||||
InitReg(MISCREG_TTBR0_EL2)
|
||||
.hyp().mon()
|
||||
.mapsTo(MISCREG_HTTBR);
|
||||
@@ -4766,8 +4890,14 @@ ISA::initializeMiscRegMetadata()
|
||||
InitReg(MISCREG_SPSR_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_SPSR_SVC); // NAM C5.2.17 SPSR_EL1
|
||||
InitReg(MISCREG_SPSR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_SPSR_SVC);
|
||||
InitReg(MISCREG_ELR_EL1)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ELR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ELR_EL1);
|
||||
InitReg(MISCREG_SP_EL0)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_SPSEL)
|
||||
@@ -4814,11 +4944,20 @@ ISA::initializeMiscRegMetadata()
|
||||
InitReg(MISCREG_AFSR0_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ADFSR_NS);
|
||||
InitReg(MISCREG_AFSR0_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ADFSR_NS);
|
||||
InitReg(MISCREG_AFSR1_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_AIFSR_NS);
|
||||
InitReg(MISCREG_AFSR1_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_AIFSR_NS);
|
||||
InitReg(MISCREG_ESR_EL1)
|
||||
.allPrivileges().exceptUserMode();
|
||||
InitReg(MISCREG_ESR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ESR_EL1);
|
||||
InitReg(MISCREG_IFSR32_EL2)
|
||||
.hyp().mon()
|
||||
.mapsTo(MISCREG_IFSR_NS);
|
||||
@@ -4842,6 +4981,9 @@ ISA::initializeMiscRegMetadata()
|
||||
InitReg(MISCREG_FAR_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_DFAR_NS, MISCREG_IFAR_NS);
|
||||
InitReg(MISCREG_FAR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_DFAR_NS, MISCREG_IFAR_NS);
|
||||
InitReg(MISCREG_FAR_EL2)
|
||||
.hyp().mon()
|
||||
.mapsTo(MISCREG_HDFAR, MISCREG_HIFAR);
|
||||
@@ -5023,9 +5165,15 @@ ISA::initializeMiscRegMetadata()
|
||||
InitReg(MISCREG_MAIR_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_PRRR_NS, MISCREG_NMRR_NS);
|
||||
InitReg(MISCREG_MAIR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_PRRR_NS, MISCREG_NMRR_NS);
|
||||
InitReg(MISCREG_AMAIR_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_AMAIR0_NS, MISCREG_AMAIR1_NS);
|
||||
InitReg(MISCREG_AMAIR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_AMAIR0_NS, MISCREG_AMAIR1_NS);
|
||||
InitReg(MISCREG_MAIR_EL2)
|
||||
.hyp().mon()
|
||||
.mapsTo(MISCREG_HMAIR0, MISCREG_HMAIR1);
|
||||
@@ -5043,6 +5191,9 @@ ISA::initializeMiscRegMetadata()
|
||||
InitReg(MISCREG_VBAR_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_VBAR_NS);
|
||||
InitReg(MISCREG_VBAR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_VBAR_NS);
|
||||
InitReg(MISCREG_RVBAR_EL1)
|
||||
.allPrivileges().exceptUserMode().writes(0);
|
||||
InitReg(MISCREG_ISR_EL1)
|
||||
@@ -5062,6 +5213,9 @@ ISA::initializeMiscRegMetadata()
|
||||
InitReg(MISCREG_CONTEXTIDR_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_CONTEXTIDR_NS);
|
||||
InitReg(MISCREG_CONTEXTIDR_EL12)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_CONTEXTIDR_NS);
|
||||
InitReg(MISCREG_TPIDR_EL1)
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_TPIDRPRW_NS);
|
||||
@@ -5180,7 +5334,21 @@ ISA::initializeMiscRegMetadata()
|
||||
.hyp()
|
||||
.res0(0xffffffff00000000)
|
||||
.mapsTo(MISCREG_CNTHP_TVAL);
|
||||
// IF Armv8.1-VHE
|
||||
InitReg(MISCREG_CNTHPS_CTL_EL2)
|
||||
.mon()
|
||||
.hyp()
|
||||
.res0(0xfffffffffffffff8)
|
||||
.unimplemented();
|
||||
InitReg(MISCREG_CNTHPS_CVAL_EL2)
|
||||
.mon()
|
||||
.hyp()
|
||||
.res0(0xfffffffffffffff8)
|
||||
.unimplemented();
|
||||
InitReg(MISCREG_CNTHPS_TVAL_EL2)
|
||||
.mon()
|
||||
.hyp()
|
||||
.res0(0xfffffffffffffff8)
|
||||
.unimplemented();
|
||||
InitReg(MISCREG_CNTHV_CTL_EL2)
|
||||
.mon()
|
||||
.hyp()
|
||||
@@ -5192,6 +5360,21 @@ ISA::initializeMiscRegMetadata()
|
||||
.mon()
|
||||
.hyp()
|
||||
.res0(0xffffffff00000000);
|
||||
InitReg(MISCREG_CNTHVS_CTL_EL2)
|
||||
.mon()
|
||||
.hyp()
|
||||
.res0(0xfffffffffffffff8)
|
||||
.unimplemented();
|
||||
InitReg(MISCREG_CNTHVS_CVAL_EL2)
|
||||
.mon()
|
||||
.hyp()
|
||||
.res0(0xfffffffffffffff8)
|
||||
.unimplemented();
|
||||
InitReg(MISCREG_CNTHVS_TVAL_EL2)
|
||||
.mon()
|
||||
.hyp()
|
||||
.res0(0xfffffffffffffff8)
|
||||
.unimplemented();
|
||||
// ENDIF Armv8.1-VHE
|
||||
InitReg(MISCREG_CNTVOFF_EL2)
|
||||
.mon()
|
||||
@@ -5746,7 +5929,8 @@ ISA::initializeMiscRegMetadata()
|
||||
InitReg(MISCREG_ZCR_EL2)
|
||||
.hyp().mon();
|
||||
InitReg(MISCREG_ZCR_EL12)
|
||||
.unimplemented().warnNotFail();
|
||||
.allPrivileges().exceptUserMode()
|
||||
.mapsTo(MISCREG_ZCR_EL1);
|
||||
InitReg(MISCREG_ZCR_EL1)
|
||||
.allPrivileges().exceptUserMode();
|
||||
|
||||
|
||||
@@ -569,8 +569,10 @@ namespace ArmISA
|
||||
MISCREG_VPIDR_EL2,
|
||||
MISCREG_VMPIDR_EL2,
|
||||
MISCREG_SCTLR_EL1,
|
||||
MISCREG_SCTLR_EL12,
|
||||
MISCREG_ACTLR_EL1,
|
||||
MISCREG_CPACR_EL1,
|
||||
MISCREG_CPACR_EL12,
|
||||
MISCREG_SCTLR_EL2,
|
||||
MISCREG_ACTLR_EL2,
|
||||
MISCREG_HCR_EL2,
|
||||
@@ -585,8 +587,11 @@ namespace ArmISA
|
||||
MISCREG_CPTR_EL3,
|
||||
MISCREG_MDCR_EL3,
|
||||
MISCREG_TTBR0_EL1,
|
||||
MISCREG_TTBR0_EL12,
|
||||
MISCREG_TTBR1_EL1,
|
||||
MISCREG_TTBR1_EL12,
|
||||
MISCREG_TCR_EL1,
|
||||
MISCREG_TCR_EL12,
|
||||
MISCREG_TTBR0_EL2,
|
||||
MISCREG_TCR_EL2,
|
||||
MISCREG_VTTBR_EL2,
|
||||
@@ -595,7 +600,9 @@ namespace ArmISA
|
||||
MISCREG_TCR_EL3,
|
||||
MISCREG_DACR32_EL2,
|
||||
MISCREG_SPSR_EL1,
|
||||
MISCREG_SPSR_EL12,
|
||||
MISCREG_ELR_EL1,
|
||||
MISCREG_ELR_EL12,
|
||||
MISCREG_SP_EL0,
|
||||
MISCREG_SPSEL,
|
||||
MISCREG_CURRENTEL,
|
||||
@@ -616,8 +623,11 @@ namespace ArmISA
|
||||
MISCREG_ELR_EL3,
|
||||
MISCREG_SP_EL2,
|
||||
MISCREG_AFSR0_EL1,
|
||||
MISCREG_AFSR0_EL12,
|
||||
MISCREG_AFSR1_EL1,
|
||||
MISCREG_AFSR1_EL12,
|
||||
MISCREG_ESR_EL1,
|
||||
MISCREG_ESR_EL12,
|
||||
MISCREG_IFSR32_EL2,
|
||||
MISCREG_AFSR0_EL2,
|
||||
MISCREG_AFSR1_EL2,
|
||||
@@ -627,6 +637,7 @@ namespace ArmISA
|
||||
MISCREG_AFSR1_EL3,
|
||||
MISCREG_ESR_EL3,
|
||||
MISCREG_FAR_EL1,
|
||||
MISCREG_FAR_EL12,
|
||||
MISCREG_FAR_EL2,
|
||||
MISCREG_HPFAR_EL2,
|
||||
MISCREG_FAR_EL3,
|
||||
@@ -703,7 +714,9 @@ namespace ArmISA
|
||||
MISCREG_PMUSERENR_EL0,
|
||||
MISCREG_PMOVSSET_EL0,
|
||||
MISCREG_MAIR_EL1,
|
||||
MISCREG_MAIR_EL12,
|
||||
MISCREG_AMAIR_EL1,
|
||||
MISCREG_AMAIR_EL12,
|
||||
MISCREG_MAIR_EL2,
|
||||
MISCREG_AMAIR_EL2,
|
||||
MISCREG_MAIR_EL3,
|
||||
@@ -711,6 +724,7 @@ namespace ArmISA
|
||||
MISCREG_L2CTLR_EL1,
|
||||
MISCREG_L2ECTLR_EL1,
|
||||
MISCREG_VBAR_EL1,
|
||||
MISCREG_VBAR_EL12,
|
||||
MISCREG_RVBAR_EL1,
|
||||
MISCREG_ISR_EL1,
|
||||
MISCREG_VBAR_EL2,
|
||||
@@ -719,6 +733,7 @@ namespace ArmISA
|
||||
MISCREG_RVBAR_EL3,
|
||||
MISCREG_RMR_EL3,
|
||||
MISCREG_CONTEXTIDR_EL1,
|
||||
MISCREG_CONTEXTIDR_EL12,
|
||||
MISCREG_TPIDR_EL1,
|
||||
MISCREG_TPIDR_EL0,
|
||||
MISCREG_TPIDRRO_EL0,
|
||||
@@ -749,10 +764,16 @@ namespace ArmISA
|
||||
MISCREG_CNTHP_CTL_EL2,
|
||||
MISCREG_CNTHP_CVAL_EL2,
|
||||
MISCREG_CNTHP_TVAL_EL2,
|
||||
MISCREG_CNTHPS_CTL_EL2,
|
||||
MISCREG_CNTHPS_CVAL_EL2,
|
||||
MISCREG_CNTHPS_TVAL_EL2,
|
||||
// IF Armv8.1-VHE
|
||||
MISCREG_CNTHV_CTL_EL2,
|
||||
MISCREG_CNTHV_CVAL_EL2,
|
||||
MISCREG_CNTHV_TVAL_EL2,
|
||||
MISCREG_CNTHVS_CTL_EL2,
|
||||
MISCREG_CNTHVS_CVAL_EL2,
|
||||
MISCREG_CNTHVS_TVAL_EL2,
|
||||
// ENDIF Armv8.1-VHE
|
||||
MISCREG_CNTVOFF_EL2,
|
||||
// END Generic Timer (AArch64)
|
||||
@@ -1647,8 +1668,10 @@ namespace ArmISA
|
||||
"vpidr_el2",
|
||||
"vmpidr_el2",
|
||||
"sctlr_el1",
|
||||
"sctlr_el12",
|
||||
"actlr_el1",
|
||||
"cpacr_el1",
|
||||
"cpacr_el12",
|
||||
"sctlr_el2",
|
||||
"actlr_el2",
|
||||
"hcr_el2",
|
||||
@@ -1663,8 +1686,11 @@ namespace ArmISA
|
||||
"cptr_el3",
|
||||
"mdcr_el3",
|
||||
"ttbr0_el1",
|
||||
"ttbr0_el12",
|
||||
"ttbr1_el1",
|
||||
"ttbr1_el12",
|
||||
"tcr_el1",
|
||||
"tcr_el12",
|
||||
"ttbr0_el2",
|
||||
"tcr_el2",
|
||||
"vttbr_el2",
|
||||
@@ -1673,7 +1699,9 @@ namespace ArmISA
|
||||
"tcr_el3",
|
||||
"dacr32_el2",
|
||||
"spsr_el1",
|
||||
"spsr_el12",
|
||||
"elr_el1",
|
||||
"elr_el12",
|
||||
"sp_el0",
|
||||
"spsel",
|
||||
"currentel",
|
||||
@@ -1694,8 +1722,11 @@ namespace ArmISA
|
||||
"elr_el3",
|
||||
"sp_el2",
|
||||
"afsr0_el1",
|
||||
"afsr0_el12",
|
||||
"afsr1_el1",
|
||||
"afsr1_el12",
|
||||
"esr_el1",
|
||||
"esr_el12",
|
||||
"ifsr32_el2",
|
||||
"afsr0_el2",
|
||||
"afsr1_el2",
|
||||
@@ -1705,6 +1736,7 @@ namespace ArmISA
|
||||
"afsr1_el3",
|
||||
"esr_el3",
|
||||
"far_el1",
|
||||
"far_el12",
|
||||
"far_el2",
|
||||
"hpfar_el2",
|
||||
"far_el3",
|
||||
@@ -1781,7 +1813,9 @@ namespace ArmISA
|
||||
"pmuserenr_el0",
|
||||
"pmovsset_el0",
|
||||
"mair_el1",
|
||||
"mair_el12",
|
||||
"amair_el1",
|
||||
"amair_el12",
|
||||
"mair_el2",
|
||||
"amair_el2",
|
||||
"mair_el3",
|
||||
@@ -1789,6 +1823,7 @@ namespace ArmISA
|
||||
"l2ctlr_el1",
|
||||
"l2ectlr_el1",
|
||||
"vbar_el1",
|
||||
"vbar_el12",
|
||||
"rvbar_el1",
|
||||
"isr_el1",
|
||||
"vbar_el2",
|
||||
@@ -1797,6 +1832,7 @@ namespace ArmISA
|
||||
"rvbar_el3",
|
||||
"rmr_el3",
|
||||
"contextidr_el1",
|
||||
"contextidr_el12",
|
||||
"tpidr_el1",
|
||||
"tpidr_el0",
|
||||
"tpidrro_el0",
|
||||
@@ -1826,9 +1862,15 @@ namespace ArmISA
|
||||
"cnthp_ctl_el2",
|
||||
"cnthp_cval_el2",
|
||||
"cnthp_tval_el2",
|
||||
"cnthps_ctl_el2",
|
||||
"cnthps_cval_el2",
|
||||
"cnthps_tval_el2",
|
||||
"cnthv_ctl_el2",
|
||||
"cnthv_cval_el2",
|
||||
"cnthv_tval_el2",
|
||||
"cnthvs_ctl_el2",
|
||||
"cnthvs_cval_el2",
|
||||
"cnthvs_tval_el2",
|
||||
"cntvoff_el2",
|
||||
"pmevcntr0_el0",
|
||||
"pmevcntr1_el0",
|
||||
|
||||
@@ -662,7 +662,11 @@ namespace ArmISA
|
||||
|
||||
BitUnion32(CPTR)
|
||||
Bitfield<31> tcpac;
|
||||
Bitfield<30> tam;
|
||||
Bitfield<28> tta_e2h;
|
||||
Bitfield<21, 20> fpen;
|
||||
Bitfield<20> tta;
|
||||
Bitfield<17, 16> zen;
|
||||
Bitfield<13, 12> res1_13_12_el2;
|
||||
Bitfield<10> tfp;
|
||||
Bitfield<9> res1_9_el2;
|
||||
|
||||
@@ -188,22 +188,23 @@ struct TlbEntry : public Serializable
|
||||
|
||||
bool
|
||||
match(Addr va, uint8_t _vmid, bool hypLookUp, bool secure_lookup,
|
||||
ExceptionLevel target_el) const
|
||||
ExceptionLevel target_el, bool in_host) const
|
||||
{
|
||||
return match(va, 0, _vmid, hypLookUp, secure_lookup, true, target_el);
|
||||
return match(va, 0, _vmid, hypLookUp, secure_lookup, true,
|
||||
target_el, in_host);
|
||||
}
|
||||
|
||||
bool
|
||||
match(Addr va, uint16_t asn, uint8_t _vmid, bool hypLookUp,
|
||||
bool secure_lookup, bool ignore_asn, ExceptionLevel target_el) const
|
||||
bool secure_lookup, bool ignore_asn, ExceptionLevel target_el,
|
||||
bool in_host) const
|
||||
{
|
||||
bool match = false;
|
||||
Addr v = vpn << N;
|
||||
|
||||
if (valid && va >= v && va <= v + size && (secure_lookup == !nstid) &&
|
||||
(hypLookUp == isHyp))
|
||||
{
|
||||
match = checkELMatch(target_el);
|
||||
match = checkELMatch(target_el, in_host);
|
||||
|
||||
if (match && !ignore_asn) {
|
||||
match = global || (asn == asid);
|
||||
@@ -216,12 +217,20 @@ struct TlbEntry : public Serializable
|
||||
}
|
||||
|
||||
bool
|
||||
checkELMatch(ExceptionLevel target_el) const
|
||||
checkELMatch(ExceptionLevel target_el, bool in_host) const
|
||||
{
|
||||
if (target_el == EL2 || target_el == EL3) {
|
||||
return (el == target_el);
|
||||
} else {
|
||||
return (el == EL0) || (el == EL1);
|
||||
switch (target_el) {
|
||||
case EL3:
|
||||
return el == EL3;
|
||||
case EL2:
|
||||
{
|
||||
return el == EL2 || (el == EL0 && in_host);
|
||||
}
|
||||
case EL1:
|
||||
case EL0:
|
||||
return (el == EL0) || (el == EL1);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -222,87 +222,106 @@ BrkPoint::test(ThreadContext *tc, Addr pc, ExceptionLevel el, DBGBCR ctr,
|
||||
bool from_link)
|
||||
{
|
||||
bool v = false;
|
||||
switch (ctr.bt)
|
||||
{
|
||||
case 0x0:
|
||||
v = testAddrMatch(tc, pc, ctr.bas);
|
||||
break;
|
||||
case 0x1:
|
||||
v = testAddrMatch(tc, pc, ctr.bas); // linked
|
||||
if (v){
|
||||
v = (conf->getBrkPoint(ctr.lbn))->testLinkedBk(tc, pc, el);
|
||||
}
|
||||
break;
|
||||
case 0x2:
|
||||
v = testContextMatch(tc, true);
|
||||
break;
|
||||
case 0x3:
|
||||
if (from_link){
|
||||
v = testContextMatch(tc, true); //linked
|
||||
}
|
||||
break;
|
||||
case 0x4:
|
||||
v = testAddrMissMatch(tc, pc, ctr.bas);
|
||||
break;
|
||||
case 0x5:
|
||||
v = testAddrMissMatch(tc, pc, ctr.bas); // linked
|
||||
if (v && !from_link)
|
||||
v = v && (conf->getBrkPoint(ctr.lbn))->testLinkedBk(tc,
|
||||
pc, el);
|
||||
break;
|
||||
case 0x6:
|
||||
// VHE not implemented
|
||||
// v = testContextMatch(tc, true);
|
||||
break;
|
||||
case 0x7:
|
||||
// VHE not implemented
|
||||
// if (from_link)
|
||||
// v = testContextMatch(tc, true);
|
||||
break;
|
||||
case 0x8:
|
||||
v = testVMIDMatch(tc);
|
||||
break;
|
||||
case 0x9:
|
||||
if (from_link && ArmSystem::haveEL(tc, EL2)){
|
||||
v = testVMIDMatch(tc); // linked
|
||||
}
|
||||
break;
|
||||
case 0xa:
|
||||
if (ArmSystem::haveEL(tc, EL2)){
|
||||
v = testContextMatch(tc, true);
|
||||
if (v && !from_link)
|
||||
v = v && testVMIDMatch(tc);
|
||||
}
|
||||
break;
|
||||
case 0xb:
|
||||
if (from_link && ArmSystem::haveEL(tc, EL2)){
|
||||
v = testContextMatch(tc, true);
|
||||
v = v && testVMIDMatch(tc);
|
||||
}
|
||||
break;
|
||||
case 0xc:
|
||||
// VHE not implemented
|
||||
// v = testContextMatch(tc, false); // CONTEXTIDR_EL2
|
||||
break;
|
||||
case 0xd:
|
||||
// VHE not implemented
|
||||
// if (from_link)
|
||||
// v = testContextMatch(tc, false);
|
||||
// CONTEXTIDR_EL2 AND LINKED
|
||||
switch (ctr.bt) {
|
||||
case 0x0:
|
||||
v = testAddrMatch(tc, pc, ctr.bas);
|
||||
break;
|
||||
|
||||
break;
|
||||
case 0xe:
|
||||
// VHE not implemented
|
||||
// v = testContextMatch(tc, true); // CONTEXTIDR_EL1
|
||||
// v = v && testContextMatch(tc, false); // CONTEXTIDR_EL2
|
||||
break;
|
||||
case 0xf:
|
||||
// VHE not implemented
|
||||
// if (from_link){
|
||||
// v = testContextMatch(tc, true); // CONTEXTIDR_EL1
|
||||
// v = v && testContextMatch(tc, false); // CONTEXTIDR_EL2
|
||||
// }
|
||||
break;
|
||||
case 0x1:
|
||||
v = testAddrMatch(tc, pc, ctr.bas); // linked
|
||||
if (v) {
|
||||
v = (conf->getBrkPoint(ctr.lbn))->testLinkedBk(tc, pc, el);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
{
|
||||
bool host = ELIsInHost(tc, el);
|
||||
v = testContextMatch(tc, !host, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3:
|
||||
if (from_link){
|
||||
bool host = ELIsInHost(tc, el);
|
||||
v = testContextMatch(tc, !host, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
v = testAddrMissMatch(tc, pc, ctr.bas);
|
||||
break;
|
||||
|
||||
case 0x5:
|
||||
v = testAddrMissMatch(tc, pc, ctr.bas); // linked
|
||||
if (v && !from_link)
|
||||
v = v && (conf->getBrkPoint(ctr.lbn))->testLinkedBk(tc, pc, el);
|
||||
break;
|
||||
|
||||
case 0x6:
|
||||
if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el))
|
||||
v = testContextMatch(tc, true);
|
||||
break;
|
||||
|
||||
case 0x7:
|
||||
if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el) && from_link)
|
||||
v = testContextMatch(tc, true);
|
||||
break;
|
||||
|
||||
case 0x8:
|
||||
if (ArmSystem::haveEL(tc, EL2) && !ELIsInHost(tc, el)) {
|
||||
v = testVMIDMatch(tc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x9:
|
||||
if (from_link && ArmSystem::haveEL(tc, EL2) &&
|
||||
!ELIsInHost(tc, el)) {
|
||||
v = testVMIDMatch(tc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xa:
|
||||
if (ArmSystem::haveEL(tc, EL2) && !ELIsInHost(tc, el)) {
|
||||
v = testContextMatch(tc, true);
|
||||
if (v && !from_link)
|
||||
v = v && testVMIDMatch(tc);
|
||||
}
|
||||
break;
|
||||
case 0xb:
|
||||
if (from_link && ArmSystem::haveEL(tc, EL2) &&
|
||||
!ELIsInHost(tc, el)) {
|
||||
v = testContextMatch(tc, true);
|
||||
v = v && testVMIDMatch(tc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xc:
|
||||
if (HaveVirtHostExt(tc) && !inSecureState(tc))
|
||||
v = testContextMatch(tc, false);
|
||||
break;
|
||||
|
||||
case 0xd:
|
||||
if (HaveVirtHostExt(tc) && from_link && !inSecureState(tc))
|
||||
v = testContextMatch(tc, false);
|
||||
break;
|
||||
|
||||
case 0xe:
|
||||
if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el)
|
||||
&& !inSecureState(tc) ) {
|
||||
v = testContextMatch(tc, true); // CONTEXTIDR_EL1
|
||||
v = v && testContextMatch(tc, false); // CONTEXTIDR_EL2
|
||||
}
|
||||
break;
|
||||
case 0xf:
|
||||
if (HaveVirtHostExt(tc) && !ELIsInHost(tc, el) && from_link
|
||||
&& !inSecureState(tc) ) {
|
||||
v = testContextMatch(tc, true); // CONTEXTIDR_EL1
|
||||
v = v && testContextMatch(tc, false); // CONTEXTIDR_EL2
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
@@ -403,6 +422,12 @@ BrkPoint::testAddrMissMatch(ThreadContext *tc, Addr in_pc, uint8_t bas)
|
||||
|
||||
bool
|
||||
BrkPoint::testContextMatch(ThreadContext *tc, bool ctx1)
|
||||
{
|
||||
return testContextMatch(tc, ctx1, ctx1);
|
||||
}
|
||||
|
||||
bool
|
||||
BrkPoint::testContextMatch(ThreadContext *tc, bool ctx1, bool low_ctx)
|
||||
{
|
||||
if (!isCntxtAware)
|
||||
return false;
|
||||
@@ -420,8 +445,8 @@ BrkPoint::testContextMatch(ThreadContext *tc, bool ctx1)
|
||||
return false;
|
||||
}
|
||||
|
||||
RegVal ctxid = tc->readMiscReg(miscridx);
|
||||
RegVal v = getContextfromReg(tc, ctx1);
|
||||
RegVal ctxid = bits(tc->readMiscReg(miscridx), 31, 0);
|
||||
RegVal v = getContextfromReg(tc, low_ctx);
|
||||
return (v == ctxid);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ class BrkPoint
|
||||
public:
|
||||
bool testAddrMatch(ThreadContext *tc, Addr pc, uint8_t bas);
|
||||
bool testAddrMissMatch(ThreadContext *tc, Addr pc, uint8_t bas);
|
||||
bool testContextMatch(ThreadContext *tc, bool ctx1, bool low_ctx);
|
||||
bool testContextMatch(ThreadContext *tc, bool ctx1);
|
||||
bool testVMIDMatch(ThreadContext *tc);
|
||||
|
||||
|
||||
@@ -264,11 +264,21 @@ TableWalker::walk(const RequestPtr &_req, ThreadContext *_tc, uint16_t _asid,
|
||||
currState->vaddr = currState->vaddr_tainted;
|
||||
|
||||
if (currState->aarch64) {
|
||||
currState->hcr = currState->tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
if (isStage2) {
|
||||
currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
|
||||
currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR_EL2);
|
||||
} else switch (currState->el) {
|
||||
case EL0:
|
||||
if (HaveVirtHostExt(currState->tc) &&
|
||||
currState->hcr.tge == 1 && currState->hcr.e2h ==1) {
|
||||
currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2);
|
||||
currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL2);
|
||||
} else {
|
||||
currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
|
||||
currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL1);
|
||||
}
|
||||
break;
|
||||
case EL1:
|
||||
currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
|
||||
currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL1);
|
||||
@@ -287,7 +297,6 @@ TableWalker::walk(const RequestPtr &_req, ThreadContext *_tc, uint16_t _asid,
|
||||
panic("Invalid exception level");
|
||||
break;
|
||||
}
|
||||
currState->hcr = currState->tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
} else {
|
||||
currState->sctlr = currState->tc->readMiscReg(snsBankedIndex(
|
||||
MISCREG_SCTLR, currState->tc, !currState->isSecure));
|
||||
@@ -370,7 +379,7 @@ TableWalker::processWalkWrapper()
|
||||
// @TODO Should this always be the TLB or should we look in the stage2 TLB?
|
||||
TlbEntry* te = tlb->lookup(currState->vaddr, currState->asid,
|
||||
currState->vmid, currState->isHyp, currState->isSecure, true, false,
|
||||
currState->el);
|
||||
currState->el, false);
|
||||
|
||||
// Check if we still need to have a walk for this request. If the requesting
|
||||
// instruction has been squashed, or a previous walk has filled the TLB with
|
||||
@@ -436,7 +445,7 @@ TableWalker::processWalkWrapper()
|
||||
currState = pendingQueue.front();
|
||||
te = tlb->lookup(currState->vaddr, currState->asid,
|
||||
currState->vmid, currState->isHyp, currState->isSecure, true,
|
||||
false, currState->el);
|
||||
false, currState->el, false);
|
||||
} else {
|
||||
// Terminate the loop, nothing more to do
|
||||
currState = NULL;
|
||||
@@ -772,6 +781,48 @@ TableWalker::processWalkAArch64()
|
||||
|
||||
switch (currState->el) {
|
||||
case EL0:
|
||||
{
|
||||
Addr ttbr0;
|
||||
Addr ttbr1;
|
||||
if (HaveVirtHostExt(currState->tc) &&
|
||||
currState->hcr.tge==1 && currState->hcr.e2h == 1) {
|
||||
// VHE code for EL2&0 regime
|
||||
ttbr0 = currState->tc->readMiscReg(MISCREG_TTBR0_EL2);
|
||||
ttbr1 = currState->tc->readMiscReg(MISCREG_TTBR1_EL2);
|
||||
} else {
|
||||
ttbr0 = currState->tc->readMiscReg(MISCREG_TTBR0_EL1);
|
||||
ttbr1 = currState->tc->readMiscReg(MISCREG_TTBR1_EL1);
|
||||
}
|
||||
switch (bits(currState->vaddr, 63,48)) {
|
||||
case 0:
|
||||
DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
|
||||
ttbr = ttbr0;
|
||||
tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
|
||||
tg = GrainMap_tg0[currState->tcr.tg0];
|
||||
currState->hpd = currState->tcr.hpd0;
|
||||
currState->isUncacheable = currState->tcr.irgn0 == 0;
|
||||
if (bits(currState->vaddr, 63, tsz) != 0x0 ||
|
||||
currState->tcr.epd0)
|
||||
fault = true;
|
||||
break;
|
||||
case 0xffff:
|
||||
DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
|
||||
ttbr = ttbr1;
|
||||
tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz);
|
||||
tg = GrainMap_tg1[currState->tcr.tg1];
|
||||
currState->hpd = currState->tcr.hpd1;
|
||||
currState->isUncacheable = currState->tcr.irgn1 == 0;
|
||||
if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) ||
|
||||
currState->tcr.epd1)
|
||||
fault = true;
|
||||
break;
|
||||
default:
|
||||
// top two bytes must be all 0s or all 1s, else invalid addr
|
||||
fault = true;
|
||||
}
|
||||
ps = currState->tcr.ips;
|
||||
}
|
||||
break;
|
||||
case EL1:
|
||||
if (isStage2) {
|
||||
DPRINTF(TLB, " - Selecting VTTBR0 (AArch64 stage 2)\n");
|
||||
@@ -828,7 +879,7 @@ TableWalker::processWalkAArch64()
|
||||
case EL2:
|
||||
switch(bits(currState->vaddr, 63,48)) {
|
||||
case 0:
|
||||
DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
|
||||
DPRINTF(TLB, " - Selecting TTBR0_EL2 (AArch64)\n");
|
||||
ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2);
|
||||
tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
|
||||
tg = GrainMap_tg0[currState->tcr.tg0];
|
||||
@@ -838,7 +889,7 @@ TableWalker::processWalkAArch64()
|
||||
break;
|
||||
|
||||
case 0xffff:
|
||||
DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
|
||||
DPRINTF(TLB, " - Selecting TTBR1_EL2 (AArch64)\n");
|
||||
ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL2);
|
||||
tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz);
|
||||
tg = GrainMap_tg1[currState->tcr.tg1];
|
||||
@@ -853,12 +904,12 @@ TableWalker::processWalkAArch64()
|
||||
// invalid addr if top two bytes are not all 0s
|
||||
fault = true;
|
||||
}
|
||||
ps = currState->tcr.ps;
|
||||
ps = currState->hcr.e2h ? currState->tcr.ips: currState->tcr.ps;
|
||||
break;
|
||||
case EL3:
|
||||
switch(bits(currState->vaddr, 63,48)) {
|
||||
case 0:
|
||||
DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
|
||||
DPRINTF(TLB, " - Selecting TTBR0_EL3 (AArch64)\n");
|
||||
ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3);
|
||||
tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
|
||||
tg = GrainMap_tg0[currState->tcr.tg0];
|
||||
@@ -1408,10 +1459,11 @@ TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
|
||||
uint8_t attrIndx = lDescriptor.attrIndx();
|
||||
|
||||
DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh);
|
||||
ExceptionLevel regime = s1TranslationRegime(tc, currState->el);
|
||||
|
||||
// Select MAIR
|
||||
uint64_t mair;
|
||||
switch (currState->el) {
|
||||
switch (regime) {
|
||||
case EL0:
|
||||
case EL1:
|
||||
mair = tc->readMiscReg(MISCREG_MAIR_EL1);
|
||||
|
||||
@@ -124,7 +124,7 @@ TLB::translateFunctional(ThreadContext *tc, Addr va, Addr &pa)
|
||||
}
|
||||
|
||||
TlbEntry *e = lookup(va, asid, vmid, isHyp, isSecure, true, false,
|
||||
aarch64 ? aarch64EL : EL1);
|
||||
aarch64 ? aarch64EL : EL1, false);
|
||||
if (!e)
|
||||
return false;
|
||||
pa = e->pAddr(va);
|
||||
@@ -157,7 +157,8 @@ TLB::finalizePhysical(const RequestPtr &req,
|
||||
|
||||
TlbEntry*
|
||||
TLB::lookup(Addr va, uint16_t asn, uint8_t vmid, bool hyp, bool secure,
|
||||
bool functional, bool ignore_asn, ExceptionLevel target_el)
|
||||
bool functional, bool ignore_asn, ExceptionLevel target_el,
|
||||
bool in_host)
|
||||
{
|
||||
|
||||
TlbEntry *retval = NULL;
|
||||
@@ -166,8 +167,9 @@ TLB::lookup(Addr va, uint16_t asn, uint8_t vmid, bool hyp, bool secure,
|
||||
int x = 0;
|
||||
while (retval == NULL && x < size) {
|
||||
if ((!ignore_asn && table[x].match(va, asn, vmid, hyp, secure, false,
|
||||
target_el)) ||
|
||||
(ignore_asn && table[x].match(va, vmid, hyp, secure, target_el))) {
|
||||
target_el, in_host)) ||
|
||||
(ignore_asn && table[x].match(va, vmid, hyp, secure, target_el,
|
||||
in_host))) {
|
||||
// We only move the hit entry ahead when the position is higher
|
||||
// than rangeMRU
|
||||
if (x > rangeMRU && !functional) {
|
||||
@@ -244,7 +246,7 @@ TLB::printTlb() const
|
||||
|
||||
void
|
||||
TLB::flushAllSecurity(bool secure_lookup, ExceptionLevel target_el,
|
||||
bool ignore_el)
|
||||
bool ignore_el, bool in_host)
|
||||
{
|
||||
DPRINTF(TLB, "Flushing all TLB entries (%s lookup)\n",
|
||||
(secure_lookup ? "secure" : "non-secure"));
|
||||
@@ -253,8 +255,7 @@ TLB::flushAllSecurity(bool secure_lookup, ExceptionLevel target_el,
|
||||
while (x < size) {
|
||||
te = &table[x];
|
||||
const bool el_match = ignore_el ?
|
||||
true : te->checkELMatch(target_el);
|
||||
|
||||
true : te->checkELMatch(target_el, in_host);
|
||||
if (te->valid && secure_lookup == !te->nstid &&
|
||||
(te->vmid == vmid || secure_lookup) && el_match) {
|
||||
|
||||
@@ -270,7 +271,7 @@ TLB::flushAllSecurity(bool secure_lookup, ExceptionLevel target_el,
|
||||
// If there's a second stage TLB (and we're not it) then flush it as well
|
||||
// if we're currently in hyp mode
|
||||
if (!isStage2 && isHyp) {
|
||||
stage2Tlb->flushAllSecurity(secure_lookup, EL1, true);
|
||||
stage2Tlb->flushAllSecurity(secure_lookup, EL1, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,7 +287,7 @@ TLB::flushAllNs(ExceptionLevel target_el, bool ignore_el)
|
||||
while (x < size) {
|
||||
te = &table[x];
|
||||
const bool el_match = ignore_el ?
|
||||
true : te->checkELMatch(target_el);
|
||||
true : te->checkELMatch(target_el, false);
|
||||
|
||||
if (te->valid && te->nstid && te->isHyp == hyp && el_match) {
|
||||
|
||||
@@ -307,17 +308,18 @@ TLB::flushAllNs(ExceptionLevel target_el, bool ignore_el)
|
||||
|
||||
void
|
||||
TLB::flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup,
|
||||
ExceptionLevel target_el)
|
||||
ExceptionLevel target_el, bool in_host)
|
||||
{
|
||||
DPRINTF(TLB, "Flushing TLB entries with mva: %#x, asid: %#x "
|
||||
"(%s lookup)\n", mva, asn, (secure_lookup ?
|
||||
"secure" : "non-secure"));
|
||||
_flushMva(mva, asn, secure_lookup, false, target_el);
|
||||
_flushMva(mva, asn, secure_lookup, false, target_el, in_host);
|
||||
flushTlbMvaAsid++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flushAsid(uint64_t asn, bool secure_lookup, ExceptionLevel target_el)
|
||||
TLB::flushAsid(uint64_t asn, bool secure_lookup, ExceptionLevel target_el,
|
||||
bool in_host)
|
||||
{
|
||||
DPRINTF(TLB, "Flushing TLB entries with asid: %#x (%s lookup)\n", asn,
|
||||
(secure_lookup ? "secure" : "non-secure"));
|
||||
@@ -329,7 +331,7 @@ TLB::flushAsid(uint64_t asn, bool secure_lookup, ExceptionLevel target_el)
|
||||
te = &table[x];
|
||||
if (te->valid && te->asid == asn && secure_lookup == !te->nstid &&
|
||||
(te->vmid == vmid || secure_lookup) &&
|
||||
te->checkELMatch(target_el)) {
|
||||
te->checkELMatch(target_el, in_host)) {
|
||||
|
||||
te->valid = false;
|
||||
DPRINTF(TLB, " - %s\n", te->print());
|
||||
@@ -341,17 +343,18 @@ TLB::flushAsid(uint64_t asn, bool secure_lookup, ExceptionLevel target_el)
|
||||
}
|
||||
|
||||
void
|
||||
TLB::flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el)
|
||||
{
|
||||
TLB::flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el,
|
||||
bool in_host) {
|
||||
|
||||
DPRINTF(TLB, "Flushing TLB entries with mva: %#x (%s lookup)\n", mva,
|
||||
(secure_lookup ? "secure" : "non-secure"));
|
||||
_flushMva(mva, 0xbeef, secure_lookup, true, target_el);
|
||||
_flushMva(mva, 0xbeef, secure_lookup, true, target_el, in_host);
|
||||
flushTlbMva++;
|
||||
}
|
||||
|
||||
void
|
||||
TLB::_flushMva(Addr mva, uint64_t asn, bool secure_lookup,
|
||||
bool ignore_asn, ExceptionLevel target_el)
|
||||
bool ignore_asn, ExceptionLevel target_el, bool in_host)
|
||||
{
|
||||
TlbEntry *te;
|
||||
// D5.7.2: Sign-extend address to 64 bits
|
||||
@@ -360,7 +363,7 @@ TLB::_flushMva(Addr mva, uint64_t asn, bool secure_lookup,
|
||||
bool hyp = target_el == EL2;
|
||||
|
||||
te = lookup(mva, asn, vmid, hyp, secure_lookup, false, ignore_asn,
|
||||
target_el);
|
||||
target_el, in_host);
|
||||
while (te != NULL) {
|
||||
if (secure_lookup == !te->nstid) {
|
||||
DPRINTF(TLB, " - %s\n", te->print());
|
||||
@@ -368,7 +371,7 @@ TLB::_flushMva(Addr mva, uint64_t asn, bool secure_lookup,
|
||||
flushedEntries++;
|
||||
}
|
||||
te = lookup(mva, asn, vmid, hyp, secure_lookup, false, ignore_asn,
|
||||
target_el);
|
||||
target_el, in_host);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,7 +379,7 @@ void
|
||||
TLB::flushIpaVmid(Addr ipa, bool secure_lookup, ExceptionLevel target_el)
|
||||
{
|
||||
assert(!isStage2);
|
||||
stage2Tlb->_flushMva(ipa, 0xbeef, secure_lookup, true, target_el);
|
||||
stage2Tlb->_flushMva(ipa, 0xbeef, secure_lookup, true, target_el, false);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -823,9 +826,10 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode,
|
||||
uint8_t ap = 0x3 & (te->ap); // 2-bit access protection field
|
||||
bool grant = false;
|
||||
|
||||
bool wxn = sctlr.wxn;
|
||||
uint8_t xn = te->xn;
|
||||
uint8_t pxn = te->pxn;
|
||||
bool r = !is_write && !is_fetch;
|
||||
bool r = (!is_write && !is_fetch);
|
||||
bool w = is_write;
|
||||
bool x = is_fetch;
|
||||
|
||||
@@ -835,7 +839,8 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode,
|
||||
// generated the fault; they count as writes otherwise
|
||||
bool grant_read = true;
|
||||
DPRINTF(TLBVerbose, "Checking permissions: ap:%d, xn:%d, pxn:%d, r:%d, "
|
||||
"w:%d, x:%d\n", ap, xn, pxn, r, w, x);
|
||||
"w:%d, x:%d, is_priv: %d, wxn: %d\n", ap, xn,
|
||||
pxn, r, w, x, is_priv, wxn);
|
||||
|
||||
if (isStage2) {
|
||||
assert(ArmSystem::haveVirtualization(tc) && aarch64EL != EL2);
|
||||
@@ -846,7 +851,10 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode,
|
||||
grant_read = hap & 0x1;
|
||||
if (is_fetch) {
|
||||
// sctlr.wxn overrides the xn bit
|
||||
grant = !sctlr.wxn && !xn;
|
||||
grant = !wxn && !xn;
|
||||
} else if (is_atomic) {
|
||||
grant = r && w;
|
||||
grant_read = r;
|
||||
} else if (is_write) {
|
||||
grant = hap & 0x2;
|
||||
} else { // is_read
|
||||
@@ -867,7 +875,7 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode,
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
grant = r || w || (x && !sctlr.wxn);
|
||||
grant = r || w || (x && !wxn);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
@@ -898,7 +906,7 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode,
|
||||
switch (perm) {
|
||||
case 0:
|
||||
case 2:
|
||||
grant = r || w || (x && !sctlr.wxn);
|
||||
grant = r || w || (x && !wxn);
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
@@ -939,7 +947,7 @@ TLB::checkPermissions64(TlbEntry *te, const RequestPtr &req, Mode mode,
|
||||
uint8_t perm = (ap & 0x2) | xn;
|
||||
switch (perm) {
|
||||
case 0:
|
||||
grant = r || w || (x && !sctlr.wxn) ;
|
||||
grant = r || w || (x && !wxn);
|
||||
break;
|
||||
case 1:
|
||||
grant = r || w;
|
||||
@@ -1049,13 +1057,16 @@ TLB::translateMmuOff(ThreadContext *tc, const RequestPtr &req, Mode mode,
|
||||
// Set memory attributes
|
||||
TlbEntry temp_te;
|
||||
temp_te.ns = !isSecure;
|
||||
if (isStage2 || hcr.dc == 0 || isSecure ||
|
||||
bool dc = (HaveVirtHostExt(tc)
|
||||
&& hcr.e2h == 1 && hcr.tge == 1) ? 0: hcr.dc;
|
||||
bool i_cacheability = sctlr.i && !sctlr.m;
|
||||
if (isStage2 || !dc || isSecure ||
|
||||
(isHyp && !(tranType & S1CTran))) {
|
||||
|
||||
temp_te.mtype = is_fetch ? TlbEntry::MemoryType::Normal
|
||||
: TlbEntry::MemoryType::StronglyOrdered;
|
||||
temp_te.innerAttrs = 0x0;
|
||||
temp_te.outerAttrs = 0x0;
|
||||
temp_te.innerAttrs = i_cacheability? 0x2: 0x0;
|
||||
temp_te.outerAttrs = i_cacheability? 0x2: 0x0;
|
||||
temp_te.shareable = true;
|
||||
temp_te.outerShareable = true;
|
||||
} else {
|
||||
@@ -1119,7 +1130,8 @@ TLB::translateMmuOn(ThreadContext* tc, const RequestPtr &req, Mode mode,
|
||||
if (isSecure && !te->ns) {
|
||||
req->setFlags(Request::SECURE);
|
||||
}
|
||||
if ((!is_fetch) && (vaddr & mask(flags & AlignmentMask)) &&
|
||||
if (!is_fetch && fault == NoFault &&
|
||||
(vaddr & mask(flags & AlignmentMask)) &&
|
||||
(te->mtype != TlbEntry::MemoryType::Normal)) {
|
||||
// Unaligned accesses to Device memory should always cause an
|
||||
// abort regardless of sctlr.a
|
||||
@@ -1199,9 +1211,15 @@ TLB::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode,
|
||||
}
|
||||
}
|
||||
|
||||
bool vm = hcr.vm;
|
||||
if (HaveVirtHostExt(tc) && hcr.e2h == 1 && hcr.tge ==1)
|
||||
vm = 0;
|
||||
else if (hcr.dc == 1)
|
||||
vm = 1;
|
||||
|
||||
Fault fault = NoFault;
|
||||
// If guest MMU is off or hcr.vm=0 go straight to stage2
|
||||
if ((isStage2 && !hcr.vm) || (!isStage2 && !sctlr.m)) {
|
||||
if ((isStage2 && !vm) || (!isStage2 && !sctlr.m)) {
|
||||
fault = translateMmuOff(tc, req, mode, tranType, vaddr,
|
||||
long_desc_format);
|
||||
} else {
|
||||
@@ -1341,10 +1359,32 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
|
||||
ELIs64(tc, EL2) :
|
||||
ELIs64(tc, aarch64EL == EL0 ? EL1 : aarch64EL);
|
||||
|
||||
hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
if (aarch64) { // AArch64
|
||||
// determine EL we need to translate in
|
||||
switch (aarch64EL) {
|
||||
case EL0:
|
||||
if (HaveVirtHostExt(tc) && hcr.tge == 1 && hcr.e2h == 1) {
|
||||
// VHE code for EL2&0 regime
|
||||
sctlr = tc->readMiscReg(MISCREG_SCTLR_EL2);
|
||||
ttbcr = tc->readMiscReg(MISCREG_TCR_EL2);
|
||||
uint64_t ttbr_asid = ttbcr.a1 ?
|
||||
tc->readMiscReg(MISCREG_TTBR1_EL2) :
|
||||
tc->readMiscReg(MISCREG_TTBR0_EL2);
|
||||
asid = bits(ttbr_asid,
|
||||
(haveLargeAsid64 && ttbcr.as) ? 63 : 55, 48);
|
||||
|
||||
} else {
|
||||
sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1);
|
||||
ttbcr = tc->readMiscReg(MISCREG_TCR_EL1);
|
||||
uint64_t ttbr_asid = ttbcr.a1 ?
|
||||
tc->readMiscReg(MISCREG_TTBR1_EL1) :
|
||||
tc->readMiscReg(MISCREG_TTBR0_EL1);
|
||||
asid = bits(ttbr_asid,
|
||||
(haveLargeAsid64 && ttbcr.as) ? 63 : 55, 48);
|
||||
|
||||
}
|
||||
break;
|
||||
case EL1:
|
||||
{
|
||||
sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1);
|
||||
@@ -1359,7 +1399,16 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
|
||||
case EL2:
|
||||
sctlr = tc->readMiscReg(MISCREG_SCTLR_EL2);
|
||||
ttbcr = tc->readMiscReg(MISCREG_TCR_EL2);
|
||||
asid = -1;
|
||||
if (hcr.e2h == 1) {
|
||||
// VHE code for EL2&0 regime
|
||||
uint64_t ttbr_asid = ttbcr.a1 ?
|
||||
tc->readMiscReg(MISCREG_TTBR1_EL2) :
|
||||
tc->readMiscReg(MISCREG_TTBR0_EL2);
|
||||
asid = bits(ttbr_asid,
|
||||
(haveLargeAsid64 && ttbcr.as) ? 63 : 55, 48);
|
||||
} else {
|
||||
asid = -1;
|
||||
}
|
||||
break;
|
||||
case EL3:
|
||||
sctlr = tc->readMiscReg(MISCREG_SCTLR_EL3);
|
||||
@@ -1367,25 +1416,39 @@ TLB::updateMiscReg(ThreadContext *tc, ArmTranslationType tranType)
|
||||
asid = -1;
|
||||
break;
|
||||
}
|
||||
hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
|
||||
scr = tc->readMiscReg(MISCREG_SCR_EL3);
|
||||
isPriv = aarch64EL != EL0;
|
||||
if (haveVirtualization) {
|
||||
vmid = bits(tc->readMiscReg(MISCREG_VTTBR_EL2), 55, 48);
|
||||
vmid = bits(tc->readMiscReg(MISCREG_VTTBR_EL2), 55, 48);
|
||||
isHyp = aarch64EL == EL2;
|
||||
isHyp |= tranType & HypMode;
|
||||
isHyp &= (tranType & S1S2NsTran) == 0;
|
||||
isHyp &= (tranType & S1CTran) == 0;
|
||||
|
||||
if (hcr.e2h == 1 && (aarch64EL == EL2
|
||||
|| (hcr.tge ==1 && aarch64EL == EL0))) {
|
||||
isHyp = true;
|
||||
directToStage2 = false;
|
||||
stage2Req = false;
|
||||
stage2DescReq = false;
|
||||
} else {
|
||||
// Work out if we should skip the first stage of translation and go
|
||||
// directly to stage 2. This value is cached so we don't have to
|
||||
// compute it for every translation.
|
||||
stage2Req = isStage2 ||
|
||||
(hcr.vm && !isHyp && !isSecure &&
|
||||
!(tranType & S1CTran) && (aarch64EL < EL2) &&
|
||||
!(tranType & S1E1Tran)); // <--- FIX THIS HACK
|
||||
stage2DescReq = isStage2 || (hcr.vm && !isHyp && !isSecure &&
|
||||
(aarch64EL < EL2));
|
||||
directToStage2 = !isStage2 && stage2Req && !sctlr.m;
|
||||
bool vm = hcr.vm;
|
||||
if (HaveVirtHostExt(tc) && hcr.e2h == 1 && hcr.tge == 1) {
|
||||
vm = 0;
|
||||
}
|
||||
|
||||
stage2Req = isStage2 ||
|
||||
(vm && !isHyp && !isSecure &&
|
||||
!(tranType & S1CTran) && (aarch64EL < EL2) &&
|
||||
!(tranType & S1E1Tran)); // <--- FIX THIS HACK
|
||||
stage2DescReq = isStage2 || (vm && !isHyp && !isSecure &&
|
||||
(aarch64EL < EL2));
|
||||
directToStage2 = !isStage2 && stage2Req && !sctlr.m;
|
||||
}
|
||||
} else {
|
||||
vmid = 0;
|
||||
isHyp = false;
|
||||
@@ -1499,7 +1562,8 @@ TLB::getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode,
|
||||
} else {
|
||||
vaddr = vaddr_tainted;
|
||||
}
|
||||
*te = lookup(vaddr, asid, vmid, isHyp, is_secure, false, false, target_el);
|
||||
*te = lookup(vaddr, asid, vmid, isHyp, is_secure, false, false, target_el,
|
||||
false);
|
||||
if (*te == NULL) {
|
||||
if (req->isPrefetch()) {
|
||||
// if the request is a prefetch don't attempt to fill the TLB or go
|
||||
@@ -1530,7 +1594,8 @@ TLB::getTE(TlbEntry **te, const RequestPtr &req, ThreadContext *tc, Mode mode,
|
||||
return fault;
|
||||
}
|
||||
|
||||
*te = lookup(vaddr, asid, vmid, isHyp, is_secure, false, false, target_el);
|
||||
*te = lookup(vaddr, asid, vmid, isHyp, is_secure, false, false,
|
||||
target_el, false);
|
||||
if (!*te)
|
||||
printTlb();
|
||||
assert(*te);
|
||||
|
||||
@@ -206,7 +206,8 @@ class TLB : public BaseTLB
|
||||
*/
|
||||
TlbEntry *lookup(Addr vpn, uint16_t asn, uint8_t vmid, bool hyp,
|
||||
bool secure, bool functional,
|
||||
bool ignore_asn, ExceptionLevel target_el);
|
||||
bool ignore_asn, ExceptionLevel target_el,
|
||||
bool in_host);
|
||||
|
||||
virtual ~TLB();
|
||||
|
||||
@@ -246,7 +247,7 @@ class TLB : public BaseTLB
|
||||
* @param secure_lookup if the operation affects the secure world
|
||||
*/
|
||||
void flushAllSecurity(bool secure_lookup, ExceptionLevel target_el,
|
||||
bool ignore_el = false);
|
||||
bool ignore_el = false, bool in_host = false);
|
||||
|
||||
/** Remove all entries in the non secure world, depending on whether they
|
||||
* were allocated in hyp mode or not
|
||||
@@ -259,8 +260,8 @@ class TLB : public BaseTLB
|
||||
*/
|
||||
void flushAll() override
|
||||
{
|
||||
flushAllSecurity(false, EL0, true);
|
||||
flushAllSecurity(true, EL0, true);
|
||||
flushAllSecurity(false, EL0, true, false);
|
||||
flushAllSecurity(true, EL0, true, false);
|
||||
}
|
||||
|
||||
/** Remove any entries that match both a va and asn
|
||||
@@ -269,20 +270,21 @@ class TLB : public BaseTLB
|
||||
* @param secure_lookup if the operation affects the secure world
|
||||
*/
|
||||
void flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup,
|
||||
ExceptionLevel target_el);
|
||||
ExceptionLevel target_el, bool in_host = false);
|
||||
|
||||
/** Remove any entries that match the asn
|
||||
* @param asn contextid/asn to flush on match
|
||||
* @param secure_lookup if the operation affects the secure world
|
||||
*/
|
||||
void flushAsid(uint64_t asn, bool secure_lookup,
|
||||
ExceptionLevel target_el);
|
||||
ExceptionLevel target_el, bool in_host = false);
|
||||
|
||||
/** Remove all entries that match the va regardless of asn
|
||||
* @param mva address to flush from cache
|
||||
* @param secure_lookup if the operation affects the secure world
|
||||
*/
|
||||
void flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el);
|
||||
void flushMva(Addr mva, bool secure_lookup, ExceptionLevel target_el,
|
||||
bool in_host = false);
|
||||
|
||||
/**
|
||||
* Invalidate all entries in the stage 2 TLB that match the given ipa
|
||||
@@ -447,9 +449,11 @@ private:
|
||||
* @param asn contextid/asn to flush on match
|
||||
* @param secure_lookup if the operation affects the secure world
|
||||
* @param ignore_asn if the flush should ignore the asn
|
||||
* @param in_host if hcr.e2h == 1 and hcr.tge == 1 for VHE.
|
||||
*/
|
||||
void _flushMva(Addr mva, uint64_t asn, bool secure_lookup,
|
||||
bool ignore_asn, ExceptionLevel target_el);
|
||||
bool ignore_asn, ExceptionLevel target_el,
|
||||
bool in_host);
|
||||
|
||||
public: /* Testing */
|
||||
Fault testTranslation(const RequestPtr &req, Mode mode,
|
||||
|
||||
@@ -45,16 +45,18 @@ namespace ArmISA {
|
||||
void
|
||||
TLBIALL::operator()(ThreadContext* tc)
|
||||
{
|
||||
getITBPtr(tc)->flushAllSecurity(secureLookup, targetEL);
|
||||
getDTBPtr(tc)->flushAllSecurity(secureLookup, targetEL);
|
||||
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
bool in_host = (hcr.tge == 1 && hcr.e2h == 1);
|
||||
getITBPtr(tc)->flushAllSecurity(secureLookup, targetEL, in_host);
|
||||
getDTBPtr(tc)->flushAllSecurity(secureLookup, targetEL, in_host);
|
||||
|
||||
// If CheckerCPU is connected, need to notify it of a flush
|
||||
CheckerCPU *checker = tc->getCheckerCpuPtr();
|
||||
if (checker) {
|
||||
getITBPtr(checker)->flushAllSecurity(secureLookup,
|
||||
targetEL);
|
||||
targetEL, in_host);
|
||||
getDTBPtr(checker)->flushAllSecurity(secureLookup,
|
||||
targetEL);
|
||||
targetEL, in_host);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,12 +75,14 @@ DTLBIALL::operator()(ThreadContext* tc)
|
||||
void
|
||||
TLBIASID::operator()(ThreadContext* tc)
|
||||
{
|
||||
getITBPtr(tc)->flushAsid(asid, secureLookup, targetEL);
|
||||
getDTBPtr(tc)->flushAsid(asid, secureLookup, targetEL);
|
||||
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
bool in_host = (hcr.tge == 1 && hcr.e2h == 1);
|
||||
getITBPtr(tc)->flushAsid(asid, secureLookup, targetEL, in_host);
|
||||
getDTBPtr(tc)->flushAsid(asid, secureLookup, targetEL, in_host);
|
||||
CheckerCPU *checker = tc->getCheckerCpuPtr();
|
||||
if (checker) {
|
||||
getITBPtr(checker)->flushAsid(asid, secureLookup, targetEL);
|
||||
getDTBPtr(checker)->flushAsid(asid, secureLookup, targetEL);
|
||||
getITBPtr(checker)->flushAsid(asid, secureLookup, targetEL, in_host);
|
||||
getDTBPtr(checker)->flushAsid(asid, secureLookup, targetEL, in_host);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,30 +114,34 @@ TLBIALLN::operator()(ThreadContext* tc)
|
||||
void
|
||||
TLBIMVAA::operator()(ThreadContext* tc)
|
||||
{
|
||||
getITBPtr(tc)->flushMva(addr, secureLookup, targetEL);
|
||||
getDTBPtr(tc)->flushMva(addr, secureLookup, targetEL);
|
||||
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
bool in_host = (hcr.tge == 1 && hcr.e2h == 1);
|
||||
getITBPtr(tc)->flushMva(addr, secureLookup, targetEL, in_host);
|
||||
getDTBPtr(tc)->flushMva(addr, secureLookup, targetEL, in_host);
|
||||
|
||||
CheckerCPU *checker = tc->getCheckerCpuPtr();
|
||||
if (checker) {
|
||||
getITBPtr(checker)->flushMva(addr, secureLookup, targetEL);
|
||||
getDTBPtr(checker)->flushMva(addr, secureLookup, targetEL);
|
||||
getITBPtr(checker)->flushMva(addr, secureLookup, targetEL, in_host);
|
||||
getDTBPtr(checker)->flushMva(addr, secureLookup, targetEL, in_host);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TLBIMVA::operator()(ThreadContext* tc)
|
||||
{
|
||||
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
bool in_host = (hcr.tge == 1 && hcr.e2h == 1);
|
||||
getITBPtr(tc)->flushMvaAsid(addr, asid,
|
||||
secureLookup, targetEL);
|
||||
secureLookup, targetEL, in_host);
|
||||
getDTBPtr(tc)->flushMvaAsid(addr, asid,
|
||||
secureLookup, targetEL);
|
||||
secureLookup, targetEL, in_host);
|
||||
|
||||
CheckerCPU *checker = tc->getCheckerCpuPtr();
|
||||
if (checker) {
|
||||
getITBPtr(checker)->flushMvaAsid(
|
||||
addr, asid, secureLookup, targetEL);
|
||||
addr, asid, secureLookup, targetEL, in_host);
|
||||
getDTBPtr(checker)->flushMvaAsid(
|
||||
addr, asid, secureLookup, targetEL);
|
||||
addr, asid, secureLookup, targetEL, in_host);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -327,7 +327,7 @@ s1TranslationRegime(ThreadContext* tc, ExceptionLevel el)
|
||||
return el;
|
||||
else if (ArmSystem::haveEL(tc, EL3) && ELIs32(tc, EL3) && scr.ns == 0)
|
||||
return EL3;
|
||||
else if (ArmSystem::haveVirtualization(tc) && ELIsInHost(tc, el))
|
||||
else if (HaveVirtHostExt(tc) && ELIsInHost(tc, el))
|
||||
return EL2;
|
||||
else
|
||||
return EL1;
|
||||
@@ -380,7 +380,8 @@ bool
|
||||
ELIsInHost(ThreadContext *tc, ExceptionLevel el)
|
||||
{
|
||||
const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
return ((IsSecureEL2Enabled(tc) || !isSecureBelowEL3(tc)) &&
|
||||
return (ArmSystem::haveEL(tc, EL2) &&
|
||||
(IsSecureEL2Enabled(tc) || !isSecureBelowEL3(tc)) &&
|
||||
HaveVirtHostExt(tc) && !ELIs32(tc, EL2) && hcr.e2h == 1 &&
|
||||
(el == EL2 || (el == EL0 && hcr.tge == 1)));
|
||||
}
|
||||
@@ -416,9 +417,12 @@ ELStateUsingAArch32K(ThreadContext *tc, ExceptionLevel el, bool secure)
|
||||
bool aarch32_below_el3 = (have_el3 && scr.rw == 0);
|
||||
|
||||
HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
bool secEL2 = false;
|
||||
bool aarch32_at_el1 = (aarch32_below_el3
|
||||
|| (have_el2
|
||||
&& !secure && hcr.rw == 0));
|
||||
|| (have_el2
|
||||
&& (secEL2 || !isSecureBelowEL3(tc))
|
||||
&& hcr.rw == 0 && !(hcr.e2h && hcr.tge
|
||||
&& HaveVirtHostExt(tc))));
|
||||
|
||||
// Only know if EL0 using AArch32 from PSTATE
|
||||
if (el == EL0 && !aarch32_at_el1) {
|
||||
@@ -497,7 +501,7 @@ computeAddrTop(ThreadContext *tc, bool selbit, bool isInstr,
|
||||
case EL2:
|
||||
{
|
||||
TCR tcr = tc->readMiscReg(MISCREG_TCR_EL2);
|
||||
if (ArmSystem::haveVirtualization(tc) && ELIsInHost(tc, el)) {
|
||||
if (HaveVirtHostExt(tc) && ELIsInHost(tc, el)) {
|
||||
tbi = selbit? tcr.tbi1 : tcr.tbi0;
|
||||
tbid = selbit? tcr.tbid1 : tcr.tbid0;
|
||||
} else {
|
||||
@@ -526,7 +530,6 @@ purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el,
|
||||
TCR tcr, bool isInstr)
|
||||
{
|
||||
bool selbit = bits(addr, 55);
|
||||
// TCR tcr = tc->readMiscReg(MISCREG_TCR_EL1);
|
||||
int topbit = computeAddrTop(tc, selbit, isInstr, tcr, el);
|
||||
|
||||
if (topbit == 63) {
|
||||
@@ -1304,9 +1307,28 @@ decodeMrsMsrBankedReg(uint8_t sysM, bool r, bool &isIntReg, int ®Idx,
|
||||
return (ok);
|
||||
}
|
||||
|
||||
bool
|
||||
isUnpriviledgeAccess(ThreadContext * tc)
|
||||
{
|
||||
const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
||||
// NV Extension not implemented yet
|
||||
bool have_nv_ext = false;
|
||||
bool unpriv_el1 = currEL(tc) == EL1 &&
|
||||
!(ArmSystem::haveVirtualization(tc) &&
|
||||
have_nv_ext && hcr.nv == 1 && hcr.nv1 == 1);
|
||||
bool unpriv_el2 = ArmSystem::haveEL(tc, EL2) && HaveVirtHostExt(tc) &&
|
||||
currEL(tc) == EL2 && hcr.e2h == 1 && hcr.tge == 1;
|
||||
|
||||
// User Access override, or UAO not implemented yet.
|
||||
bool user_access_override = false;
|
||||
return (unpriv_el1 || unpriv_el2) && !user_access_override;
|
||||
}
|
||||
|
||||
bool
|
||||
SPAlignmentCheckEnabled(ThreadContext* tc)
|
||||
{
|
||||
ExceptionLevel regime = s1TranslationRegime(tc, currEL(tc));
|
||||
|
||||
switch (currEL(tc)) {
|
||||
case EL3:
|
||||
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).sa;
|
||||
@@ -1315,7 +1337,11 @@ SPAlignmentCheckEnabled(ThreadContext* tc)
|
||||
case EL1:
|
||||
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa;
|
||||
case EL0:
|
||||
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa0;
|
||||
{
|
||||
SCTLR sc = (regime == EL2) ? tc->readMiscReg(MISCREG_SCTLR_EL2):
|
||||
tc->readMiscReg(MISCREG_SCTLR_EL1);
|
||||
return sc.sa0;
|
||||
}
|
||||
default:
|
||||
panic("Invalid exception level");
|
||||
break;
|
||||
|
||||
@@ -450,6 +450,7 @@ inline ByteOrder byteOrder(const ThreadContext *tc)
|
||||
return isBigEndian64(tc) ? BigEndianByteOrder : LittleEndianByteOrder;
|
||||
};
|
||||
|
||||
}
|
||||
bool isUnpriviledgeAccess(ThreadContext * tc);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user