mem-cache: Add multiple eviction stats
[gem5.git] / src / arch / arm / remote_gdb.cc
index b85b453694a9839cd7186e5a4b4a89732ef3e2b1..ceb0ffafe9cb189e1c813738753043bb5e6810f5 100644 (file)
@@ -1,6 +1,7 @@
 /*
+ * Copyright 2015 LabWare
  * Copyright 2014 Google Inc.
- * Copyright (c) 2010, 2013 ARM Limited
+ * Copyright (c) 2010, 2013, 2016, 2018-2019 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -40,6 +41,7 @@
  *
  * Authors: Nathan Binkert
  *          William Wang
+ *          Boris Shingarov
  */
 
 /*
  * "Stub" to allow remote cpu to debug over a serial line using gdb.
  */
 
+#include "arch/arm/remote_gdb.hh"
+
 #include <sys/signal.h>
 #include <unistd.h>
 
 #include "arch/arm/decoder.hh"
 #include "arch/arm/pagetable.hh"
 #include "arch/arm/registers.hh"
-#include "arch/arm/remote_gdb.hh"
 #include "arch/arm/system.hh"
 #include "arch/arm/utility.hh"
 #include "arch/arm/vtophys.hh"
 #include "base/remote_gdb.hh"
 #include "base/socket.hh"
 #include "base/trace.hh"
+#include "blobs/gdb_xml_aarch64_core.hh"
+#include "blobs/gdb_xml_aarch64_fpu.hh"
+#include "blobs/gdb_xml_aarch64_target.hh"
+#include "blobs/gdb_xml_arm_core.hh"
+#include "blobs/gdb_xml_arm_target.hh"
+#include "blobs/gdb_xml_arm_vfpv3.hh"
 #include "cpu/static_inst.hh"
 #include "cpu/thread_context.hh"
 #include "cpu/thread_state.hh"
 using namespace std;
 using namespace ArmISA;
 
-RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc)
-    : BaseRemoteGDB(_system, tc, GDB_REG_BYTES)
+RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc, int _port)
+    : BaseRemoteGDB(_system, tc, _port), regCache32(this), regCache64(this)
 {
 }
 
