arch-arm: Add support for the brk instruction

Add support for software breakpoints as signalled by the aarch64 brk
instruction. This introduces a new SoftwareBreakpoint fault.

Change-Id: I93646c3298e09d7f7b0983108ba8937c7331297a
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/5721
Reviewed-by: Giacomo Gabrielli <Giacomo.Gabrielli@arm.com>
diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc
index ef9d05a..0293ee1 100644
--- a/src/arch/arm/faults.cc
+++ b/src/arch/arm/faults.cc
@@ -278,6 +278,11 @@
     "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
     0, 0, 0, 0, false, true,  true,  EC_SERROR, FaultStat()
 };
+template<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals = {
+    // Some dummy values (SoftwareBreakpoint is AArch64-only)
+    "Software Breakpoint",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
+    0, 0, 0, 0, true, false, false,  EC_SOFTWARE_BREAKPOINT, FaultStat()
+};
 template<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals = {
     // Some dummy values
     "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
@@ -1393,6 +1398,25 @@
     return toHyp;
 }
 
+
+SoftwareBreakpoint::SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss)
+    : ArmFaultVals<SoftwareBreakpoint>(_mach_inst, _iss)
+{}
+
+bool
+SoftwareBreakpoint::routeToHyp(ThreadContext *tc) const
+{
+    assert(from64);
+
+    const bool have_el2 = ArmSystem::haveVirtualization(tc);
+
+    const HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
+    const HDCR mdcr  = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
+
+    return have_el2 && !inSecureState(tc) && fromEL <= EL1 &&
+        (hcr.tge || mdcr.tde);
+}
+
 void
 ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
     DPRINTF(Faults, "Invoking ArmSev Fault\n");
@@ -1425,6 +1449,7 @@
 template class ArmFaultVals<PCAlignmentFault>;
 template class ArmFaultVals<SPAlignmentFault>;
 template class ArmFaultVals<SystemError>;
+template class ArmFaultVals<SoftwareBreakpoint>;
 template class ArmFaultVals<ArmSev>;
 template class AbortFault<PrefetchAbort>;
 template class AbortFault<DataAbort>;
diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh
index de5061b..8f86097 100644
--- a/src/arch/arm/faults.hh
+++ b/src/arch/arm/faults.hh
@@ -545,6 +545,15 @@
     bool routeToHyp(ThreadContext *tc) const override;
 };
 
+/// System error (AArch64 only)
+class SoftwareBreakpoint : public ArmFaultVals<SoftwareBreakpoint>
+{
+  public:
+    SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss);
+
+    bool routeToHyp(ThreadContext *tc) const override;
+};
+
 // A fault that flushes the pipe, excluding the faulting instructions
 class ArmSev : public ArmFaultVals<ArmSev>
 {
@@ -583,6 +592,7 @@
 template<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals;
 template<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals;
 template<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals;
+template<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals;
 template<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals;
 
 
diff --git a/src/arch/arm/isa/insts/misc64.isa b/src/arch/arm/isa/insts/misc64.isa
index 00724c0..dd6711e 100644
--- a/src/arch/arm/isa/insts/misc64.isa
+++ b/src/arch/arm/isa/insts/misc64.isa
@@ -1,6 +1,6 @@
 // -*- mode:c++ -*-
 
-// Copyright (c) 2011-2013, 2016 ARM Limited
+// Copyright (c) 2011-2013, 2016-2017 ARM Limited
 // All rights reserved
 //
 // The license below extends only to copyright in the software and shall
@@ -162,4 +162,16 @@
     header_output += BasicDeclare.subst(clrexIop)
     decoder_output += BasicConstructor64.subst(clrexIop)
     exec_output += BasicExecute.subst(clrexIop)
+
+
+    brkCode = '''
+    fault = std::make_shared<SoftwareBreakpoint>(machInst,
+                                                 bits(machInst, 20, 5));
+    '''
+
+    brkIop = InstObjParams("brk", "Brk64", "ArmStaticInst",
+                           brkCode, ["IsSerializeAfter"])
+    header_output += BasicDeclare.subst(brkIop)
+    decoder_output += BasicConstructor64.subst(brkIop)
+    exec_output += BasicExecute.subst(brkIop)
 }};
diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh
index 9fd945a..3072581 100644
--- a/src/arch/arm/types.hh
+++ b/src/arch/arm/types.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012-2013 ARM Limited
+ * Copyright (c) 2010, 2012-2013, 2017 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -621,7 +621,8 @@
         EC_STACK_PTR_ALIGNMENT     = 0x26,
         EC_FP_EXCEPTION            = 0x28,
         EC_FP_EXCEPTION_64         = 0x2C,
-        EC_SERROR                  = 0x2F
+        EC_SERROR                  = 0x2F,
+        EC_SOFTWARE_BREAKPOINT     = 0x38,
     };
 
     /**