summaryrefslogtreecommitdiff
path: root/src/arch/arm/insts
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm/insts')
-rw-r--r--src/arch/arm/insts/mem64.hh8
-rw-r--r--src/arch/arm/insts/misc64.cc226
-rw-r--r--src/arch/arm/insts/misc64.hh44
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)
{}