@@ -174,7 +183,7 @@ RemoteGDB::acc(Addr va, size_t len)
 {
     if (FullSystem) {
         for (ChunkGenerator gen(va, len, PageBytes); !gen.done(); gen.next()) {
-            if (!virtvalid(context, gen.addr())) {
+            if (!virtvalid(context(), gen.addr())) {
                 DPRINTF(GDBAcc, "acc:   %#x mapping is invalid\n", va);
                 return false;
             }
@@ -183,142 +192,154 @@ RemoteGDB::acc(Addr va, size_t len)
         DPRINTF(GDBAcc, "acc:   %#x mapping is valid\n", va);
         return true;
     } else {
-        TlbEntry entry;
-        //Check to make sure the first byte is mapped into the processes address
-        //space.
-        if (context->getProcessPtr()->pTable->lookup(va, entry))
-            return true;
-        return false;
+        // Check to make sure the first byte is mapped into the processes
+        // address space.
+        return context()->getProcessPtr()->pTable->lookup(va) != nullptr;
     }
 }
 
-/*
- * Translate the kernel debugger register format into the GDB register
- * format.
- */
 void
-RemoteGDB::getregs()
+RemoteGDB::AArch64GdbRegCache::getRegs(ThreadContext *context)
 {
-    DPRINTF(GDBAcc, "getregs in remotegdb \n");
+    DPRINTF(GDBAcc, "getRegs in remotegdb \n");
 
-    memset(gdbregs.regs, 0, gdbregs.bytes());
+    for (int i = 0; i < 31; ++i)
+        r.x[i] = context->readIntReg(INTREG_X0 + i);
+    r.spx = context->readIntReg(INTREG_SPX);
+    r.pc = context->pcState().pc();
+    r.cpsr = context->readMiscRegNoEffect(MISCREG_CPSR);
 
-    if (inAArch64(context)) {  // AArch64
-        // x0-x30
-        for (int i = 0; i < 31; ++i)
-            gdbregs.regs64[GDB64_X0 + i] = context->readIntReg(INTREG_X0 + i);
-        gdbregs.regs64[GDB64_SPX] = context->readIntReg(INTREG_SPX);
-        // pc
-        gdbregs.regs64[GDB64_PC] = context->pcState().pc();
-        // cpsr
-        gdbregs.regs64[GDB64_CPSR] =
-            context->readMiscRegNoEffect(MISCREG_CPSR);
-        // v0-v31
-        for (int i = 0; i < 128; i += 4) {
-            int gdboff = GDB64_V0_32 + i;
-            gdbregs.regs32[gdboff + 0] = context->readFloatRegBits(i + 2);
-            gdbregs.regs32[gdboff + 1] = context->readFloatRegBits(i + 3);
-            gdbregs.regs32[gdboff + 2] = context->readFloatRegBits(i + 0);
-            gdbregs.regs32[gdboff + 3] = context->readFloatRegBits(i + 1);
+    size_t base = 0;
+    for (int i = 0; i < NumVecV8ArchRegs; i++) {
+        auto v = (context->readVecReg(RegId(VecRegClass, i))).as<VecElem>();
+        for (size_t j = 0; j < NumVecElemPerNeonVecReg; j++) {
+            r.v[base] = v[j];
+            base++;
         }
-    } else {  // AArch32
-        // R0-R15 supervisor mode
-        gdbregs.regs32[GDB32_R0 + 0] = context->readIntReg(INTREG_R0);
-        gdbregs.regs32[GDB32_R0 + 1] = context->readIntReg(INTREG_R1);
-        gdbregs.regs32[GDB32_R0 + 2] = context->readIntReg(INTREG_R2);
-        gdbregs.regs32[GDB32_R0 + 3] = context->readIntReg(INTREG_R3);
-        gdbregs.regs32[GDB32_R0 + 4] = context->readIntReg(INTREG_R4);
-        gdbregs.regs32[GDB32_R0 + 5] = context->readIntReg(INTREG_R5);
-        gdbregs.regs32[GDB32_R0 + 6] = context->readIntReg(INTREG_R6);
-        gdbregs.regs32[GDB32_R0 + 7] = context->readIntReg(INTREG_R7);
-        gdbregs.regs32[GDB32_R0 + 8] = context->readIntReg(INTREG_R8);
-        gdbregs.regs32[GDB32_R0 + 9] = context->readIntReg(INTREG_R9);
-        gdbregs.regs32[GDB32_R0 + 10] = context->readIntReg(INTREG_R10);
-        gdbregs.regs32[GDB32_R0 + 11] = context->readIntReg(INTREG_R11);
-        gdbregs.regs32[GDB32_R0 + 12] = context->readIntReg(INTREG_R12);
-        gdbregs.regs32[GDB32_R0 + 13] = context->readIntReg(INTREG_SP);
-        gdbregs.regs32[GDB32_R0 + 14] = context->readIntReg(INTREG_LR);
-        gdbregs.regs32[GDB32_R0 + 15] = context->pcState().pc();
+    }
+    r.fpsr = context->readMiscRegNoEffect(MISCREG_FPSR);
+    r.fpcr = context->readMiscRegNoEffect(MISCREG_FPCR);
+}
 
-        // CPSR
-        gdbregs.regs32[GDB32_CPSR] = context->readMiscRegNoEffect(MISCREG_CPSR);
+void
+RemoteGDB::AArch64GdbRegCache::setRegs(ThreadContext *context) const
+{
+    DPRINTF(GDBAcc, "setRegs in remotegdb \n");
 
-        // vfpv3/neon floating point registers (32 double or 64 float)
-        for (int i = 0; i < NumFloatV7ArchRegs; ++i)
-            gdbregs.regs32[GDB32_F0 + i] = context->readFloatRegBits(i);
+    for (int i = 0; i < 31; ++i)
+        context->setIntReg(INTREG_X0 + i, r.x[i]);
+    auto pc_state = context->pcState();
+    pc_state.set(r.pc);
+    context->pcState(pc_state);
+    context->setMiscRegNoEffect(MISCREG_CPSR, r.cpsr);
+    // Update the stack pointer. This should be done after
+    // updating CPSR/PSTATE since that might affect how SPX gets
+    // mapped.
+    context->setIntReg(INTREG_SPX, r.spx);
 
-        // FPSCR
-        gdbregs.regs32[GDB32_FPSCR] =
-            context->readMiscRegNoEffect(MISCREG_FPSCR);
+    size_t base = 0;
+    for (int i = 0; i < NumVecV8ArchRegs; i++) {
+        auto v = (context->getWritableVecReg(
+                RegId(VecRegClass, i))).as<VecElem>();
+        for (size_t j = 0; j < NumVecElemPerNeonVecReg; j++) {
+            v[j] = r.v[base];
+            base++;
+        }
     }
+    context->setMiscRegNoEffect(MISCREG_FPSR, r.fpsr);
+    context->setMiscRegNoEffect(MISCREG_FPCR, r.fpcr);
 }
 
-/*
- * Translate the GDB register format into the kernel debugger register
- * format.
- */
 void
-RemoteGDB::setregs()
+RemoteGDB::AArch32GdbRegCache::getRegs(ThreadContext *context)
 {
+    DPRINTF(GDBAcc, "getRegs in remotegdb \n");
 
-    DPRINTF(GDBAcc, "setregs in remotegdb \n");
-    if (inAArch64(context)) {  // AArch64
-        // x0-x30
-        for (int i = 0; i < 31; ++i)
-            context->setIntReg(INTREG_X0 + i, gdbregs.regs64[GDB64_X0 + i]);
-        // pc
-        context->pcState(gdbregs.regs64[GDB64_PC]);
-        // cpsr
-        context->setMiscRegNoEffect(MISCREG_CPSR, gdbregs.regs64[GDB64_CPSR]);
-        // Update the stack pointer. This should be done after
-        // updating CPSR/PSTATE since that might affect how SPX gets
-        // mapped.
-        context->setIntReg(INTREG_SPX, gdbregs.regs64[GDB64_SPX]);
-        // v0-v31
-        for (int i = 0; i < 128; i += 4) {
-            int gdboff = GDB64_V0_32 + i;
-            context->setFloatRegBits(i + 2, gdbregs.regs32[gdboff + 0]);
-            context->setFloatRegBits(i + 3, gdbregs.regs32[gdboff + 1]);
-            context->setFloatRegBits(i + 0, gdbregs.regs32[gdboff + 2]);
-            context->setFloatRegBits(i + 1, gdbregs.regs32[gdboff + 3]);
-        }
-    } else {  // AArch32
-        // R0-R15 supervisor mode
-        // arm registers are 32 bits wide, gdb registers are 64 bits wide
-        // two arm registers are packed into one gdb register (little endian)
-        context->setIntReg(INTREG_R0, gdbregs.regs32[GDB32_R0 + 0]);
-        context->setIntReg(INTREG_R1, gdbregs.regs32[GDB32_R0 + 1]);
-        context->setIntReg(INTREG_R2, gdbregs.regs32[GDB32_R0 + 2]);
-        context->setIntReg(INTREG_R3, gdbregs.regs32[GDB32_R0 + 3]);
-        context->setIntReg(INTREG_R4, gdbregs.regs32[GDB32_R0 + 4]);
-        context->setIntReg(INTREG_R5, gdbregs.regs32[GDB32_R0 + 5]);
-        context->setIntReg(INTREG_R6, gdbregs.regs32[GDB32_R0 + 6]);
-        context->setIntReg(INTREG_R7, gdbregs.regs32[GDB32_R0 + 7]);
-        context->setIntReg(INTREG_R8, gdbregs.regs32[GDB32_R0 + 8]);
-        context->setIntReg(INTREG_R9, gdbregs.regs32[GDB32_R0 + 9]);
-        context->setIntReg(INTREG_R10, gdbregs.regs32[GDB32_R0 + 10]);
-        context->setIntReg(INTREG_R11, gdbregs.regs32[GDB32_R0 + 11]);
-        context->setIntReg(INTREG_R12, gdbregs.regs32[GDB32_R0 + 12]);
-        context->setIntReg(INTREG_SP, gdbregs.regs32[GDB32_R0 + 13]);
-        context->setIntReg(INTREG_LR, gdbregs.regs32[GDB32_R0 + 14]);
-        context->pcState(gdbregs.regs32[GDB32_R0 + 7]);
+    r.gpr[0] = context->readIntReg(INTREG_R0);
+    r.gpr[1] = context->readIntReg(INTREG_R1);
+    r.gpr[2] = context->readIntReg(INTREG_R2);
+    r.gpr[3] = context->readIntReg(INTREG_R3);
+    r.gpr[4] = context->readIntReg(INTREG_R4);
+    r.gpr[5] = context->readIntReg(INTREG_R5);
+    r.gpr[6] = context->readIntReg(INTREG_R6);
+    r.gpr[7] = context->readIntReg(INTREG_R7);
+    r.gpr[8] = context->readIntReg(INTREG_R8);
+    r.gpr[9] = context->readIntReg(INTREG_R9);
+    r.gpr[10] = context->readIntReg(INTREG_R10);
+    r.gpr[11] = context->readIntReg(INTREG_R11);
+    r.gpr[12] = context->readIntReg(INTREG_R12);
+    r.gpr[13] = context->readIntReg(INTREG_SP);
+    r.gpr[14] = context->readIntReg(INTREG_LR);
+    r.gpr[15] = context->pcState().pc();
+    r.cpsr = context->readMiscRegNoEffect(MISCREG_CPSR);
 
-        //CPSR
-        context->setMiscRegNoEffect(MISCREG_CPSR, gdbregs.regs32[GDB32_CPSR]);
+    // One day somebody will implement transfer of FPRs correctly.
+    for (int i = 0; i < 32; i++)
+        r.fpr[i] = 0;
 
-        //vfpv3/neon floating point registers (32 double or 64 float)
-        for (int i = 0; i < NumFloatV7ArchRegs; ++i)
-            context->setFloatRegBits(i, gdbregs.regs32[GDB32_F0 + i]);
+    r.fpscr = context->readMiscRegNoEffect(MISCREG_FPSCR);
+}
 
-        //FPSCR
-        context->setMiscReg(MISCREG_FPSCR, gdbregs.regs32[GDB32_FPSCR]);
-    }
+void
+RemoteGDB::AArch32GdbRegCache::setRegs(ThreadContext *context) const
+{
+    DPRINTF(GDBAcc, "setRegs in remotegdb \n");
+
+    context->setIntReg(INTREG_R0, r.gpr[0]);
+    context->setIntReg(INTREG_R1, r.gpr[1]);
+    context->setIntReg(INTREG_R2, r.gpr[2]);
+    context->setIntReg(INTREG_R3, r.gpr[3]);
+    context->setIntReg(INTREG_R4, r.gpr[4]);
+    context->setIntReg(INTREG_R5, r.gpr[5]);
+    context->setIntReg(INTREG_R6, r.gpr[6]);
+    context->setIntReg(INTREG_R7, r.gpr[7]);
+    context->setIntReg(INTREG_R8, r.gpr[8]);
+    context->setIntReg(INTREG_R9, r.gpr[9]);
+    context->setIntReg(INTREG_R10, r.gpr[10]);
+    context->setIntReg(INTREG_R11, r.gpr[11]);
+    context->setIntReg(INTREG_R12, r.gpr[12]);
+    context->setIntReg(INTREG_SP, r.gpr[13]);
+    context->setIntReg(INTREG_LR, r.gpr[14]);
+    auto pc_state = context->pcState();
+    pc_state.set(r.gpr[15]);
+    context->pcState(pc_state);
+
+    // One day somebody will implement transfer of FPRs correctly.
+
+    context->setMiscReg(MISCREG_FPSCR, r.fpscr);
+    context->setMiscRegNoEffect(MISCREG_CPSR, r.cpsr);
 }
 
-// Write bytes to kernel address space for debugger.
 bool
-RemoteGDB::write(Addr vaddr, size_t size, const char *data)
+RemoteGDB::getXferFeaturesRead(const std::string &annex, std::string &output)
 {
-    return BaseRemoteGDB::write(vaddr, size, data);
+#define GDB_XML(x, s) \
+        { x, std::string(reinterpret_cast<const char *>(Blobs::s), \
+        Blobs::s ## _len) }
+    static const std::map<std::string, std::string> annexMap32{
+        GDB_XML("target.xml", gdb_xml_arm_target),
+        GDB_XML("arm-core.xml", gdb_xml_arm_core),
+        GDB_XML("arm-vfpv3.xml", gdb_xml_arm_vfpv3),
+    };
+    static const std::map<std::string, std::string> annexMap64{
+        GDB_XML("target.xml", gdb_xml_aarch64_target),
+        GDB_XML("aarch64-core.xml", gdb_xml_aarch64_core),
+        GDB_XML("aarch64-fpu.xml", gdb_xml_aarch64_fpu),
+    };
+#undef GDB_XML
+    auto& annexMap = inAArch64(context()) ? annexMap64 : annexMap32;
+    auto it = annexMap.find(annex);
+    if (it == annexMap.end())
+        return false;
+    output = it->second;
+    return true;
 }
 
+BaseGdbRegCache*
+RemoteGDB::gdbRegs()
+{
+    if (inAArch64(context()))
+        return &regCache64;
+    else
+        return &regCache32;
+}