From a6464e3cbad1d704d0c2410dea676ea2676b7500 Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Sat, 6 Feb 2021 17:50:49 +0530 Subject: [PATCH] arch-power: Add multi-mode debugging support This adds multi-mode support for remote debugging via GDB with the addition of the XML target description files for both 32-bit and 64-bit variants of the Power architecture. Proper byte order conversions have also been added. Since, MSR has now been modeled to some extent, it is also exposed by getRegs() but setRegs() does not modify it. Similarly, the target descriptions require FPSCR to also be part of the payload and hence, it has been added too. Change-Id: I156fdccb791f161959dbb2c3dd8ab1e510d9cd4b Signed-off-by: Sandipan Das --- ext/gdb-xml/power-core.xml | 49 ++++++++++++++ ext/gdb-xml/power-fpu.xml | 44 ++++++++++++ ext/gdb-xml/power.xml | 92 -------------------------- ext/gdb-xml/power64-core.xml | 49 ++++++++++++++ ext/gdb-xml/powerpc-32.xml | 16 +++++ ext/gdb-xml/powerpc-64.xml | 16 +++++ src/arch/power/SConscript | 6 +- src/arch/power/remote_gdb.cc | 125 +++++++++++++++++++++++++++++------ src/arch/power/remote_gdb.hh | 37 ++++++++++- 9 files changed, 319 insertions(+), 115 deletions(-) create mode 100644 ext/gdb-xml/power-core.xml create mode 100644 ext/gdb-xml/power-fpu.xml delete mode 100644 ext/gdb-xml/power.xml create mode 100644 ext/gdb-xml/power64-core.xml create mode 100644 ext/gdb-xml/powerpc-32.xml create mode 100644 ext/gdb-xml/powerpc-64.xml diff --git a/ext/gdb-xml/power-core.xml b/ext/gdb-xml/power-core.xml new file mode 100644 index 000000000..6cf57b137 --- /dev/null +++ b/ext/gdb-xml/power-core.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/gdb-xml/power-fpu.xml b/ext/gdb-xml/power-fpu.xml new file mode 100644 index 000000000..145eede7f --- /dev/null +++ b/ext/gdb-xml/power-fpu.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/gdb-xml/power.xml b/ext/gdb-xml/power.xml deleted file mode 100644 index da5a07ca9..000000000 --- a/ext/gdb-xml/power.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - powerpc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ext/gdb-xml/power64-core.xml b/ext/gdb-xml/power64-core.xml new file mode 100644 index 000000000..cd5bc6d0e --- /dev/null +++ b/ext/gdb-xml/power64-core.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/gdb-xml/powerpc-32.xml b/ext/gdb-xml/powerpc-32.xml new file mode 100644 index 000000000..a537f927d --- /dev/null +++ b/ext/gdb-xml/powerpc-32.xml @@ -0,0 +1,16 @@ + + + + + + + + powerpc:common + + + diff --git a/ext/gdb-xml/powerpc-64.xml b/ext/gdb-xml/powerpc-64.xml new file mode 100644 index 000000000..a762f8cc2 --- /dev/null +++ b/ext/gdb-xml/powerpc-64.xml @@ -0,0 +1,16 @@ + + + + + + + + powerpc:common64 + + + diff --git a/src/arch/power/SConscript b/src/arch/power/SConscript index cf79094a7..9b297eba6 100644 --- a/src/arch/power/SConscript +++ b/src/arch/power/SConscript @@ -60,4 +60,8 @@ if env['TARGET_ISA'] == 'power': ISADesc('isa/main.isa') - GdbXml('power.xml', 'gdb_xml_power') + GdbXml('power-core.xml', 'gdb_xml_power_core') + GdbXml('power64-core.xml', 'gdb_xml_power64_core') + GdbXml('power-fpu.xml', 'gdb_xml_power_fpu') + GdbXml('powerpc-32.xml', 'gdb_xml_powerpc_32') + GdbXml('powerpc-64.xml', 'gdb_xml_powerpc_64') diff --git a/src/arch/power/remote_gdb.cc b/src/arch/power/remote_gdb.cc index d2e292e42..57a41f5cc 100644 --- a/src/arch/power/remote_gdb.cc +++ b/src/arch/power/remote_gdb.cc @@ -136,7 +136,11 @@ #include -#include "blobs/gdb_xml_power.hh" +#include "blobs/gdb_xml_power64_core.hh" +#include "blobs/gdb_xml_power_core.hh" +#include "blobs/gdb_xml_power_fpu.hh" +#include "blobs/gdb_xml_powerpc_32.hh" +#include "blobs/gdb_xml_powerpc_64.hh" #include "cpu/thread_state.hh" #include "debug/GDBAcc.hh" #include "debug/GDBMisc.hh" @@ -146,7 +150,7 @@ using namespace PowerISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc, int _port) - : BaseRemoteGDB(_system, tc, _port), regCache(this) + : BaseRemoteGDB(_system, tc, _port), regCache32(this), regCache64(this) { } @@ -170,22 +174,27 @@ RemoteGDB::PowerGdbRegCache::getRegs(ThreadContext *context) { DPRINTF(GDBAcc, "getRegs in remotegdb \n"); + Msr msr = context->readMiscRegNoEffect(MISCREG_MSR); + ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big); + // Default order on 32-bit PowerPC: // R0-R31 (32-bit each), F0-F31 (64-bit IEEE754 double), - // PC, MSR, CR, LR, CTR, XER (32-bit each) + // PC, MSR, CR, LR, CTR, XER, FPSCR (32-bit each) for (int i = 0; i < NumIntArchRegs; i++) - r.gpr[i] = htobe((uint32_t)context->readIntReg(i)); + r.gpr[i] = htog((uint32_t)context->readIntReg(i), order); for (int i = 0; i < NumFloatArchRegs; i++) r.fpr[i] = context->readFloatReg(i); - r.pc = htobe((uint32_t)context->pcState().pc()); - r.msr = 0; // Is MSR modeled? - r.cr = htobe((uint32_t)context->readMiscReg(MISCREG_CR)); - r.lr = htobe((uint32_t)context->readMiscReg(MISCREG_LR)); - r.ctr = htobe((uint32_t)context->readMiscReg(MISCREG_CTR)); - r.xer = htobe((uint32_t)context->readMiscReg(MISCREG_XER)); + r.pc = htog((uint32_t)context->pcState().pc(), order); + r.msr = htog((uint32_t)context->readMiscRegNoEffect(MISCREG_MSR), order); + r.cr = htog((uint32_t)context->readMiscRegNoEffect(MISCREG_CR), order); + r.lr = htog((uint32_t)context->readMiscRegNoEffect(MISCREG_LR), order); + r.ctr = htog((uint32_t)context->readMiscRegNoEffect(MISCREG_CTR), order); + r.xer = htog((uint32_t)context->readMiscRegNoEffect(MISCREG_XER), order); + r.fpscr = htog((uint32_t)context->readMiscRegNoEffect(MISCREG_FPSCR), + order); } void @@ -193,24 +202,90 @@ RemoteGDB::PowerGdbRegCache::setRegs(ThreadContext *context) const { DPRINTF(GDBAcc, "setRegs in remotegdb \n"); + Msr msr = context->readMiscRegNoEffect(MISCREG_MSR); + ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big); + for (int i = 0; i < NumIntArchRegs; i++) - context->setIntReg(i, betoh(r.gpr[i])); + context->setIntReg(i, gtoh(r.gpr[i], order)); for (int i = 0; i < NumFloatArchRegs; i++) context->setFloatReg(i, r.fpr[i]); - context->pcState(betoh(r.pc)); - // Is MSR modeled? - context->setMiscReg(MISCREG_CR, betoh(r.cr)); - context->setMiscReg(MISCREG_LR, betoh(r.lr)); - context->setMiscReg(MISCREG_CTR, betoh(r.ctr)); - context->setMiscReg(MISCREG_XER, betoh(r.xer)); + auto pc = context->pcState(); + pc.byteOrder(order); + pc.set(gtoh(r.pc, order)); + context->pcState(pc); + // Do not modify MSR + context->setMiscRegNoEffect(MISCREG_CR, gtoh(r.cr, order)); + context->setMiscRegNoEffect(MISCREG_LR, gtoh(r.lr, order)); + context->setMiscRegNoEffect(MISCREG_CTR, gtoh(r.ctr, order)); + context->setMiscRegNoEffect(MISCREG_XER, gtoh(r.xer, order)); + context->setMiscRegNoEffect(MISCREG_FPSCR, gtoh(r.fpscr, order)); +} + +void +RemoteGDB::Power64GdbRegCache::getRegs(ThreadContext *context) +{ + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); + + Msr msr = context->readMiscRegNoEffect(MISCREG_MSR); + ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big); + + // Default order on 64-bit PowerPC: + // GPRR0-GPRR31 (64-bit each), FPR0-FPR31 (64-bit IEEE754 double), + // CIA, MSR, CR, LR, CTR, XER, FPSCR (only CR, XER, FPSCR are 32-bit + // each and the rest are 64-bit) + + for (int i = 0; i < NumIntArchRegs; i++) + r.gpr[i] = htog(context->readIntReg(i), order); + + for (int i = 0; i < NumFloatArchRegs; i++) + r.fpr[i] = context->readFloatReg(i); + + r.pc = htog(context->pcState().pc(), order); + r.msr = htog(context->readMiscRegNoEffect(MISCREG_MSR), order); + r.cr = htog((uint32_t)context->readMiscRegNoEffect(MISCREG_CR), order); + r.lr = htog(context->readMiscRegNoEffect(MISCREG_LR), order); + r.ctr = htog(context->readMiscRegNoEffect(MISCREG_CTR), order); + r.xer = htog((uint32_t)context->readMiscRegNoEffect(MISCREG_XER), order); + r.fpscr = htog((uint32_t)context->readMiscRegNoEffect(MISCREG_FPSCR), + order); +} + +void +RemoteGDB::Power64GdbRegCache::setRegs(ThreadContext *context) const +{ + DPRINTF(GDBAcc, "setRegs in remotegdb \n"); + + Msr msr = context->readMiscRegNoEffect(MISCREG_MSR); + ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big); + + for (int i = 0; i < NumIntArchRegs; i++) + context->setIntReg(i, gtoh(r.gpr[i], order)); + + for (int i = 0; i < NumFloatArchRegs; i++) + context->setFloatReg(i, r.fpr[i]); + + auto pc = context->pcState(); + pc.byteOrder(order); + pc.set(gtoh(r.pc, order)); + context->pcState(pc); + // Do not modify MSR + context->setMiscRegNoEffect(MISCREG_CR, gtoh(r.cr, order)); + context->setMiscRegNoEffect(MISCREG_LR, gtoh(r.lr, order)); + context->setMiscRegNoEffect(MISCREG_CTR, gtoh(r.ctr, order)); + context->setMiscRegNoEffect(MISCREG_XER, gtoh(r.xer, order)); + context->setMiscRegNoEffect(MISCREG_FPSCR, gtoh(r.fpscr, order)); } BaseGdbRegCache* RemoteGDB::gdbRegs() { - return ®Cache; + Msr msr = context()->readMiscRegNoEffect(MISCREG_MSR); + if (msr.sf) + return ®Cache64; + else + return ®Cache32; } bool @@ -219,10 +294,20 @@ RemoteGDB::getXferFeaturesRead(const std::string &annex, std::string &output) #define GDB_XML(x, s) \ { x, std::string(reinterpret_cast(Blobs::s), \ Blobs::s ## _len) } - static const std::map annexMap { - GDB_XML("target.xml", gdb_xml_power), + static const std::map annexMap32{ + GDB_XML("target.xml", gdb_xml_powerpc_32), + GDB_XML("power-core.xml", gdb_xml_power_core), + GDB_XML("power-fpu.xml", gdb_xml_power_fpu) + }; + static const std::map annexMap64{ + GDB_XML("target.xml", gdb_xml_powerpc_64), + GDB_XML("power64-core.xml", gdb_xml_power64_core), + GDB_XML("power-fpu.xml", gdb_xml_power_fpu) }; #undef GDB_XML + + Msr msr = context()->readMiscRegNoEffect(MISCREG_MSR); + auto& annexMap = msr.sf ? annexMap64 : annexMap32; auto it = annexMap.find(annex); if (it == annexMap.end()) return false; diff --git a/src/arch/power/remote_gdb.hh b/src/arch/power/remote_gdb.hh index 3bb726e52..50b4f7957 100644 --- a/src/arch/power/remote_gdb.hh +++ b/src/arch/power/remote_gdb.hh @@ -49,7 +49,7 @@ class RemoteGDB : public BaseRemoteGDB { using BaseGdbRegCache::BaseGdbRegCache; private: - struct { + struct M5_ATTR_PACKED { uint32_t gpr[NumIntArchRegs]; uint64_t fpr[NumFloatArchRegs]; uint32_t pc; @@ -58,7 +58,9 @@ class RemoteGDB : public BaseRemoteGDB uint32_t lr; uint32_t ctr; uint32_t xer; + uint32_t fpscr; } r; + public: char *data() const { return (char *)&r; } size_t size() const { return sizeof(r); } @@ -71,16 +73,47 @@ class RemoteGDB : public BaseRemoteGDB } }; - PowerGdbRegCache regCache; + class Power64GdbRegCache : public BaseGdbRegCache + { + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct M5_ATTR_PACKED { + uint64_t gpr[NumIntArchRegs]; + uint64_t fpr[NumFloatArchRegs]; + uint64_t pc; + uint64_t msr; + uint32_t cr; + uint64_t lr; + uint64_t ctr; + uint32_t xer; + uint32_t fpscr; + } r; + + public: + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string + name() const + { + return gdb->name() + ".Power64GdbRegCache"; + } + }; + + PowerGdbRegCache regCache32; + Power64GdbRegCache regCache64; public: RemoteGDB(System *_system, ThreadContext *tc, int _port); BaseGdbRegCache *gdbRegs(); + std::vector availableFeatures() const { return {"qXfer:features:read+"}; }; + bool getXferFeaturesRead(const std::string &annex, std::string &output); }; -- 2.30.2