summaryrefslogtreecommitdiff
path: root/src/arch/arm/insts
diff options
context:
space:
mode:
authorGiacomo Travaglini <giacomo.travaglini@arm.com>2018-10-24 13:34:25 +0100
committerGiacomo Travaglini <giacomo.travaglini@arm.com>2018-10-26 09:45:47 +0000
commit68bc5397c937c7289ad7e78416132dc77ccf34a9 (patch)
treebe3918bf7b1688f1ad6779637f24d57d152b9d30 /src/arch/arm/insts
parent16860301e804af0051a83f84c084b9e4c11eacb4 (diff)
downloadgem5-68bc5397c937c7289ad7e78416132dc77ccf34a9.tar.xz
arch-arm: Refactor AArch64 MSR/MRS trapping
This patch refactors AArch64 MSR/MRS trapping, by moving the trapping helpers in arch/arm/utility and in the isa code into a MiscRegOp64 class. This class is 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. What do we gain? 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. Change-Id: I0924354db100de04f1079a1ab43d4fd32039e08d Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/13778 Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
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)
{}