diff options
-rw-r--r-- | src/arch/arm/insts/pseudo.cc | 40 | ||||
-rw-r--r-- | src/arch/arm/insts/pseudo.hh | 21 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/misc.isa | 7 | ||||
-rw-r--r-- | src/arch/arm/miscregs.cc | 21 | ||||
-rw-r--r-- | src/arch/arm/miscregs.hh | 10 |
5 files changed, 88 insertions, 11 deletions
diff --git a/src/arch/arm/insts/pseudo.cc b/src/arch/arm/insts/pseudo.cc index 40e00accf..e2504d61e 100644 --- a/src/arch/arm/insts/pseudo.cc +++ b/src/arch/arm/insts/pseudo.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014,2016-2017 ARM Limited + * Copyright (c) 2014,2016-2018 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -181,10 +181,8 @@ WarnUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab) const fullMnemonic.size() ? fullMnemonic.c_str() : mnemonic); } - - McrMrcMiscInst::McrMrcMiscInst(const char *_mnemonic, ExtMachInst _machInst, - uint64_t _iss, MiscRegIndex _miscReg) + uint64_t _iss, MiscRegIndex _miscReg) : ArmStaticInst(_mnemonic, _machInst, No_OpClass) { flags[IsNonSpeculative] = true; @@ -217,3 +215,37 @@ McrMrcMiscInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const { return csprintf("%-10s (pipe flush)", mnemonic); } + +McrMrcImplDefined::McrMrcImplDefined(const char *_mnemonic, + ExtMachInst _machInst, uint64_t _iss, + MiscRegIndex _miscReg) + : McrMrcMiscInst(_mnemonic, _machInst, _iss, _miscReg) +{} + +Fault +McrMrcImplDefined::execute(ExecContext *xc, Trace::InstRecord *traceData) const +{ + uint32_t cpsr = xc->readMiscReg(MISCREG_CPSR); + uint32_t hcr = xc->readMiscReg(MISCREG_HCR); + uint32_t scr = xc->readMiscReg(MISCREG_SCR); + uint32_t hdcr = xc->readMiscReg(MISCREG_HDCR); + uint32_t hstr = xc->readMiscReg(MISCREG_HSTR); + uint32_t hcptr = xc->readMiscReg(MISCREG_HCPTR); + + bool hypTrap = mcrMrc15TrapToHyp(miscReg, hcr, cpsr, scr, hdcr, hstr, + hcptr, iss); + if (hypTrap) { + return std::make_shared<HypervisorTrap>(machInst, iss, + EC_TRAPPED_CP15_MCR_MRC); + } else { + return std::make_shared<UndefinedInstruction>(machInst, false, + mnemonic); + } +} + +std::string +McrMrcImplDefined::generateDisassembly(Addr pc, + const SymbolTable *symtab) const +{ + return csprintf("%-10s (implementation defined)", mnemonic); +} diff --git a/src/arch/arm/insts/pseudo.hh b/src/arch/arm/insts/pseudo.hh index fe28789f0..5fb7499df 100644 --- a/src/arch/arm/insts/pseudo.hh +++ b/src/arch/arm/insts/pseudo.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014,2016 ARM Limited + * Copyright (c) 2014,2016,2018 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -123,7 +123,7 @@ class WarnUnimplemented : public ArmStaticInst */ class McrMrcMiscInst : public ArmStaticInst { - private: + protected: uint64_t iss; MiscRegIndex miscReg; @@ -138,4 +138,21 @@ class McrMrcMiscInst : public ArmStaticInst }; +/** + * This class is also used for IMPLEMENTATION DEFINED registers, whose mcr/mrc + * behaviour is trappable even for unimplemented registers. + */ +class McrMrcImplDefined : public McrMrcMiscInst +{ + public: + McrMrcImplDefined(const char *_mnemonic, ExtMachInst _machInst, + uint64_t _iss, MiscRegIndex _miscReg); + + Fault execute(ExecContext *xc, Trace::InstRecord *traceData) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + +}; + #endif diff --git a/src/arch/arm/isa/formats/misc.isa b/src/arch/arm/isa/formats/misc.isa index 4f834b8e1..a9acc21af 100644 --- a/src/arch/arm/isa/formats/misc.isa +++ b/src/arch/arm/isa/formats/misc.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// Copyright (c) 2010-2013,2016-2017 ARM Limited +// Copyright (c) 2010-2013,2016-2018 ARM Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -219,6 +219,11 @@ let {{ machInst, csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s unknown", crn, opc1, crm, opc2, isRead ? "read" : "write")); + case MISCREG_IMPDEF_UNIMPL: + return new McrMrcImplDefined( + isRead ? "mrc implementation defined" : + "mcr implementation defined", + machInst, iss, MISCREG_IMPDEF_UNIMPL); case MISCREG_CP15ISB: return new Isb(machInst, iss); case MISCREG_CP15DSB: diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc index c0b6aa5d5..7d5441ca8 100644 --- a/src/arch/arm/miscregs.cc +++ b/src/arch/arm/miscregs.cc @@ -502,6 +502,19 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2) } break; case 9: + // Every cop register with CRn = 9 and CRm in + // {0-2}, {5-8} is implementation defined regardless + // of opc1 and opc2. + switch (crm) { + case 0: + case 1: + case 2: + case 5: + case 6: + case 7: + case 8: + return MISCREG_IMPDEF_UNIMPL; + } if (opc1 == 0) { switch (crm) { case 12: @@ -565,7 +578,9 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2) case 10: if (opc1 == 0) { // crm 0, 1, 4, and 8, with op2 0 - 7, reserved for TLB lockdown - if (crm == 2) { // TEX Remap Registers + if (crm < 2) { + return MISCREG_IMPDEF_UNIMPL; + } else if (crm == 2) { // TEX Remap Registers if (opc2 == 0) { // Selector is TTBCR.EAE return MISCREG_PRRR_MAIR0; @@ -609,6 +624,8 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2) case 8: case 15: // Reserved for DMA operations for TCM access + return MISCREG_IMPDEF_UNIMPL; + default: break; } } @@ -689,7 +706,7 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2) break; case 15: // Implementation defined - return MISCREG_CP15_UNIMPL; + return MISCREG_IMPDEF_UNIMPL; } // Unrecognized register return MISCREG_CP15_UNIMPL; diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh index cb4dcab8c..9bca3d116 100644 --- a/src/arch/arm/miscregs.hh +++ b/src/arch/arm/miscregs.hh @@ -677,7 +677,7 @@ namespace ArmISA // NUM_PHYS_MISCREGS specifies the number of actual physical // registers, not considering the following pseudo-registers - // (dummy registers), like UNKNOWN, CP15_UNIMPL... + // (dummy registers), like UNKNOWN, CP15_UNIMPL, MISCREG_IMPDEF_UNIMPL. // Checkpointing should use this physical index when // saving/restoring register values. NUM_PHYS_MISCREGS = 606, // 606 @@ -690,6 +690,11 @@ namespace ArmISA MISCREG_A64_UNIMPL, MISCREG_UNKNOWN, + // Implementation defined register: this represent + // a pool of unimplemented registers whose access can throw + // either UNDEFINED or hypervisor trap exception. + MISCREG_IMPDEF_UNIMPL, + // Total number of Misc Registers: Physical + Dummy NUM_MISCREGS }; @@ -1380,7 +1385,8 @@ namespace ArmISA "cp14_unimpl", "cp15_unimpl", "a64_unimpl", - "unknown" + "unknown", + "impl_defined" }; static_assert(sizeof(miscRegName) / sizeof(*miscRegName) == NUM_MISCREGS, |