83a84,309
> Fault
> MiscRegOp64::trap(ThreadContext *tc, MiscRegIndex misc_reg,
> ExceptionLevel el, uint32_t immediate) const
> {
> bool is_vfp_neon = false;
>
> // Check for traps to supervisor (FP/SIMD regs)
> if (el <= EL1 && checkEL1Trap(tc, misc_reg, el)) {
>
> return std::make_shared<SupervisorTrap>(machInst, 0x1E00000,
> EC_TRAPPED_SIMD_FP);
> }
>
> // Check for traps to hypervisor
> if ((ArmSystem::haveVirtualization(tc) && el <= EL2) &&
> checkEL2Trap(tc, misc_reg, el, &is_vfp_neon)) {
>
> return std::make_shared<HypervisorTrap>(
> machInst, is_vfp_neon ? 0x1E00000 : immediate,
> is_vfp_neon ? EC_TRAPPED_SIMD_FP : EC_TRAPPED_MSR_MRS_64);
> }
>
> // Check for traps to secure monitor
> if ((ArmSystem::haveSecurity(tc) && el <= EL3) &&
> checkEL3Trap(tc, misc_reg, el, &is_vfp_neon)) {
>
> return std::make_shared<SecureMonitorTrap>(
> machInst,
> is_vfp_neon ? 0x1E00000 : immediate,
> is_vfp_neon ? EC_TRAPPED_SIMD_FP : EC_TRAPPED_MSR_MRS_64);
> }
>
> return NoFault;
> }
>
> bool
> MiscRegOp64::checkEL1Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
> ExceptionLevel el) const
> {
> const CPACR cpacr = tc->readMiscReg(MISCREG_CPACR_EL1);
>
> bool trap_to_sup = false;
> switch (misc_reg) {
> case MISCREG_FPCR:
> case MISCREG_FPSR:
> case MISCREG_FPEXC32_EL2:
> if ((el == EL0 && cpacr.fpen != 0x3) ||
> (el == EL1 && !(cpacr.fpen & 0x1)))
> trap_to_sup = true;
> break;
> default:
> break;
> }
> return trap_to_sup;
> }
>
> bool
> MiscRegOp64::checkEL2Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
> ExceptionLevel el, bool * is_vfp_neon) const
> {
> const CPTR cptr = tc->readMiscReg(MISCREG_CPTR_EL2);
> const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
> const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
> const CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
>
> bool trap_to_hyp = false;
> *is_vfp_neon = 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;
> *is_vfp_neon = true;
> 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;
>
> // @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;
> default:
> break;
> }
> }
> return trap_to_hyp;
> }
>
> bool
> MiscRegOp64::checkEL3Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
> ExceptionLevel el, bool * is_vfp_neon) const
> {
> const CPTR cptr = tc->readMiscReg(MISCREG_CPTR_EL3);
>
> bool trap_to_mon = false;
> *is_vfp_neon = false;
>
> switch (misc_reg) {
> // FP/SIMD regs
> case MISCREG_FPCR:
> case MISCREG_FPSR:
> case MISCREG_FPEXC32_EL2:
> trap_to_mon = cptr.tfp;
> *is_vfp_neon = true;
> break;
> // CPACR, CPTR
> case MISCREG_CPACR_EL1:
> if (el == EL1 || el == EL2) {
> trap_to_mon = cptr.tcpac;
> }
> break;
> case MISCREG_CPTR_EL2:
> if (el == EL2) {
> trap_to_mon = cptr.tcpac;
> }
> break;
> default:
> break;
> }
> return trap_to_mon;
> }
>