diff options
Diffstat (limited to 'src/arch/arm/insts')
-rw-r--r-- | src/arch/arm/insts/mem64.hh | 8 | ||||
-rw-r--r-- | src/arch/arm/insts/misc64.cc | 226 | ||||
-rw-r--r-- | src/arch/arm/insts/misc64.hh | 44 |
3 files changed, 271 insertions, 7 deletions
diff --git a/src/arch/arm/insts/mem64.hh b/src/arch/arm/insts/mem64.hh index 4f662831d..8e21bb3b6 100644 --- a/src/arch/arm/insts/mem64.hh +++ b/src/arch/arm/insts/mem64.hh @@ -39,12 +39,13 @@ #ifndef __ARCH_ARM_MEM64_HH__ #define __ARCH_ARM_MEM64_HH__ +#include "arch/arm/insts/misc64.hh" #include "arch/arm/insts/static_inst.hh" namespace ArmISA { -class SysDC64 : public ArmStaticInst +class SysDC64 : public MiscRegOp64 { protected: IntRegIndex base; @@ -53,9 +54,10 @@ class SysDC64 : public ArmStaticInst SysDC64(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _base, MiscRegIndex miscReg, uint64_t _imm) - : ArmStaticInst(mnem, _machInst, __opClass), base(_base), - dest((IntRegIndex)miscReg), imm(_imm) + : MiscRegOp64(mnem, _machInst, __opClass, false), + base(_base), dest((IntRegIndex)miscReg), imm(_imm) {} + std::string generateDisassembly( Addr pc, const SymbolTable *symtab) const override; }; diff --git a/src/arch/arm/insts/misc64.cc b/src/arch/arm/insts/misc64.cc index 5bdf6cb94..b2761e76c 100644 --- a/src/arch/arm/insts/misc64.cc +++ b/src/arch/arm/insts/misc64.cc @@ -81,6 +81,232 @@ UnknownOp64::generateDisassembly(Addr pc, const SymbolTable *symtab) const return csprintf("%-10s (inst %#08x)", "unknown", machInst & mask(32)); } +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; +} + std::string MiscRegRegImmOp64::generateDisassembly( Addr pc, const SymbolTable *symtab) const diff --git a/src/arch/arm/insts/misc64.hh b/src/arch/arm/insts/misc64.hh index 961df65d8..8af488a02 100644 --- a/src/arch/arm/insts/misc64.hh +++ b/src/arch/arm/insts/misc64.hh @@ -106,7 +106,43 @@ class UnknownOp64 : public ArmStaticInst Addr pc, const SymbolTable *symtab) const override; }; -class MiscRegRegImmOp64 : public ArmStaticInst +/** + * This class is implementing the Base class for a generic AArch64 + * instruction which is making use of system registers (MiscReg), like + * MSR,MRS,SYS. The common denominator or those instruction is the + * chance that the system register access is trapped to an upper + * Exception level. MiscRegOp64 is providing that feature. Other + * "pseudo" instructions, like access to implementation defined + * registers can inherit from this class to make use of the trapping + * functionalities even if there is no data movement between GPRs and + * system register. + */ +class MiscRegOp64 : public ArmStaticInst +{ + protected: + bool miscRead; + + MiscRegOp64(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, bool misc_read) : + ArmStaticInst(mnem, _machInst, __opClass), + miscRead(misc_read) + {} + + Fault trap(ThreadContext *tc, MiscRegIndex misc_reg, + ExceptionLevel el, uint32_t immediate) const; + private: + bool checkEL1Trap(ThreadContext *tc, const MiscRegIndex misc_reg, + ExceptionLevel el) const; + + bool checkEL2Trap(ThreadContext *tc, const MiscRegIndex misc_reg, + ExceptionLevel el, bool *is_vfp_neon) const; + + bool checkEL3Trap(ThreadContext *tc, const MiscRegIndex misc_reg, + ExceptionLevel el, bool *is_vfp_neon) const; + +}; + +class MiscRegRegImmOp64 : public MiscRegOp64 { protected: MiscRegIndex dest; @@ -116,7 +152,7 @@ class MiscRegRegImmOp64 : public ArmStaticInst MiscRegRegImmOp64(const char *mnem, ExtMachInst _machInst, OpClass __opClass, MiscRegIndex _dest, IntRegIndex _op1, uint32_t _imm) : - ArmStaticInst(mnem, _machInst, __opClass), + MiscRegOp64(mnem, _machInst, __opClass, false), dest(_dest), op1(_op1), imm(_imm) {} @@ -124,7 +160,7 @@ class MiscRegRegImmOp64 : public ArmStaticInst Addr pc, const SymbolTable *symtab) const override; }; -class RegMiscRegImmOp64 : public ArmStaticInst +class RegMiscRegImmOp64 : public MiscRegOp64 { protected: IntRegIndex dest; @@ -134,7 +170,7 @@ class RegMiscRegImmOp64 : public ArmStaticInst RegMiscRegImmOp64(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _dest, MiscRegIndex _op1, uint32_t _imm) : - ArmStaticInst(mnem, _machInst, __opClass), + MiscRegOp64(mnem, _machInst, __opClass, true), dest(_dest), op1(_op1), imm(_imm) {} |