arch-power: Add support for trapping user faults

This adds support for trapping into GDB when user-mode
faults such as those pertaining to alignment (SIGBUS),
traps (SIGTRAP) and unimplemented opcodes (SIGILL) are
encountered.

Change-Id: Ieb557abd4173b5acb4be6f0c30964aea1eba71a5
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/47359
Reviewed-by: Boris Shingarov <shingarov@labware.com>
Maintainer: Boris Shingarov <shingarov@labware.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/arch/power/SConscript b/src/arch/power/SConscript
index 720455c..52a607d 100644
--- a/src/arch/power/SConscript
+++ b/src/arch/power/SConscript
@@ -34,6 +34,7 @@
 # Scons bug id: 2006 M5 Bug id: 308
     Dir('isa/formats')
     Source('decoder.cc')
+    Source('faults.cc')
     Source('insts/branch.cc')
     Source('insts/mem.cc')
     Source('insts/integer.cc')
diff --git a/src/arch/power/faults.cc b/src/arch/power/faults.cc
new file mode 100644
index 0000000..3b8851e
--- /dev/null
+++ b/src/arch/power/faults.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 IBM Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/power/faults.hh"
+
+#include <csignal>
+
+#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
+
+namespace gem5
+{
+
+namespace PowerISA
+{
+
+void
+UnimplementedOpcodeFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    panic_if(tc->getSystemPtr()->trapToGdb(SIGILL, tc->contextId()),
+             "Unimplemented opcode encountered at virtual address %#x\n",
+             tc->pcState().pc());
+}
+
+void
+AlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    panic_if(!tc->getSystemPtr()->trapToGdb(SIGBUS, tc->contextId()),
+             "Alignment fault when accessing virtual address %#x\n", vaddr);
+}
+
+void
+TrapFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
+{
+    panic_if(tc->getSystemPtr()->trapToGdb(SIGTRAP, tc->contextId()),
+             "Trap encountered at virtual address %#x\n",
+             tc->pcState().pc());
+}
+
+} // namespace PowerISA
+
+} // namespace gem5
diff --git a/src/arch/power/faults.hh b/src/arch/power/faults.hh
index edfcc8f..03eeee7 100644
--- a/src/arch/power/faults.hh
+++ b/src/arch/power/faults.hh
@@ -63,6 +63,9 @@
         : PowerFault("Unimplemented Opcode")
     {
     }
+
+    void invoke(ThreadContext *tc, const StaticInstPtr &inst =
+                nullStaticInstPtr) override;
 };
 
 
@@ -78,11 +81,16 @@
 
 class AlignmentFault : public PowerFault
 {
+  private:
+    Addr vaddr;
   public:
-    AlignmentFault()
-        : PowerFault("Alignment")
+    AlignmentFault(Addr va)
+        : PowerFault("Alignment"), vaddr(va)
     {
     }
+
+    void invoke(ThreadContext *tc, const StaticInstPtr &inst =
+                nullStaticInstPtr) override;
 };
 
 
@@ -93,6 +101,9 @@
         : PowerFault("Trap")
     {
     }
+
+    void invoke(ThreadContext *tc, const StaticInstPtr &inst =
+                nullStaticInstPtr) override;
 };
 
 } // namespace PowerISA
diff --git a/src/arch/power/isa/formats/integer.isa b/src/arch/power/isa/formats/integer.isa
index 9c2804d..d54a124 100644
--- a/src/arch/power/isa/formats/integer.isa
+++ b/src/arch/power/isa/formats/integer.isa
@@ -575,7 +575,6 @@
     code  = 'int64_t src1 = ' + src1 + ';\n'
     code += 'int64_t src2 = ' + src2 + ';\n'
     code += 'if (checkTrap(src1, src2)) {\n'
-    code += '    panic("trap generated at %#x", xc->pcState().pc());\n'
     code += '    return std::make_shared<TrapFault>();\n'
     code += '}\n'
 
@@ -590,7 +589,6 @@
     # Add code to set up variables and check for a trap
     code  = 'int64_t src = ' + src + ';\n'
     code += 'if (checkTrap(src, si)) {\n'
-    code += '    panic("trap generated at %#x", xc->pcState().pc());\n'
     code += '    return std::make_shared<TrapFault>();\n'
     code += '}\n'
 
diff --git a/src/arch/power/isa/formats/unknown.isa b/src/arch/power/isa/formats/unknown.isa
index 31290d5..921700b 100644
--- a/src/arch/power/isa/formats/unknown.isa
+++ b/src/arch/power/isa/formats/unknown.isa
@@ -71,9 +71,9 @@
     Fault
     Unknown::execute(ExecContext *xc, Trace::InstRecord *traceData) const
     {
-        panic("attempt to execute unknown instruction at %#x"
-              "(inst 0x%08x, opcode 0x%x, binary: %s)",
-              xc->pcState().pc(), machInst, PO, inst2string(machInst));
+        inform("attempt to execute unknown instruction at %#x"
+               "(inst 0x%08x, opcode 0x%x, binary: %s)",
+               xc->pcState().pc(), machInst, PO, inst2string(machInst));
         return std::make_shared<UnimplementedOpcodeFault>();
     }
 }};
diff --git a/src/arch/power/tlb.cc b/src/arch/power/tlb.cc
index f559d59..4bca6f0 100644
--- a/src/arch/power/tlb.cc
+++ b/src/arch/power/tlb.cc
@@ -218,11 +218,13 @@
 Fault
 TLB::translateInst(const RequestPtr &req, ThreadContext *tc)
 {
+    Addr vaddr = req->getVaddr();
+
     // Instruction accesses must be word-aligned
-    if (req->getVaddr() & 0x3) {
-        DPRINTF(TLB, "Alignment Fault on %#x, size = %d\n", req->getVaddr(),
+    if (vaddr & 0x3) {
+        DPRINTF(TLB, "Alignment Fault on %#x, size = %d\n", vaddr,
                 req->getSize());
-        return std::make_shared<AlignmentFault>();
+        return std::make_shared<AlignmentFault>(vaddr);
     }
 
     return tc->getProcessPtr()->pTable->translate(req);